赞
踩
目录
四.处理 json 和 HttpMessageConverter
2.2@RequestBody和@ResponseBody的区别
4.3处理 JSON-底层实现(HttpMessageConverter)
1.2. 自定义的拦截器必须实现 HandlerInterceptor 接口
3.1快速入门在 springDispatcherServlet-servlet.xml
5.统一处理异常信息--SimpleMappingExceptionResolver
这个基本数据类型和字符串会进行自动转换,也没有啥好实例的,简单来说:就像我们使用年龄这个属性的时候,当我们在页面输入18,他就会自动转化为“18”,但是当我们在后台去获取的时候他又会是我们定义的Interage类型的18.这个就是基本数据类型和字符串的自动转
这些都是springmvc帮你去转化的
- @DateTimeFormat(pattern="yyyy-MM-dd")
- private Date birthday;
- @NumberFormat(pattern="###,###.##")
- private float salary;
记住需要jar包
- @NotEmpty//必须非空
- private String email;
-
- //@Range(min = 1,max = 100)
- //表示接收的age值,在 1-100之间
-
- @Range(min = 1,max = 100)
- private Integer age;
- //@NotEmpty 表示name不能为空
- //Asserts that the annotated string, collection, map or array is not {@code null} or empty.
- @NotEmpty
- private String name;
-
- @DateTimeFormat(pattern = "yyyy-MM-dd")
- private Date birthday;
-
- @NumberFormat(pattern = "###,###.##")
- private Float salary;
- /**
- * 编写方法,处理添加妖怪
- * 1. springmvc可以将提交的数据,按照参数名和对象的属性名匹配
- * 2. 直接封装到对象中->老师前面讲解模型数据时,讲过
- * String => Integer
- * 3. @Valid Monster monster :表示对monster接收的数据进行校验
- * 4. Errors errors 表示如果校验出现错误,将校验的错误信息保存 errors
- * 5. Map<String, Object> map 表示如果校验出现错误, 将校验的错误信息保存 map 同时保存monster对象
- * 6. 校验发生的时机: 在springmvc底层,反射调用目标方法时,会接收到http请求的数据,然后根据注解来进行验证
- * , 在验证过程中,如果出现了错误,就把错误信息填充errors 和 map
- *
- * @param monster
- * @return
- */
- @RequestMapping(value = "/save")
- public String save(@Valid Monster monster, Errors errors, Map<String, Object> map) {
- System.out.println("----monster---" + monster);
- //我们为了看到验证的情况,我们输出map 和 errors
- System.out.println("===== map ======");
- for (Map.Entry<String, Object> entry : map.entrySet()) {
- System.out.println("key= " + entry.getKey() + " value=" + entry.getValue());
- }
-
- System.out.println("===== errors ======");
- if (errors.hasErrors()) {//判断是否有错误
- List<ObjectError> allErrors = errors.getAllErrors();
- for (ObjectError error : allErrors) {
- System.out.println("error=" + error);
- }
- return "datavalid/monster_addUI";
- }
- return "datavalid/success";
- }
为何会需要自定义那,因为在我们前面如果输入错误后面的错误信息会是如下图这样:
所以我们需要自己设置一个自定义验证错误信息,也好让我们更加直观的看出来错误
1.5.1. 配置国际化文件 springDispatcherServlet-servlet.xml
- <bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
- <property name="order" value="99"></property>
- </bean>
- <!-- 配置国际化错误信息的资源处理 bean -->
- <bean id="messageSource" class=
- "org.springframework.context.support.ResourceBundleMessageSource">
- <!-- 配置国际化文件名字
- 如果你这样配的话,表示 messageSource 回到 src/i18nXXX.properties 去读取错误
- 信息
- -->
- <property name="basename" value="i18n"></property>
- </bean>
1.5.2创建国际化文件 D:\idea_java_projects\springmvc\src\i18n.properties
- NotEmpty.monster.name=\u7528\u6237\u540d\u4e0d\u80fd\u4e3a\u7a7a//姓名不能为空
- typeMismatch.monster.age=\u5e74\u9f84\u8981\u6c42\u5728\u0031\u002d\u0031\u0035\
- u0030\u4e4b\u95f4//生日格式不正确
- typeMismatch.monster.birthday=\u751f\u65e5\u683c\u5f0f\u4e0d\u6b63\u786e
- typeMismatch.monster.salary=\u85aa\u6c34\u683c\u5f0f\u4e0d\u6b63\u786e
1.5.3修改 monster_addUI.jsp , 回显错误信息
- <form:form action="save" method="POST" modelAttribute="monster">
- 妖怪名字: <form:input path="name"/> <form:errors path="name"/><br><br>
- 妖怪年龄~: <form:input path="age"/> <form:errors path="age"/><br><br>
- 妖怪生日: <form:input path="birthday"/> <form:errors path="birthday"/> 要求
- 以"9999-11-11"的形式<br><br>
- 妖 怪 工 资 : <form:input path="salary"/> <form:errors path="salary"/> 要 求 以
- "123,890.12"的形式<br><br>
- 电子邮件: <form:input path="email"/><br><br>
- <input type="submit" value="添加妖怪"/>
- </form:form>
- //email是string,使用@NotEmpty
- @NotEmpty//必须非空
- private String email;
-
- //@Range(min = 1,max = 100)
- //表示接收的age值,在 1-100之间
-
- @NotNull(message = "age不能为空")
- @Range(min = 1,max = 100)
- private Integer age;
- //@NotEmpty 表示name不能为空
- //Asserts that the annotated string, collection, map or array is not {@code null} or empty.
- @NotEmpty
- private String name;
-
- @NotNull(message = "生日不能为空")
- @DateTimeFormat(pattern = "yyyy-MM-dd")
- private Date birthday;
-
- @NotNull(message = "薪水不能为空")
- @NumberFormat(pattern = "###,###.##")
- private Float salary;
- //取消绑定 monster的name表单提交的值给monster.name属性
- @InitBinder
- public void initBinder(WebDataBinder webDataBinder) {
- /**
- * 解读
- * 1. 方法上需要标注 @InitBinder springmvc底层会初始化 WebDataBinder
- * 2. 调用 webDataBinder.setDisallowedFields("name") 表示取消指定属性的绑定
- * 即:当表单提交字段为 name时, 就不在把接收到的name值,填充到model数据monster的name属性
- * 3. 机制:springmvc 在底层通过反射调用目标方法时, 接收到http请求的参数和值,使用反射+注解技术
- * 取消对指定属性的填充
- * 4. setDisallowedFields支持可变参数,可以填写多个字段
- * 5. 如果我们取消某个属性绑定,验证就没有意义了,应当把验证的注解去掉, name属性会使用默认值null
- * //@NotEmpty
- * private String name;
- *
- */
- //webDataBinder.setDisallowedFields("name");
- }
* 解读 * 1. 方法上需要标注 @InitBinder springmvc底层会初始化 WebDataBinder * 2. 调用 webDataBinder.setDisallowedFields("name") 表示取消指定属性的绑定 * 即:当表单提交字段为 name时, 就不在把接收到的name值,填充到model数据monster的name属性 * 3. 机制:springmvc 在底层通过反射调用目标方法时, 接收到http请求的参数和值,使用反射+注解技术 * 取消对指定属性的填充 * 4. setDisallowedFields支持可变参数,可以填写多个字段 * 5. 如果我们取消某个属性绑定,验证就没有意义了,应当把验证的注解去掉, name属性会使用默认值null * //@NotEmpty * private String name;本身就拿不到数据了,就没有必要去验证了
-
- /**
- * @author 海绵hong
- * @version 1.0
- * 编写过滤器,处理中文乱码
- */
- public class MyCharacterFilter implements Filter {
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
-
- }
-
- @Override
- public void doFilter(ServletRequest servletRequest,
- ServletResponse servletResponse,
- FilterChain filterChain) throws IOException, ServletException {
- //这里加入对编码的处理
- servletRequest.setCharacterEncoding("utf-8");
- //放行请求,这个规则和前面讲过的java web的过滤器一样
- filterChain.doFilter(servletRequest, servletResponse);
-
- }
-
- @Override
- public void destroy() {
-
- }
- }
- <!--配置处理中文乱码的过滤器
- 拦截所有请求,处理编码, 提醒,把过滤器配置到web.xml前面
- -->
- <filter>
- <filter-name>MyCharacterFilter</filter-name>
- <filter-class>com.hong.web.filter.MyCharacterFilter</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>MyCharacterFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
我们使用Spring 提供的过滤器处理中文乱码,那样的话我们就会发现我们之前所使用的自定义过滤器需要定义utf-8这个固定的编码格式,但是我们也不知道何时需要,那么我们还要在init()中读取内容,单手Spring 提供的过滤器处理中文乱码就可以很灵活。
- <!--配置处理中文乱码的过滤器
- 拦截所有请求,处理编码, 提醒,把过滤器配置到web.xml前面
- -->
- <!-- <filter>-->
- <!-- <filter-name>MyCharacterFilter</filter-name>-->
- <!-- <filter-class>com.hong.web.filter.MyCharacterFilter</filter-class>-->
- <!-- </filter>-->
- <!-- <filter-mapping>-->
- <!-- <filter-name>MyCharacterFilter</filter-name>-->
- <!-- <url-pattern>/*</url-pattern>-->
- <!-- </filter-mapping>-->
-
-
- <!--配置Spring提供的过滤器,解决中文乱码问题-->
-
- <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>
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>json提交</title>
- <!-- 引入jquery -->
- <script type="text/javascript" src="script/jquery-3.6.0.min.js"></script>
-
- <!-- 编写jquery代码和ajax请求 -->
- <script type="text/javascript">
- $(function () {
- //给id="getJson"绑定点击事件
- $("#getJson").click(function () {
- //console.log("ok ....")
-
- var url = this.href;
- var args = {"time": new Date};//这是要发送数据,为了防止页面缓存
- $.post(
- url,
- args,
- function (data) {//data 就是返回的数据,是json格式=>如果是多个json数据,可以遍历
- console.log("dataa= ", data);
- console.log("dog.name=", data.name)
- console.log("dog.addresss=", data.address)
- },
- "json"
- );
- return false;//这里我们返回false,就不使用href默认机制
- })
-
- //绑定按钮点击事件, 提交json数据
- //springmvc 可以在在台將json轉成對象
- $("button[name='butt1']").click(function () {
- //目标:将userName 和 age 封装成json字符串,发送给目标方法
- var url = "/springmvc/save2";
- var userName = $("#userName").val();
- var age = $("#age").val();
- //将json对象转成json字符串
- var args = JSON.stringify({"userName": userName, "age": age});
- $.ajax({
- url: url,
- data: args,
- type: "POST",
- success: function (data) {
- console.log("返回的data= ", data);
- },
- //下面这个contentType参数,是指定发送数据的编码和格式
- contentType: "application/json;charset=utf-8"
- })
- })
- })
- </script>
-
- </head>
- <body>
- <h1>请求一个json数据</h1>
- <%--老师处理
- 1.当用户点击超链接时,我们发出一个ajax请求
- 2. 接收到请求后,我们查看这个数据
- 3. 使用前面讲过的jquery发出ajax请求知识
- --%>
- <a href="<%=request.getContextPath()%>/json/dog" id="getJson">点击获取json数据</a>
-
- <h1>发出一个json数据</h1>
- u:<input id="userName" type="text"><br/>
- a:<input id="age" type="text"><br/>
- <button name="butt1">添加用户</button>
-
- <h1>下载文件的测试 </h1>
- <a href="<%=request.getContextPath()%>/downFile">点击下载文件</a>
- </body>
- </html>
javabean--Dog
。。。。。
Handler
- @Controller
- public class JsonHandler {
- /**
- * 解读
- * 1. 目标方法 @ResponseBody,表返回的数据是json格式
- * 2. springmvc底层根据目标方法@ResponseBody, 返回指定格式, 根据的http请求来进行处理
- * 3. 底层原理我们在前面自定义@ResponseBody讲过, 这里原生的springmvc使用转换器
- * 4. HttpMessageConverter [一会debug]
- *
- * @return
- */
- @RequestMapping(value = "/getJson")
- //指定返回的数据格式 json ,靠这个@ResponseBody
- @ResponseBody
- public Dog getJson() {
- //创建一只狗
- Dog dog = new Dog();
- dog.setName("大黄狗");
- dog.setAddress("北京八达岭~");
- return dog;
- }
- }
@RequestBody
用法:一般放在controller层的具体请求方法的入参中。比如:
- @PostMapping("/url")
- public urlBo getUrlByPhoneNumber(@RequestBody String json,HttpServetRequest request){
- UrlBo ub=new Gson().fromJson(json,UrlBo.class);
- ....//其他处理逻辑
- }
这里的@RequestBody用于读取Http请求的body部分数据——就是我们的请求数据。比如json或者xml。然后把数据绑定到 controller中方法的参数上,这里就是String json这个入参啦~。
使用时要注意能不能用@RequestBody把request请求的数据解析,并赋给我们定义的参数上是由请求头的Content-Type的值来决定的。
当我们用get/post方式提交请求后, Content-Type的值有以下几种,分别对应能不能解析数据如下:
1.application/x-www-form-urlencoded, 可选(即非必须,因为这种情况的数据@RequestParam, @ModelAttribute也可以处理,当然@RequestBody也能处理)
2.multipart/form-data, 不能处理(即使用@RequestBody不能处理这种格式的数据)
3.其他格式(其他格式包括application/json, application/xml等),这些格式的数据,必须使用@RequestBody来处理
说明:request的body部分的数据编码格式由header部分的Content-Type指定。
@ReponseBody
用法:放在controller层的方法上,将Controller的方法返回的对象,SpringMVC会根据返回值类型(Map、Llist)找到可以处理的消息转换器,并确定结果的MediaType。返回对象、map和List结果将由MappingJackson2HttpMessageConverter处理,并且MediaType为:application/json。后面写入到Response对象的body数据区。
使用时机:
当我们想让页面知道我们返回的数据不是按照html标签的页面来解析,而是其他某种格式的数据解析时(如json、xml等)使用。
例如:
- @RequestMapping("/getList")
- @ResponseBody
- public Map<String,Object> getStudentList(HtppServletRequest request){
- Map<String,Object> map=new HashMap<String,Object>();
- Dto dto=getParamAsDto(request);
- List li=studentAction.getList(dto.get("age"));
- map.put("studentInfo",li);
- }
1. 使用 HttpMessageConverter<T> 将请求信息转化并绑定到处理方法的入参中, 或将响应结果转为对应类型的响应信息,Spring 提供了两种途径:
√ 使用 @RequestBody / @ResponseBody 对目标方法进行标注
- <h1>下载文件的测试 </h1>
- <a href="<%=request.getContextPath()%>/downFile">点击下载文件</a>
- //响应用户下载文件的请求
- @RequestMapping(value = "/downFile")
- public ResponseEntity<byte[]> downFile(HttpSession session)
- throws Exception {
-
-
- //1. 先获取到下载文件的inputStream
- InputStream resourceAsStream =
- session.getServletContext().getResourceAsStream("/img/2.jpg");
-
- //2. 开辟一个存放文件的byte数组, 这里使用byte[] 是可以支持二进制数据(图片,视频。)
- byte[] bytes = new byte[resourceAsStream.available()];
- //3. 将下载文件的数据,读入到byte[]
- resourceAsStream.read(bytes);
-
- //public ResponseEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers, HttpStatus status) {}
- //4. 创建返回的HttpStatus
- HttpStatus httpStatus = HttpStatus.OK;
- //5. 创建 headers
- HttpHeaders headers = new HttpHeaders();
- //指定返回的数据,客户端应当以附件形式处理
- headers.add("Content-Disposition", "attachment;filename=2.jpg");
- // 文件下载响应头的设置
- // content-type 指示响应内容的格式
- // content-disposition 指示如何处理响应内容。
- // 一般有两种方式:
- // inline:直接在页面显示
- // attchment:以附件形式下载
-
- //构建一个ResponseEntity 对象1. 的http响应头headers 2. http响应状态 3. 下载的文件数据
- ResponseEntity<byte[]> responseEntity =
- new ResponseEntity<>(bytes, headers, httpStatus);
- //如果出现找不到文件,解决方法 rebuild project -> 重启tomcat
- return responseEntity;
- }
-
- /**
- * @author 海绵hong
- * @version 1.0
- * 处理文件上传的handler
- */
- @Controller
- public class FileUploadHandler {
-
- //编写方法,处理文件上传的请求
-
- @RequestMapping(value = "/fileUpload")
- public String fileUpload(@RequestParam(value = "file") MultipartFile file,
- HttpServletRequest request, String introduce) throws IOException {
-
- //接收到提交的文件名
- String originalFilename = file.getOriginalFilename();
- System.out.println("你上传的文件名= " + originalFilename);
- System.out.println("introduce=" + introduce);
- //得到要把上传文件保存到哪个路径[全路径:包括文件名]
- String fileFullPath =
- request.getServletContext().getRealPath("/img/" + originalFilename);
- //创建文件
- File saveToFile = new File(fileFullPath);
- //将上传的文件,转存到saveToFile
- file.transferTo(saveToFile);
- return "success";
-
- }
● 自定义拦截器执行流程说明1. 如果 preHandle 方法 返回 false, 则不再执行目标方法 , 可以在此指定返回页面2. postHandle 在目标方法被执行后执行 . 可以在方法中访问到目标方法返回的 ModelAndView 对象3. 若 preHandle 返回 true, 则 afterCompletion 方法 在渲染视图之后被执行 .4. 若 preHandle 返回 false, 则 afterCompletion 方法不会被调用5. 在配置拦截器时,可以指定该拦截器对哪些请求生效,哪些请求不生效
配置自定义拦截器
- <!--配置自定义拦截器-spring配置文件-->
- <mvc:interceptors>
- <!--
- 解读
- 1. 第一种配置方式
- 2. 使用ref 引用到对应的myInterceptor01
- 3. 这种方式,会拦截所有的目标方法
- -->
- <!--<ref bean="myInterceptor01"/>-->
-
- <!--解读
- 1. 第二种配置方式
- 2. mvc:mapping path="/hi" 指定要拦截的路径
- 3. ref bean="myInterceptor01" 指定对哪个拦截器进行配置
- -->
- <!--<mvc:interceptor>-->
- <!-- <mvc:mapping path="/hi"/>-->
- <!-- <ref bean="myInterceptor01"/>-->
- <!--</mvc:interceptor>-->
-
- <!--解读
- 1. 第3种配置方式
- 2. mvc:mapping path="/h*" 通配符方式 表示拦截 /h 打头的路径
- 3. mvc:exclude-mapping path="/hello" /hello不拦截
- 4. ref bean="myInterceptor01" 指定对哪个拦截器配置
- -->
- <mvc:interceptor>
- <mvc:mapping path="/h*"/>
- <mvc:exclude-mapping path="/hello"/>
- <ref bean="myInterceptor01"/>
- </mvc:interceptor>
自定义过滤器
-
- @Component
- public class MyInterceptor01 implements HandlerInterceptor {
-
- /**
- * 解读
- * 1. preHandle() 在目标方法执行前被执行
- * 2. 如果preHandle() 返回false , 不再执行目标方法
- * 3. 该方法可以获取到request, response, handler
- * 4. 这里根据业务,可以进行拦截,并指定跳转到哪个页面
- * @param request
- * @param response
- * @param handler
- * @return
- * @throws Exception
- */
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- System.out.println("--MyInterceptor01--preHandle()---");
- //获取到用户提交的关键字
- String keyword = request.getParameter("keyword");
- if("病毒".equals(keyword)) {
- //请求转发到warning
- request.getRequestDispatcher("/WEB-INF/pages/warning.jsp")
- .forward(request,response);
-
- return false;
- }
- System.out.println("得到到keyword= "+ keyword);
- return true;
- }
-
- /**
- * 解读
- * 1. 在目标方法执行后,会执行postHandle
- * 2. 该方法可以获取到 目标方法,返回的ModelAndView对象
- * @param request
- * @param response
- * @param handler
- * @param modelAndView
- * @throws Exception
- */
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
- System.out.println("--MyInterceptor01--postHandle()--");
- }
-
- /**
- * 解读
- * 1. afterCompletion() 在视图渲染后被执行, 这里可以进行资源清理工作
- * @param request
- * @param response
- * @param handler
- * @param ex
- * @throws Exception
- */
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
- System.out.println("--MyInterceptor01--afterCompletion()--");
- }
- }
Handler方法
- @Controller
- public class FurnHandler {
-
- @RequestMapping(value = "/hi")
- public String hi(User user) {
-
- System.out.println("---FurnHandler--hi()---");
- return "success";
- }
-
- @RequestMapping(value = "/hello")
- public String hello() {
- System.out.println("---FurnHandler--hello()---");
- return "success";
- }
-
- @RequestMapping(value = "/ok")
- public String ok() {
- System.out.println("---FurnHandler--ok()---");
- return "success";
- }
- }
- <mvc:interceptor>
- <mvc:mapping path="/hi"/>
- <ref bean="myInterceptor01"/>
- </mvc:interceptor>
- <mvc:interceptor>
- <mvc:mapping path="/h*"/>
- <mvc:exclude-mapping path="/hello"/>
- <ref bean="myInterceptor01"/>
- </mvc:interceptor>
先去配置文件中寻找拦截的页面,然后进入到preHandle(),接着到目标方法,并在这个时间将对象填充到目标方法,在之后就是postHandle()方法,这个时候该方法里面的modelAndView中存储着之前的对象(换句话说就是在这个地方你可以去改变你的值),在之后就是执行资源清理工作的afterCompletion()登场了
根据配置顺序,先配置那个就先执行那个 。如果有有一个方法在执行的时候,有两个拦截器。
这个我就叫hong(),拦截器有a,b两个,a在前。
当有请求需要这个拦截器的时候,会先去执行a的preHandle()如果为true就继续执行b的preHandle(),当执行目标方法之后就会继续去执行b的post()方法,然后再就是a的post。然后就会继续渲染视图(因为这两个方法a,b已经把modelAndView进行了二次渲染,这个时候需要的话也可以进行二次修改)在之后就是执行b的after()最后才是a的after()。就是挑明说a配置顺序在前所以第一个就是它,但之后全部都是b先执行
再建立一个拦截器
@Component public class MyInterceptor02 implements HandlerInterceptor {}
配置文件配置顺序(在第一个的后面接上的)
- <!--解读
- 1.配置的第二个拦截器
- 2.多个拦截器在执行时,是顺序执行
- -->
- <mvc:interceptor>
- <mvc:mapping path="/h*"/>
- <ref bean="myInterceptor02"/>
- </mvc:interceptor>
- </mvc:interceptors>
基本步骤:
先执行页面请求,在页面中有handler之后,会去执行handler当我们的handler出现我们自定义的异常之后@ExceptionHandler(),这个框号中有的异常。我们就会去去执行这个注解下面的方法。
- /**
- * 解读
- * 1. localException 方法处理局部异常
- * 2. 这里处理ArithmeticException.class,NullPointerException.class异常
- * 3. Exception ex: 生成的异常对象,会传递给ex, 通过ex可以得到相关的信息
- * , 这里程序员可以加入自己的业务逻辑
- * @return
- */
- @ExceptionHandler({ArithmeticException.class,NullPointerException.class,NumberFormatException.class})
- public String localException(Exception ex, HttpServletRequest request){
- System.out.println("局部异常信息是-" + ex.getMessage());
- //如何将异常的信息带到下一个页面.
- request.setAttribute("reason", ex.getMessage());
- return "exception";
- }
- <%-- Created by IntelliJ IDEA.
- User: 海绵hong
- Version: 1.0
- Filename: exception
- --%>
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>异常提示信息</title>
- </head>
- <body>
- <h1>朋友,发生异常,信息如下 :</h1>
- ${reason }
- </body>
- </html>
- /**
- * 如果类上标注了@ControllerAdvice,就是一个全局异常处理类
- */
- @ControllerAdvice
- public class MyGlobalException {
-
- /**
- * 解读
- * 1. 全局异常就不管是哪个Handler抛出的异常,都可以捕获 , @ExceptionHandler({异常类型})
- * 2. 这里处理的全局异常是NumberFormatException.class,ClassCastException.class
- * 3. Exception ex 接收抛出的异常对象
- *
- * @return
- */
- //
- @ExceptionHandler({NumberFormatException.class, ClassCastException.class})
- public String globalException(Exception ex, HttpServletRequest request) {
- System.out.println("全局异常处理-" + ex.getMessage());
- //如何将异常的信息带到下一个页面.
- request.setAttribute("reason", ex.getMessage());
- return "exception";
- }
-
- }
- @RequestMapping(value = "/testGlobalException")
- public String global(){
- //解读
- //1. 这里我们模拟了一个异常 NumberFormatException
- //2. 该异常没有在局部异常处理,按照异常处理机制,就会交给全局异常处理类处理
- int num = Integer.parseInt("hello");
- return "success";
- }
被@ControllerAdvice标注的类就是全局异常类。局部异常在handler中,但是全局异常在全局异常处理类
- @ResponseStatus(reason = "年龄需要在1-120之间", value = HttpStatus.BAD_REQUEST)
- public class AgeException extends RuntimeException {
-
- public AgeException() {
- }
-
- public AgeException(String message) {
- super(message);
- }
- }
- @RequestMapping(value = "/testException02")
- public String test02(){
-
- throw new AgeException("年龄必须在1-120之间~~~");
- }
当然当我们将自定义异常写入全局异常也是可以被接管的
@ExceptionHandler({NumberFormatException.class, ClassCastException.class, AgeException.class})
- @RequestMapping(value = "/testException03")
- public String test03(){
- int[] arr = new int[]{3,9,10,190};
- //抛出一个数组越界的异常 ArrayIndexOutOfBoundsException
- System.out.println(arr[90]);
- return "success";
- }
- <bean>
- class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
- <property name="exceptionMappings">
- <props>
- <prop key="java.lang.ArrayIndexOutOfBoundsException">arrEx</prop>
- </props>
- </property>
- </bean>
- <!-- 加入两个常规配置 -->
- <!-- 能支持 SpringMVC 高级功能,比如 JSR303 校验,映射动态请求 -->
- <mvc:annotation-driven></mvc:annotation-driven>
- <!-- 将 SpringMVC 不能处理的请求交给 Tomcat, 比如请求 css,js 等-->
- <mvc:default-servlet-handler/>
- //如果发生了没有归类的异常, 可以给出统一提示页面
- @RequestMapping(value = "/testException04")
- public String test04(){
- String str = "hello";
- //这里会抛出 StringIndexOutOfBoundsException
- char c = str.charAt(10);
- return "success";
- }
- <!-- 配置一个统一异常处理 -->
- <bean
- class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
- <property name="exceptionMappings">
- <props>
- <prop key="java.lang.ArrayIndexOutOfBoundsException">arrEx</prop>
- <prop key="java.lang.Exception">otherEx</prop>
- </props>
- </property>
- </bean>
异常处理的优先级
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。