SpringMVC和Struct2的区别
共同点:
- 都是表现层框架,都是基于MVC模型编写的
- 底层都离不开ServletAPI
- 处理请求的机制是一个核心控制器
区别: - SpringMVC入口是Servlet,Struct2入口是Filter
- SpringMVC是基于方法设计的,它是单例的。Struct2是基于类设计的,是多例的,每次都会重新创建处理对象,所以每次去执行操作时,SpringMV C会比Struct2快一些。
- SpringMVC处理Ajax请求更方便。
- Struct2的OGNL表达式开发效率比SpringMVC更高,但是执行效率并没有比JSTL表达式高。
springmvc入门程序
执行流程:
完整案例:
index.jsp:
<h3>入门程序</h3>
<a href="hello">入门程序</a>
HelloController.java:
// 控制器类
@Controller
public class HelloController {
@RequestMapping(path="/hello")
public String sayHello(){
System.out.println("Hello StringMVC");
return "success";
}
}
web.xml:
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!--配置前端控制器-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--加载springmvc.xml配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!--一启动tomcat就创建DispatcherServlet对象,然后创建springmvc.xml文件-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
resources中的springmvc.xml.
<!-- 开启注解扫描 -->
<context:component-scan base-package="cn.itcast"/>
<!-- 视图解析器对象 -->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 开启SpringMVC框架注解的支持 -->
<mvc:annotation-driven/>
success.jsp:
<h3>入门成功</h3>
运行结果:
SpringMVC的消息处理流程有了解吗?(重点)
各个组件的功能:
- DispatcherServlet:前端控制器
控制整个流程的执行,调用其它组件处理用户请求 - HandlerMapping:处理器映射器
根据用户请求找到Controller类中的映射方法,如:ControllerHello类中sayHello() - HandlerAdapter:处理器适配器
处理controller类中映射方法,并返回modelandview给前端控制器 - ViewResolver:视图解析器
对modelandview进行解析,返回view - View:视图
浏览器将view渲染出来,返回给客户端
@RequestMapping注解(重点)
作用:建立请求URL和处理请求方法之间的对应关系
属性:
path==value指定映射路径的
method指定请求方式。如:GET、POST、PUT、DELETE等
eg:
@RequestMapping(value="/testRequestMapping",method = {RequestMethod.GET})
public String testRequestMapping(){
System.out.println("测试RequestMapping注解...");
return "success";
}
params指定请求参数的条件,要求请求参数的key-value和配置的一模一样
eg:
@RequestMapping(value="/testRequestMapping",params = {"username=heihei"})
public String testRequestMapping(){
System.out.println("测试RequestMapping注解...");
return "success";
}
<a href="user/testRequestMapping?username=heihei">RequestMapping注解</a>
headers:指定请求消息头
eg:
@RequestMapping(value="/testRequestMapping",headers = {"Accept"})
public String testRequestMapping(){
System.out.println("测试RequestMapping注解...");
return "success";
}
浏览器中按F12进行调试就可以看到消息头
绑定请求参数
入门级
执行流程:
param.jsp:
<a href="param/testParam?username=hehe&password=123">请求参数绑定</a>
ParamController.java:
/**
* 请求参数绑定
*/
@Controller
@RequestMapping("/param")
public class ParamController {
/**
* 请求参数绑定入门
* @return
*/
@RequestMapping("/testParam")
public String testParam(String username,String password){
System.out.println("执行了...");
System.out.println("用户名:"+username);
System.out.println("密码:"+password);
return "success";
}
运行结果:
把参数封装到javabean中的数据绑定(带有对象引用)
执行流程:
Account.java:
public class Account implements Serializable{
private String username;
private String password;
private Double money;
private User user;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String toString() {
return "Account{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", money=" + money +
", user=" + user +
'}';
}
}
User.java:
public class User implements Serializable{
private String uname;
private Integer age;
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"uname='" + uname + '\'' +
", age=" + age +
", date=" + date +
'}';
}
}
param.jsp:
<form action="param/saveAccount" method="post">
姓名:<input type="text" name="username" /><br/>
密码:<input type="text" name="password" /><br/>
金额:<input type="text" name="money" /><br/>
用户姓名:<input type="text" name="user.uname" /><br/>
用户年龄:<input type="text" name="user.age" /><br/>
<input type="submit" value="提交" />
</form>
ParamController.java:
/**
* 请求参数绑定
*/
@Controller
@RequestMapping("/param")
public class ParamController {
/**
* 请求参数绑定把数据封装到JavaBean的类中
* @return
*/
@RequestMapping("/saveAccount")
public String saveAccount(Account account){
System.out.println("执行了...");
System.out.println(account);
return "success";
}
}
运行结果:
带有集合类型的数据绑定
Account.java:
public class Account implements Serializable{
private String username;
private String password;
private Double money;
private List<User> list;
private Map<String,User> map;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
public List<User> getList() {
return list;
}
public void setList(List<User> list) {
this.list = list;
}
public Map<String, User> getMap() {
return map;
}
public void setMap(Map<String, User> map) {
this.map = map;
}
@Override
public String toString() {
return "Account{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", money=" + money +
", list=" + list +
", map=" + map +
'}';
}
}
User.java:
public class User implements Serializable{
private String uname;
private Integer age;
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"uname='" + uname + '\'' +
", age=" + age +
", date=" + date +
'}';
}
}
param.jsp:
<form action="param/saveAccount" method="post">
姓名:<input type="text" name="username" /><br/>
密码:<input type="text" name="password" /><br/>
金额:<input type="text" name="money" /><br/>
用户姓名:<input type="text" name="list[0].uname" /><br/>
用户年龄:<input type="text" name="list[0].age" /><br/>
用户姓名:<input type="text" name="map['one'].uname" /><br/>
用户年龄:<input type="text" name="map['one'].age" /><br/>
<input type="submit" value="提交" />
</form>
ParamController.java:
@RequestMapping("/saveAccount")
public String saveAccount(Account account){
System.out.println("执行了...");
System.out.println(account);
return "success";
}
运行结果:
配置解决中文乱码的过滤器
发送请求后,控制台出现乱码:
解决:
web.xml:
<!--配置解决中文乱码的过滤器-->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
解决后:
自定义类型转换器
我们在页面中输入数据时,它都是按照字符串类型进行处理的,但是我么后台中各种数据类型划分明确,它是如何将字符串类型转换成后台中对应的数据类型呢!这就是SpringMVC框架为我们做好的-----类型转换器。
但是有些类型可能框架无法转换,如:日期类型-写法2014-09-03无法转换,但是/写法可以转换2014/09/03。
这需要我们自定义类型转换器
步骤:
- 编写具有类型转换功能类
- 配置类型转换器,让前端控制器能够找到它
- 在类型转换器中注入转换功能功能类
- 让类型转换器生效
User.java:
public class User implements Serializable{
private String uname;
private Integer age;
private Date date;
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
@Override
public String toString() {
return "User{" +
"uname='" + uname + '\'' +
", age=" + age +
", date=" + date +
'}';
}
}
param.jsp:
<form action="param/saveUser" method="post">
用户姓名:<input type="text" name="uname" /><br/>
用户年龄:<input type="text" name="age" /><br/>
用户生日:<input type="text" name="date" /><br/>
<input type="submit" value="提交" />
</form>
ParamController.java:
@Controller
@RequestMapping("/param")
public class ParamController {
/**
* 自定义类型转换器
* @param user
* @return
*/
@RequestMapping("/saveUser")
public String saveUser(User user){
System.out.println("执行了...");
System.out.println(user);
return "success";
}
}
类型转换代码:
/**
* 把字符串转换日期
*/
public class StringToDateConverter implements Converter<String,Date>{
/**
* String source 传入进来字符串
* @param source
* @return
*/
public Date convert(String source) {
// 判断
if(source == null){
throw new RuntimeException("请您传入数据");
}
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
try {
// 把字符串转换日期
return df.parse(source);
} catch (Exception e) {
throw new RuntimeException("数据类型转换出现错误");
}
}
}
springmvc.xml:
<!--配置自定义类型转换器-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="cn.itcast.utils.StringToDateConverter"/>
</set>
</property>
</bean>
<!-- 让类型转换器生效 -->
<mvc:annotation-driven conversion-service="conversionService"/>
SpringMVC常用注解(重点)
- @RequestParam
作用:把请求中指定名称的参数给控制器中形参赋值
使用地方:方法形参上
属性:
value==name指定参数的名称
required指定请求参数中是否必须提供参数,默认值为true。
anno.jsp:
<a href="anno/testRequestParam?dname=哈哈">RequestParam</a>
AnnoController.java:
运行结果:
@requestparam案例再重现
@requestparam案例再现
- @RequestBody
作用:获取请求体的内容,得到的是key=value&key=value…结构的数据
使用地方:方法形参上
属性:
required指定是否必须有请求体,默认值为true
细节:对GET请求方式没用
<form action="anno/testRequestBody" method="post">
用户姓名:<input type="text" name="username" /><br/>
用户年龄:<input type="text" name="age" /><br/>
<input type="submit" value="提交" />
</form>
/**
* 获取到请求体的内容
* @return
*/
@RequestMapping("/testRequestBody")
public String testRequestBody(@RequestBody String body){
System.out.println("执行了...");
System.out.println(body);
return "success";
}
运行结果:
restful风格
优点:结构清晰、易于理解、方便扩展
- @PathVariable
作用:指定请求的URL路径里面的变量
使用地方:方法的形参上
属性:
name==value指定参数的名称
<a href="anno/testPathVariable/10">testPathVariable</a>
@Controller
@RequestMapping("/anno")
public class AnnoController {
/**
* PathVariable注解
* @return
*/
@RequestMapping(value="/testPathVariable/{sid}")
public String testPathVariable(@PathVariable(name="sid") String id){
System.out.println("执行了...");
System.out.println(id);
return "success";
}
}
运行结果:
- @RequestHeader
作用:获取请求头的值
使用地方:方法的形参上
属性:
value指定请求头类型,如:Accept等
<a href="anno/testRequestHeader2">RequestHeader</a>
@Controller
@RequestMapping("/anno")
public class AnnoController {
/**
* 获取请求头的值
* @param header
* @return
*/
@RequestMapping(value="/testRequestHeader2")
public String testRequestHeader2(@RequestHeader(value="Accept") String header){
System.out.println("执行了...");
System.out.println(header);
return "success";
}
}
运行结果:
-
@RequestAttribute
作用:获取request请求域中的值
作用地方:方法的形参上
属性:required 指定是否必须有请求域,默认值是true
-
@CookieValue
作用:用于把指定的cookie名称值给控制器方法形参赋值
使用地方:方法的形参上
属性:
value指定参数名,如:JSESSIONID
anno.jsp:
<a href="anno/testCookieValue">CookieValue</a>
AnnoController.java:
@Controller
@RequestMapping("/anno")
public class AnnoController {
/**
* 获取Cookie的值
* @return
*/
@RequestMapping(value="/testCookieValue")
public String testCookieValue(@CookieValue(value="JSESSIONID") String cookieValue){
System.out.println("执行了...");
System.out.println(cookieValue);
return "success";
}
}
运行结果:
- @ModelAttribute
作用:出现在方法上,表示当前方法会在控制器方法执行之前先执行
出现在参数上,获取指定的数据给参数赋值
出现位置:方法上和参数上都可以
执行流程:
@ModelAttribute注解修饰的方法有返回值
anno.jsp:
<form action="anno/testModelAttribute" method="post">
用户姓名:<input type="text" name="uname" /><br/>
用户年龄:<input type="text" name="age" /><br/>
<input type="submit" value="提交" />
</form>
@Controller
@RequestMapping("/anno")
public class AnnoController {
/**
* ModelAttribute注解
* @return
*/
@RequestMapping(value="/testModelAttribute")
public String testModelAttribute( User user){
System.out.println("testModelAttribute执行了...");
System.out.println(user);
return "success";
}
// 该方法会先执行
@ModelAttribute
public User showUser(String uname){
System.out.println("showUser执行了...");
// 通过用户查询数据库(模拟)
User user = new User();
user.setUname(uname);
user.setAge(20);
user.setDate(new Date());
return user;
}
}
运行结果:
@ModelAttribute注解修饰的方法没有返回值(用在参数上)
执行流程:
anno.jsp:
<form action="anno/testModelAttribute" method="post">
用户姓名:<input type="text" name="uname" /><br/>
用户年龄:<input type="text" name="age" /><br/>
<input type="submit" value="提交" />
</form>
AnnoController.java:
@Controller
@RequestMapping("/anno")
public class AnnoController {
/**
* ModelAttribute注解
* @return
*/
@RequestMapping(value="/testModelAttribute")
public String testModelAttribute(@ModelAttribute("abc") User user){
System.out.println("testModelAttribute执行了...");
System.out.println(user);
return "success";
}
@ModelAttribute
public void showUser(String uname, Map<String,User> map){
System.out.println("showUser执行了...");
// 通过用户查询数据库(模拟)
User user = new User();
user.setUname(uname);
user.setAge(20);
user.setDate(new Date());
map.put("abc",user);
}
}
- @SessionAttributes
作用:用于多次执行控制器方法间参数共享
使用地方:类上
属性:value==names指定request域中的key
在页面中获取session域中数据:
执行流程:
anno.jsp:
<a href="anno/getSessionAttributes">getSessionAttributes</a>
<a href="anno/delSessionAttributes">delSessionAttributes</a>
<a href="anno/testSessionAttributes">testSessionAttributes</a>
AnnoController.java:
@Controller
@RequestMapping("/anno")
@SessionAttributes(value={"msg"}) // 把msg=美美存入到session域对中
public class AnnoController {
/**
* 把数据存储到request域中
* @return
*/
@RequestMapping(value="/testSessionAttributes")
public String testSessionAttributes(Model model){
System.out.println("testSessionAttributes...");
// 把数据存储到request域中
model.addAttribute("msg","美美");
return "success";
}
/**
* 获取到session域中数据
* @param modelMap
* @return
*/
@RequestMapping(value="/getSessionAttributes")
public String getSessionAttributes(ModelMap modelMap){
System.out.println("getSessionAttributes...");
String msg = (String) modelMap.get("msg");
System.out.println(msg);
return "success";
}
/**
* 清除session域中的数据
* @param status
* @return
*/
@RequestMapping(value="/delSessionAttributes")
public String delSessionAttributes(SessionStatus status){
System.out.println("getSessionAttributes...");
status.setComplete();
return "success";
}
}
在页面中取出session域中的数据
success.jsp:
<h3>入门成功</h3>
${sessionScope}
运行结果:
响应之返回值是字符串类型
执行流程:
浏览器发送请求>>>后台查出数据,存到model对象中,然后存到request域中>>>跳转页面,将request域中数据取出来
response.jsp:
<a href="user/testString" >testString</a>
UserController.java:
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/testString")
public String testString(Model model){
System.out.println("testString方法执行了...");
// 模拟从数据库中查询出User对象
User user = new User();
user.setUsername("美美");
user.setPassword("123");
user.setAge(30);
// model对象
model.addAttribute("user",user);
return "success";
}
}
success.jsp:
<h3>执行成功</h3>
${user.username}
${user.password}
${user.age}
运行结果:
响应之返回值是ModelAndView类型
同返回值是字符串类型
<a href="user/testModelAndView" >testModelAndView</a>
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
// 创建ModelAndView对象
ModelAndView mv = new ModelAndView();
System.out.println("testModelAndView方法执行了...");
// 模拟从数据库中查询出User对象
User user = new User();
user.setUsername("小凤");
user.setPassword("456");
user.setAge(30);
// 把user对象存到ModelAndView对象中,然后会存储到request域中
mv.addObject("user",user);
// 跳转到哪个页面
mv.setViewName("success");
return mv;
}
}
<h3>执行成功</h3>
${user.username}
${user.password}
${user.age}
运行结果:
响应之返回值是void类型
项目目录结构:
- 请求转发
<a href="user/testVoid" >testVoid</a>
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/testVoid")
public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("testVoid方法执行了...");
// 编写请求转发的程序
request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
return;
}
}
运行结果:
- 重定向
<a href="user/testVoid" >testVoid</a>
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/testVoid")
public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("testVoid方法执行了...");
// 重定向
response.sendRedirect(request.getContextPath()+"/index.jsp");
System.out.println(request.getContextPath());
return;
}
}
运行结果:
- 直接进行相应
执行流程:
设置编码格式>>>设置浏览器解析格式和字符集>>>直接进行响应
<a href="user/testVoid" >testVoid</a>
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/testVoid")
public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("testVoid方法执行了...");
// 设置中文乱码
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
// 直接会进行响应
response.getWriter().print("你好");
return;
}
}
运行结果:
请求转发和重定向的区别(重点)
- 请求转发:
request.getRequestDispatcher(URL).forward(request,response);
处理流程:
1.客户端发送请求,servlet做出业务逻辑处理
2.servlet调用forward方法,服务器把目标资源返回给客户端
- 重定向
response.sendRedirect(URL地址)
处理流程:
1.客户端发送请求,servlet做出业务逻辑处理
2.servlet调用sendRedirect()方法,把要访问的目标资源作为响应头返回给客户端
3.客户端再次访问服务器的xxx.jsp页面,服务器再次对客户端做出响应
区别:
1.请求转发在服务器内部转发,整个过程处于同一个请求中
2.重定向则是完全的跳转,浏览器会得到跳转后的地址,重新发送请求,整个过程处于两个请求中
3.请求转发中数据的存取可以使用request域:request.setAttribute(),request.getAttribute(),重定向是取不到request域的,只能使用session
4.请求转发在服务器内部进行,不能跨域、重定向可以跨域
Ajax请求之异步请求(补)
响应json数据之发送Ajax请求
页面发送ajax请求,后端拿到数据,并打印出来
response.jsp:
<script>
// 页面加载,绑定单击事件
$(function(){
$("#btn").click(function(){
// alert("hello btn");
// 发送ajax请求
$.ajax({
// 编写json格式,设置属性和值
url:"user/testAjax",
contentType:"application/json;charset=UTF-8",
data:'{"username":"hehe","password":"123","age":30}',
dataType:"json",
type:"post",
});
});
});
</script>
UserController.java:
@Controller
@RequestMapping("/user")
public class UserController {
/**
* 模拟异步请求响应
*/
@RequestMapping("/testAjax")
public void testAjax(@RequestBody String body){
System.out.println("testAjax方法执行了...");
System.out.println(body);// 做响应,模拟查询数据库
}
}
运行结果:
响应json数据之响应json格式数据
页面发送ajax请求,传的是json字符串数据,后端拿到json字符串数据给封装到user对象中,@ResponseBody把user对象转成json字符串数据再返回给页面。
response.jsp:
// 页面加载,绑定单击事件
$(function(){
$("#btn").click(function(){
// alert("hello btn");
// 发送ajax请求
$.ajax({
// 编写json格式,设置属性和值
url:"user/testAjax",
contentType:"application/json;charset=UTF-8",
data:'{"username":"hehe","password":"123","age":30}',
dataType:"json",
type:"post",
success:function(data){
// data服务器端响应的json的数据,进行解析
alert(data);
alert(data.username);
alert(data.password);
alert(data.age);
}
});
});
});
UserController.java:
@Controller
@RequestMapping("/user")
public class UserController {
/**
* 模拟异步请求响应
* @ResponseBody把user对象转成json字符串数据返回给页面
*/
@RequestMapping("/testAjax")
public @ResponseBody User testAjax(@RequestBody User user){
System.out.println("testAjax方法执行了...");
// 客户端发送ajax的请求,传的是json字符串,后端把json字符串封装到user对象中
System.out.println(user);
// 做响应,模拟查询数据库
user.setUsername("haha");
user.setAge(40);
// 做响应
return user;
}
}
运行结果:
文件上传
传统方式上传
执行流图:
index.jsp:
<form action="user/fileupload1" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload" /><br/>
<input type="submit" value="上传" />
</form>
UserController.java:
@Controller
@RequestMapping("/user")
public class UserController {
/**
* 文件上传
* @return
*/
@RequestMapping("/fileupload1")
public String fileuoload1(HttpServletRequest request) throws Exception {
System.out.println("文件上传...");
// 使用fileupload组件完成文件上传
// 上传的位置
String path = request.getSession().getServletContext().getRealPath("/uploads/");
// 判断,该路径是否存在
File file = new File(path);
if(!file.exists()){
// 创建该文件夹
file.mkdirs();
}
// 解析request对象,获取上传文件项
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
// 解析request
List<FileItem> items = upload.parseRequest(request);
// 遍历
for(FileItem item:items){
// 进行判断,当前item对象是否是上传文件项
if(item.isFormField()){
// 说明普通表单向
}else{
// 说明上传文件项
// 获取上传文件的名称
String filename = item.getName();
// 把文件的名称设置唯一值,uuid
String uuid = UUID.randomUUID().toString().replace("-", "");
filename = uuid+"_"+filename;
// 完成文件上传
item.write(new File(path,filename));
// 删除临时文件
item.delete();
}
}
return "success";
}
}
运行结果:
Springmvc框架文件上传
原理图:
springmvc.xml:
<!--配置文件解析器对象-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--字节单位-->
<property name="maxUploadSize" value="10485760" />
</bean>
UserController.java:
@Controller
@RequestMapping("/user")
public class UserController {
/**
* SpringMVC文件上传
* @return
*/
@RequestMapping("/fileupload2")
public String fileuoload2(HttpServletRequest request, MultipartFile upload) throws Exception {
System.out.println("springmvc文件上传...");
// 使用fileupload组件完成文件上传
// 上传的位置
String path = request.getSession().getServletContext().getRealPath("/uploads/");
// 判断,该路径是否存在
File file = new File(path);
if(!file.exists()){
// 创建该文件夹
file.mkdirs();
}
// 说明上传文件项
// 获取上传文件的名称
String filename = upload.getOriginalFilename();
// 把文件的名称设置唯一值,uuid
String uuid = UUID.randomUUID().toString().replace("-", "");
filename = uuid+"_"+filename;
// 完成文件上传
upload.transferTo(new File(path,filename));
return "success";
}
}
跨服务器上传
图片经过应用服务器,上传到图片服务器
index.jsp:
<form action="user/fileupload3" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload" /><br/>
<input type="submit" value="上传" />
</form>
UserController.java:
@Controller
@RequestMapping("/user")
public class UserController {
/**
* 跨服务器文件上传
* @return
*/
@RequestMapping("/fileupload3")
public String fileuoload3(MultipartFile upload) throws Exception {
System.out.println("跨服务器文件上传...");
// 定义上传文件服务器路径
String path = "http://localhost:9090/uploads/";
// 说明上传文件项
// 获取上传文件的名称
String filename = upload.getOriginalFilename();
// 把文件的名称设置唯一值,uuid
String uuid = UUID.randomUUID().toString().replace("-", "");
filename = uuid+"_"+filename;
// 创建客户端的对象
Client client = Client.create();
// 和图片服务器进行连接
WebResource webResource = client.resource(path + filename);
// 上传文件
webResource.put(upload.getBytes());
return "success";
}
}
springmvc异常处理
步骤:
1.编写自定义异常类(做提示信息的)
2.编写异常处理器代码
3.配置异常处理器(前端控制器能够找到它)
执行流图:
自定义异常类:
public class SysException extends Exception{
// 存储提示信息的
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public SysException(String message) {
this.message = message;
}
}
异常处理器:
public class SysExceptionResolver implements HandlerExceptionResolver{
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
// 获取到异常对象
SysException e = null;
if(ex instanceof SysException){
e = (SysException)ex;
}else{
e = new SysException("系统正在维护....");
}
// 创建ModelAndView对象
ModelAndView mv = new ModelAndView();
mv.addObject("errorMsg",e.getMessage());
mv.setViewName("error");
return mv;
}
}
index.jsp:
<h3>异常处理</h3>
<a href="user/testException" >异常处理</a>
UserController.java:
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/testException")
public String testException() throws SysException {
System.out.println("testException执行了...");
try {
// 模拟异常
int a = 10/0;
} catch (Exception e) {
// 打印异常信息
e.printStackTrace();
// 抛出自定义异常信息
throw new SysException("查询所有用户出现错误了...");
}
return "success";
}
}
springmvc.xml:
<!--配置异常处理器-->
<bean id="sysExceptionResolver" class="cn.itcast.exception.SysExceptionResolver"/>
error.jsp:
${errorMsg}
运行结果:
拦截器
作用:用于对处理器(Controller类中的方法)进行预处理和后处理
拦截器和过滤器的区别
1.过滤器是servelt规范的一部分,任何javaweb工程都能使用
2.拦截器是springmvc框架自己的,只有使用springmvc框架工程才能使用
3.过滤器在url-pattern中配置/*,可以对所有要访问的资源进行拦截
4.拦截器只会拦截要访问的控制器中的方法(Controller类中的方法),对于jsp、html、js、css、image等无法拦截
步骤:
1.编写拦截器类,实现HandlerInterceptor接口
2.配置拦截器,并在其中注册拦截器对象
执行流图:
index.jsp:
<h3>拦截器</h3>
<a href="user/testInterceptor" >拦截器</a>
拦截器:
public class MyInterceptor1 implements HandlerInterceptor{
/*
* 预处理,controller方法执行前
* return true 放行,执行下一个拦截器,如果没有,执行controller中的方法
* return false不放行
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor1执行了...前1111");
return true;
}
springmvc.xml:
<!--配置拦截器-->
<mvc:interceptors>
<!--配置拦截器-->
<mvc:interceptor>
<!--要拦截的具体的方法-->
<mvc:mapping path="/user/*"/>
<!--不要拦截的方法
<mvc:exclude-mapping path=""/>
-->
<!--配置拦截器对象-->
<bean class="cn.itcast.controller.cn.itcast.interceptor.MyInterceptor1" />
</mvc:interceptor>
</mvc:interceptors>
UserController.java:
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/testInterceptor")
public String testInterceptor(){
System.out.println("testInterceptor执行了...");
return "success";
}
}
success.jsp:
<h3>执行成功</h3>
运行结果:
拦截器接口(HandlerInterceptor)中的方法
preHandler()预处理方法,在Controller类方法执行之前执行,可以提前跳转到其他页面
postHandler()后处理方法,在控制类方法执行之后和页面跳转之前执行,同样也可以提前跳转到其他页面
afterCompletion()在整个过程执行完之后执行,不可以跳转页面
index.jsp:
<h3>拦截器</h3>
<a href="user/testInterceptor" >拦截器</a>
拦截器1:
public class MyInterceptor1 implements HandlerInterceptor{
/**
* 预处理,controller方法执行前
* return true 放行,执行下一个拦截器,如果没有,执行controller中的方法
* return false不放行
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor1执行了...前1111");
request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
return true;
}
/**
* 后处理方法,controller方法执行后,success.jsp执行之前
*/
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor1执行了...后1111");
request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
}
/**
* success.jsp页面执行后,该方法会执行
*/
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor1执行了...最后1111");
}
}
拦截器2:
public class MyInterceptor2 implements HandlerInterceptor{
/**
* 预处理,controller方法执行前
* return true 放行,执行下一个拦截器,如果没有,执行controller中的方法
* return false不放行
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor1执行了...前2222");
request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
return true;
}
/**
* 后处理方法,controller方法执行后,success.jsp执行之前
*/
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor1执行了...后2222");
request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
}
/**
* success.jsp页面执行后,该方法会执行
*/
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor1执行了...最后2222");
}
}
处理器:
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/testInterceptor")
public String testInterceptor(){
System.out.println("testInterceptor执行了...");
return "success";
}
}
springmvc.xml:
<!--配置拦截器-->
<mvc:interceptors>
<!--配置拦截器-->
<mvc:interceptor>
<!--要拦截的具体的方法-->
<mvc:mapping path="/user/*"/>
<!--不要拦截的方法
<mvc:exclude-mapping path=""/>
-->
<!--配置拦截器对象-->
<bean class="cn.itcast.controller.cn.itcast.interceptor.MyInterceptor1" />
</mvc:interceptor>
<!--配置第二个拦截器-->
<mvc:interceptor>
<!--要拦截的具体的方法-->
<mvc:mapping path="/**"/>
<!--不要拦截的方法
<mvc:exclude-mapping path=""/>
-->
<!--配置拦截器对象-->
<bean class="cn.itcast.controller.cn.itcast.interceptor.MyInterceptor2" />
</mvc:interceptor>
</mvc:interceptors>
success.jsp:
<h3>执行成功</h3>
运行结果: