1、HandlerExceptionResolver

Spring HandlerExceptionResolver的实现们会处理controller执行过程中发送的unexpected exceptions。

一个HandlerExceptionResolver类似于你这web.xml中定义的exception mappings。然而,它们提供了更具弹性的方式。例如,它们提供了抛出exception时正在执行的handler的信息。更多地,编码式处理exceptions给予你更多的选择,可以在request被forwarded到另一个URL之前进行合适的处理。

除了实现HandlerExceptionResolver接口(具体来说就是实现resolveException(Exception, Handler) 方法,返回一个ModelAndView )外,你还可以使用SimpleMappingExceptionResolver或者创建@ExceptionHandler methods。前者可以让你获取可能被抛出的任意exception的class name,并将其映射到一个view name。其功能等效于Servlet API中的exception mapping feature,但可以实现更细化的exceptions mappings (来自不同handlers)。@ExceptionHandler注解可被用于methods,会被调用来处理一个exception。 这种方法可以定义在@Controller内部,或者定义在@ControllerAdvice class内--这样会适用于很多@Controller classes。 后面会详述。

2、@ExceptionHandler

HandlerExceptionResolver接口和SimpleMappingExceptionResolver实现们允许你声明式地将Exceptions映射到特定的views -- 还可以在forward到这些views之前进行一些逻辑操作。然而,在某些情况下,特别是在依赖于@ResponseBody methods而不是view resolution时,直接设置response status、将error content写入response body更为方便。

你可以使用@ExceptionHandler methods来完成。 当在一个controller内部声明了这种方法后,这种方法就会被用于该controller(或任意子类)中@RequestMapping methods抛出的exceptions。你也可以在一个@ControllerAdvice class中定义一个@ExceptionHandler method,这种情况下I安,他会处理很多controllers的@RequestMapping methods抛出的异常。

下面是controller本地的@ExceptionHandler method:

@Controller
public class SimpleController { // @RequestMapping methods omitted ... @ExceptionHandler(IOException.class)
public ResponseEntity<String> handleIOException(IOException ex) {
// prepare responseEntity
return responseEntity;
} }

注意,@ExceptionHandler的value可以是Exception类型的数组。只要被抛出的异常匹配了该数组中的任意一个,该方法就会被调用。如果该注解的value没有被设置,那么异常类型就是方法的参数类型。

很像标准controller 的@RequestMapping methods,@ExceptionHandler methods的方法参数和返回值是很灵活的。 例如,在Servlet环境下可以使用HttpServletRequest,而在Porlet环境下可以使用PortletRequest。 返回类型可以是String -- 会被解释成view name,也可以是ModelAndView对象、ResponseEntity,或者使用@ResponseBody将返回值转成String并写入response stream。

3、处理标准的Spring MVC Exceptions

在处理一个请求时,Spring MVC 可能抛出大量异常。 SimpleMappingExceptionResolver 可以轻易地将任何异常按照需要映射到默认的error view。然而,当clients以自动方式解析响应时,你会希望设置特定的response status code。 这些状态码可以区分client error (4xx) 或 server error (5xx)。

DefaultHandlerExceptionResolver 会将Spring MVC exceptions 翻译成特定的error status codes。 MVC namespace、MVC Java  config、还有DispatcherServlet(当不使用MVC namespace 或 Java config时)会默认注册该功能。

下面列出了一些由该resolver处理的exceptions和相应的status code。

Exception HTTP Status Code

BindException

400 (Bad Request)

ConversionNotSupportedException

500 (Internal Server Error)

HttpMediaTypeNotAcceptableException

406 (Not Acceptable)

HttpMediaTypeNotSupportedException

415 (Unsupported Media Type)

HttpMessageNotReadableException

400 (Bad Request)

HttpMessageNotWritableException

500 (Internal Server Error)

HttpRequestMethodNotSupportedException

405 (Method Not Allowed)

MethodArgumentNotValidException

400 (Bad Request)

MissingPathVariableException

500 (Internal Server Error)

MissingServletRequestParameterException

400 (Bad Request)

MissingServletRequestPartException

400 (Bad Request)

NoHandlerFoundException

404 (Not Found)

NoSuchRequestHandlingMethodException

404 (Not Found)

TypeMismatchException

400 (Bad Request)

DefaultHandlerExceptionResolver 会悄悄的工作:设置response的status code。然而,它没有将任何error content写入到response body 的功能-- 当你希望给每个error response添加一些开发者友好的内容时,它无能为力。这时,你可以准备一个ModelAndView,然后通过view resolution来render content -- 就是说,通过配置一个ContentNegotiatingViewResolver、MappingJackson2JsonView等等view resolution来完成。然而,你可能更倾向于使用@ExceptionHandler method。

如果你倾向于使用@ExceptionHandler methods来写入error content,你可以继承ResponseEntityExceptionHandler。这对于需要提供一个@ExceptionHandler method来处理标准的Spring MVC exceptions并返回ResponseEntity的@ControllerAdvice classes来说,是一个很方便的base。它可以允许你定制response,并通过message converter来写入error content。 详见其javadocs。

4、使用@ResponseStatus来注解业务异常 (Business Exceptions)

业务异常可以使用@ResponseStatus来注解。 当该异常被抛出时,ResponseStatusExceptionResolver会设置其response status。 DispatcherServlet默认注册了ResponseStatusExceptionResolver,所以直接可用。

5、定制Default Servlet Container Error page

当response status被设置成一个error status code,且response body为空时,Servlet Container通常会render一个HTML格式的error page。想要定制container默认的error page,你可以在web.xml中声明一个<error-page>元素。一直到Servlet 3 (不包含),该元素都是被映射到一个特定的status code或exception type。但从Servlet 3 开始,error page不需要被映射了,这意味着指定的位置会定制默认的Servlet Container error page。

<error-page>
<location>/error</location>
</error-page>

注意,该error page的实际位置可以是一个JSP page,或者container包含的其他URL -- 只要是通过一个@Controller method处理的URL即可:

当写入error information时,可以之一个controller中通过request attributes来访问HttpServletResponse中设置好的status code和error message:

@Controller
public class ErrorController { @RequestMapping(path = "/error", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public Map<String, Object> handle(HttpServletRequest request) { Map<String, Object> map = new HashMap<String, Object>();
map.put("status", request.getAttribute("javax.servlet.error.status_code"));
map.put("reason", request.getAttribute("javax.servlet.error.message")); return map;
} }

或者,在一个JSP中:

<%@ page contentType="application/json" pageEncoding="UTF-8"%>
{
status:<%=request.getAttribute("javax.servlet.error.status_code") %>,
reason:<%=request.getAttribute("javax.servlet.error.message") %>
}

官方文档连接:http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-exceptionhandlers

Spring 4 官方文档学习(十一)Web MVC 框架之异常处理的更多相关文章

  1. Spring 4 官方文档学习(十一)Web MVC 框架之配置Spring MVC

    内容列表: 启用MVC Java config 或 MVC XML namespace 修改已提供的配置 类型转换和格式化 校验 拦截器 内容协商 View Controllers View Reso ...

  2. Spring 4 官方文档学习(十一)Web MVC 框架之resolving views 解析视图

    接前面的Spring 4 官方文档学习(十一)Web MVC 框架,那篇太长,故另起一篇. 针对web应用的所有的MVC框架,都会提供一种呈现views的方式.Spring提供了view resolv ...

  3. Spring 4 官方文档学习(十一)Web MVC 框架

    介绍Spring Web MVC 框架 Spring Web MVC的特性 其他MVC实现的可插拔性 DispatcherServlet 在WebApplicationContext中的特殊的bean ...

  4. Spring 4 官方文档学习(十二)View技术

    关键词:view technology.template.template engine.markup.内容较多,按需查用即可. 介绍 Thymeleaf Groovy Markup Template ...

  5. Spring Boot 官方文档学习(一)入门及使用

    个人说明:本文内容都是从为知笔记上复制过来的,样式难免走样,以后再修改吧.另外,本文可以看作官方文档的选择性的翻译(大部分),以及个人使用经验及问题. 其他说明:如果对Spring Boot没有概念, ...

