19

Spring MVC 异常处理机制

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzI0NTc5Mzk4MQ%3D%3D&%3Bmid=2247483902&%3Bidx=1&%3Bsn=680316920333abd8a187051b44584e6d
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

在Spring MVC中,当一个请求发生异常(Controller抛出一个异常时), DispatcherServlet 采用委托的方式交给一个处理链来处理或者解析这个抛出的异常,这是在request和Servlet Container之间的一道屏障,所以我们可以在这里做一些处理工作,如转换异常,转换成友好的error page或者http 状态码等。

核心接口

这个处理机制在Spring是以 HandlerExceptionResolver 接口为核心的,该接口只有一个处理方法:

ModelAndView resolveException(

HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);

对于返回值 ModelAndView,有如下约定:

  • ModelAndView 指向一个页面

  • 空的ModelAndView,表示异常已经在 HandlerExceptionResolver内部处理完成

  • null表示异常未处理,需要继续执行其它的HandlerExceptionResolver

你可以通过声明多个HandlerExceptionResolver bean,并实现Ordered接口,来组成一个有顺序的HandlerExceptionResolver chain来处理异常。

Spring已经提供了以下几种实现:

  • SimpleMappingExceptionResolver 处理逻辑是根据Exception的class name映射成指定的error page。

  • DefaultHandlerExceptionResolver 是根据异常的类型转成http 状态码。

  • ResponseStatusExceptionResolver 是根据把异常和状态码通过@ResponseStatus绑定,当有异常抛出时,最终给客户端返回对应的状态码。

  • ExceptionHandlerExceptionResolver 是处理@ExceptionHandler的解析类,当有异常发生时,交给@ExceptionHandler方法去处理。

处理逻辑

对ExceptionResolver的处理是在DispatcherServlet中进行的

DispatcherServlet有一个属性,这就表示前边提到的chain:

/** List of HandlerExceptionResolvers used by this servlet */

private List<HandlerExceptionResolver> handlerExceptionResolvers;

在DispatcherServlet初始化的时候同时对handlerExceptionResolvers进行了初始化

EruY7zM.jpg!web

它从ApplicationContext中查询所有HandlerExceptionResolver bean,然后排序,上边这就是初始化工作.

在processHandlerException方法完成的对 HandlerExceptionResolver chain的调用,返回值不为null,即视作处理完成

// Check registered HandlerExceptionResolvers...

ModelAndView exMv = null;

for (HandlerExceptionResolver handlerExceptionResolver : this.handlerExceptionResolvers) {

exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);

if (exMv != null) {

break;

}

}

自定义异常处理器,可以实现HandlerExceptionResolver,也可以继承AbstractHandlerExceptionResolver类,实现doResolveException方法即可。

这里重点说下功能最为丰富的ExceptionHandlerExceptionResolver

通过@ExceptionHandler注解的方法,被视为异常处理方法,是通过ExceptionHandlerExceptionResolver来处理。 该方法支持的参数类型有:

  • Exception

  • Request/Response

  • Session

  • WebRequest or NativeRequest

  • java.util.Locale

  • java.io.InputStream / java.io.Reader 

  • java.io.OutputStream / java.io.Writer

  • org.springframework.ui.Model 

支持的返回值类型有:

  • ModelAndView object (Servlet MVC or Portlet MVC).

  • org.springframework.ui.Model 

  • java.util.Map object for exposing a model

  • org.springframework.web.servlet.View.

  • String value which is interpreted as view name.

  • @ResponseBody  可以通过message converters 搭配内容协商来转换消息体.

  • HttpEntity<?> or ResponseEntity<?> 

  • void 如果直接通过Response回写消息流,则该方法可以返回void

@ExceptionHandler搭配 @ControllerAdvice使用,可作为全局异常处理器

@ControllerAdvice

public class GlobalExceptionController {

@ExceptionHandler(CustomGenericException.class)

public ModelAndView handleCustomException(CustomGenericException ex) {

ModelAndView model = new ModelAndView("error/error");

model.addObject("code”, ex.getErrCode());

model.addObject(“msg”, ex.getErrMsg());

return model;

}

@ExceptionHandler(Exception.class)

public ModelAndView handleAllException(Exception ex) {

ModelAndView model = new ModelAndView("error/error");

model.addObject(“msg”, "this is Exception.class");

return model;

}

}

以上便是Spring MVC中的异常处理逻辑,如有不对的地方,欢迎拍砖。

SpringAutowired

nU3Ibiy.jpg!web3u2uYv6.png!web

长按,识别二维码,加关注


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK