SpringMVC高级特性
- SpringMVC三种处理资源方式
- Json数据交互
- Springmvc处理异常方式
- 文件上传下载
一、SpringMVC的拦截规则
昨天我们将SpringMVC拦截后缀设置为*.form
代表SpringMVC会拦截*.form
结尾的后缀
SpringMVC提供的拦截规则:
*.form
:代表以*.form
结尾的后缀请求都会进入springmvc管理
/:代表除了JSP以外拦截所有,html、css、js等静态web资源也会拦截
String contentType = request.getContentType(); System.out.println(contentType); System.out.println(user); return user; }
测试json对象自动封装数据(post)
前端:
$("#test6").click(function () {
var json = {username: "dfbz", password: "admin"};
$.ajax({
url: "/demo5_7.form",
type: "post",
//请求头类型设置为默认的(不写也可以post默认就是application../x-www...)
contentType:"application/x-www-form-urlencoded; charset=UTF-8",
data: json, //传递json对象
success: function (data) {
alert(data);
alert(JSON.stringify(data));
}
});
});
后台:
@RequestMapping(value = "/demo5_7")
@ResponseBody
public User demo5_7(User user, HttpServletRequest request) throws IOException { //map转json对象
String contentType = request.getContentType();
System.out.println(contentType);
System.out.println(user);
return user;
}
测试json字符串自动封装数据
前端:
$("#test6").click(function () {
var json = {username: "dfbz", password: "admin"};
$.ajax({
url: "/demo5_6.form",
type: "post", //提交方式必须使用post
//提交json字符串自动封装必须使用application/json
contentType:"application/json;charset=utf8",
data: JSON.stringify(json),
success: function (data) {
alert(data);
alert(JSON.stringify(data));
}
});
});
后台:
@RequestMapping(value = "/demo5_6")
@ResponseBody
public User demo5_6(@RequestBody User user) {
return user;
}
小结:我们只要记住get一般是用于查询的,因此只要封装基本数据类型就可以,post一般做添加的因此需要封装Java对象
@RequestBody:强制封装,只能用于前端提交json字符串的,而且提交类型必须是application/json;charset=utf8
,提交类型必须是Post(因为get的提交类型为null)
自动封装:用于前端提交key=val&key=val
类型的数据,提交方式为get或者post+提交类型application/x-www-form-urlencoded;
3. 表单序列化
有时候我们也需要使用ajax提交整个表单的数据,如果将整个表单的数据手动拼接为json对象未免太过麻烦,好在jquery有帮我们提供一个表单序列化方法(serialize),将整个表单的数据序列化为key1=val1&key2=val2
这样的格式,加上我们前面学过的知识可以使用ajax将整个表单的数据提交到后台并能自动封装了!
前端:
<form action="/demo5_7.form" id="mainForm" >
<input type="text" name="username">
<input type="text" name="password">
</form>
<button id="test6">ajax提交表单数据</button>
<script> $("#test6").click(function () { $.ajax({ url: "/demo5_7.form", type: "post", data: $("#mainForm").serialize(), //序列化表单数据 success: function (data) { alert(data); alert(JSON.stringify(data)); } }) }); </script>
后端:
@RequestMapping(value = "/demo5_7")
@ResponseBody
public User demo5_7(User user, HttpServletRequest request) throws IOException {
System.out.println(user);
return user;
}
三、SpringMVC的异常处理方式
1.单个异常处理方式
package com.dfbz.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class Demo2Controller {
@RequestMapping("/demo2_1")
@ResponseBody
public String test1() {
System.out.println("东方");
int i = 1 / 0;
System.out.println("标准");
return "你好好";
}
@ExceptionHandler(ArithmeticException.class)
public String test2(Model model, Exception e) {
model.addAttribute("error", e.getMessage());
System.out.println("出现异常啦!");
return "error";
}
}
2. 全局异常处理方式
需要我们编写一个类实现HandlerExceptionResolver接口
定义全局异常:
package com.dfbz.exception;
import com.dfbz.controller.Demo2Controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
public class MyExceptionHandler implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(
HttpServletRequest request,
HttpServletResponse response,
Object obj,
Exception e) {
HandlerMethod method= (HandlerMethod) obj;
ModelAndView mav=new ModelAndView();
mav.setViewName("error");
mav.addObject("error",e.getMessage());
return mav;
}
}
注入到IOC容器中:
<!--把异常类注入IOC容器-->
<bean class="com.dfbz.exception.MyExceptionHandler" />
测试controller:
@RequestMapping("/demo2_1")
@ResponseBody
public String test1() {
System.out.println("东方");
int i = 1 / 0;
System.out.println("标准");
return "你好好";
}
注意:方法处理异常优先级比全局异常高!如果进入了方法处理异常则不会进入全局异常方法中!
注解方式实现全局异常
使用@ControllerAdvice
注解可以配置全局异常
@ExceptionHandler()
:设置什么异常才会进入方法
package com.dfbz.exception;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
@ControllerAdvice //全局异常注解
public class AnnoMyExceptionHandler {
@ExceptionHandler(value = Exception.class) //传入什么异常需要进入此方法
public ModelAndView resolveException(Exception e) {
ModelAndView mav=new ModelAndView();
mav.setViewName("error");
mav.addObject("error",e.getMessage());
return mav;
}
}
3. SpringMVC提供的处理方式
只需要在spring.xml配置文件中定义即可,适合全局处理简单的异常,缺点不能自定义异常信息
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<!-- <prop key="java.lang.ArithmeticException">/jsp/error.jsp</prop>-->
<!--已经配置了视图解析器-->
<prop key="java.lang.ClassCastException">index</prop>
<prop key="java.lang.ArithmeticException">error</prop>
</props>
</property>
</bean>
4. 框架底层异常和无法捕获的异常处理方案
在web.xml文件中定义此类的处理方法
<!--如果程序出现Throwable异常则会跳转到/index.jsp页面-->
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/index.jsp</location>
</error-page>
<error-page>
<!--如果页面出现404则跳转到/success.jsp页面-->
<error-code>404</error-code>
<location>/success.jsp</location>
</error-page>
四、上传下载的实现
1.文件上传
SpringMVC支持文件上传组件
commons-fileupload组件.
commons-fileupload依赖commons-io组件.
1.1 文件上传开发流程
a.编写form表单 表单必须是post请求方式,enctype必须是multipart/form-data
(默认值是:application/x-www-form-urlencoded)
b.配置文件上传解析器 bean的名字不能写错,一定是multipartResolver
c.在controller中编写处理文件上传的方法,参数为MultipartFile
1.2 配置步骤
1.2.1.导入依赖
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
1.2.2. 前端页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--
文件上传enctype类型必须是multipart/form-data
提交方式必须是post
--%>
<form action="/upload" enctype="multipart/form-data" method="post">
<input type="file" name="file">
<input type="submit">
</form>
</body>
</html>
1.2.3. controller
@RequestMapping("/upload")
public String upload(HttpServletRequest request, MultipartFile file) throws IOException { //变量名一定要和前端提交的name一致
String fileName = file.getOriginalFilename();
String realPath = request.getRealPath("upload"); //获取服务器端某个文件夹的绝对路径
file.transferTo(new File(realPath +"/"+ UUID.randomUUID().toString() + fileName));
return "success";
}
1.2.4. dispatcher-servlet.xml配置
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--默认文件最大大小,单位b-->
<property name="maxUploadSize" value="20000000"></property>
</bean>
注意:
因为核心控制器对上传解释器的名字是固定的. 是multipartResolver,所以我们配置上传解释器,名字必须是multipartResolver
查询核心控制器DispacherServlet代码,发现multipartResolver一个固定加载的属性。
public class DispatcherServlet extends FrameworkServlet {
public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver";
如图所示
1.3. 多文件上传
前端页面
<h3>多文件上传</h3>
<form action="/uploads" enctype="multipart/form-data" method="post">
<input type="file" name="files">
<input type="file" name="files">
<input type="file" name="files">
<input type="file" name="files">
<input type="submit">
</form>
controller
@RequestMapping("/uploads")
public String uploads(HttpServletRequest request, MultipartFile[] files) throws IOException { //变量名一定要和前端提交的name一致
String realPath = request.getRealPath("upload"); //获取服务器端某个文件夹的绝对路径
for (MultipartFile file : files) {
String fileName = file.getOriginalFilename();
file.transferTo(new File(realPath + "/" + UUID.randomUUID().toString() + fileName));
}
return "success";
}
dispatcher-servlet.xml配置:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--默认文件最大大小,单位b-->
<property name="maxUploadSize" value="20000000"></property>
</bean>
1.3.* 多文件上传
前端页面
<h3>多文件上传</h3>
<form action="/uploads" enctype="multipart/form-data" method="post">
<input type="file" name="files">
<input type="file" name="files">
<input type="file" name="files">
<input type="file" name="files">
<input type="submit">
</form>
controller
@RequestMapping("/uploads")
public String uploads(HttpServletRequest request, MultipartFile[] files) throws IOException { //变量名一定要和前端提交的name一致
String realPath = request.getRealPath("upload"); //获取服务器端某个文件夹的绝对路径
for (MultipartFile file : files) {
String fileName = file.getOriginalFilename();
file.transferTo(new File(realPath + "/" + UUID.randomUUID().toString() + fileName));
}
return "success";
}
dispatcher-servlet.xml配置:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--默认文件最大大小,单位b-->
<property name="maxUploadSize" value="20000000"></property>
</bean>