  6. Spring boot官方文档学习(一)

    个人说明:本文内容都是从为知笔记上复制过来的,样式难免走样,以后再修改吧.另外,本文可以看作官方文档的选择性的翻译(大部分),以及个人使用经验及问题. 其他说明:如果对Spring Boot没有概念, ...

  7. Spring Framework 官方文档学习(四)之Validation、Data Binding、Type Conversion(二)

    接前一篇 Spring Framework 官方文档学习(四)之Validation.Data Binding.Type Conversion(一) 本篇主要内容:Spring Type Conver ...

  8. Spring Framework 官方文档学习(四)之Validation、Data Binding、Type Conversion

    本篇太乱,请移步: Spring Framework 官方文档学习(四)之Validation.Data Binding.Type Conversion(一) 写了删删了写,反复几次,对自己的描述很不 ...

  9. Spring Framework 官方文档学习(四)之Validation、Data Binding、Type Conversion(一)

    题外话:本篇是对之前那篇的重排版.并拆分成两篇,免得没了看的兴趣. 前言 在Spring Framework官方文档中,这三者是放到一起讲的,但没有解释为什么放到一起.大概是默认了读者都是有相关经验的 ...

  10. Spring 4 官方文档学习(十一)Web MVC 框架之编码式Servlet容器初始化

    在Servlet 3.0+ 环境中,你可以编码式配置Servlet容器,用来代替或者结合 web.xml文件.下面是注册DispatcherServlet : import org.springfra ...

随机推荐

  1. bzoj3745: [Coci2015]Norma

    Description Input 第1行,一个整数N: 第2~n+1行,每行一个整数表示序列a. Output 输出答案对10^9取模后的结果. 预处理每个位置的数作为最小/大值向左延伸的最大距离, ...

  2. 短作业优先调度算法(SJF)

    假设有n项作业位于就绪队列中,这些作业的提交时间用数组requestTimes按照提交时间的先后顺序存储,对应的作业服务时间(持续时间)用数组durations存储.采用SJF算法,计算n项作业的平均 ...

  3. 大型博彩公司招聘 .net,DB,tester,android

    大型博彩公司招聘 .net,DB,tester,android,ios等. 等拿完年终奖的朋友,可以先发简历给我,先面试,年后上班. emai:sjchen1203@126.com 要求: 1. 全职 ...

  4. CGContextAddArcToPoint和CGContextAddArc

    比较难的是CGContextAddArcToPoint 代码如下: CGContextRef context=UIGraphicsGetCurrentContext(); CGContextSetRG ...

  5. Oracle EBS Java Applet报错:找不到类

    Oracle EBS Home Page可以打开,但是无法打开EBS的Form,查看Java控制台,有错误报出. java控制台报错,如下: Java Plug-in 1.6.0_07 使用 JRE ...

  6. HDU2047

    http://acm.hdu.edu.cn/showproblem.php?pid=2047 对于这道题,我就从后面向前面考虑. 当第n个是o的话,那么n-1 只可以取e或者f,如果n是e或者f的话, ...

  7. C语言初始化——bss段初始化、跃入C、C与汇编

    1.bss段初始化 变量 存放位置 初始化的全局变量 数据段 局部变量 栈 malloc函数分配的 堆 未初始的全局变量 bss段 说明:全局变量在未赋初值时,会被保留到bss段. 测试: #incl ...

  8. Qlikview List控件

    将纵向展示变为横向展示 方法: ListBox属性分页,“外观”分页“单列”属性不要打钩,用鼠标调整控件高度,Listbox控件会自适应现实将数据打横现实.

  9. 各种数据库分页sql

    1.oracle数据库分页 select * from (select a.*,rownum rc from 表名 where rownum<=endrow) a where a.rc>= ...

  10. Address already in use的解决方法

    当客户端保持着与服务器端的连接,这时服务器端断开,再开启服务器时会出现: Address already in usr. 可以用netstat -anp | more 可以看到客户端还保持着与服务器的 ...