SpringMVC异常处理核心接口 - HandlerExceptionResolver接口 三个实现
org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
ExceptionHandlerExceptionResolver:该类主要处理Controller中用@ExceptionHandler注解定义的方法。该类也是
DefaultHandlerExceptionResolver:
ResponseStatusExceptionResolver:
为什么ExceptionHandlerExceptionResolver、DefaultHandlerExceptionResolver、ResponseStatusExceptionResolver是
RootBeanDefinition exceptionHandlerExceptionResolver = new RootBeanDefinition(ExceptionHandlerExceptionResolver.class);
exceptionHandlerExceptionResolver.setSource(source);
exceptionHandlerExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
exceptionHandlerExceptionResolver.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
exceptionHandlerExceptionResolver.getPropertyValues().add("messageConverters", messageConverters);
exceptionHandlerExceptionResolver.getPropertyValues().add("order", 0);
String methodExceptionResolverName = parserContext.getReaderContext().registerWithGeneratedName(exceptionHandlerExceptionResolver);
RootBeanDefinition responseStatusExceptionResolver = new RootBeanDefinition(ResponseStatusExceptionResolver.class);
responseStatusExceptionResolver.setSource(source);
responseStatusExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
responseStatusExceptionResolver.getPropertyValues().add("order", 1);
String responseStatusExceptionResolverName = parserContext.getReaderContext().registerWithGeneratedName(responseStatusExceptionResolver);
RootBeanDefinition defaultExceptionResolver = new RootBeanDefinition(DefaultHandlerExceptionResolver.class);
defaultExceptionResolver.setSource(source);
defaultExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
defaultExceptionResolver.getPropertyValues().add("order", 2);
String defaultExceptionResolverName = parserContext.getReaderContext().registerWithGeneratedName(defaultExceptionResolver);
ExceptionHandlerExceptionResolver处理过程总结一下:根据用户调用Controller中相应的方法得到HandlerMethod,之后构造ExceptionHandlerMethodResolver,构造ExceptionHandlerMethodResolver有2种选择,
通过HandlerMethod拿到Controller,找出Controller中带有@ExceptionHandler注解的方法(局部) 找到@ControllerAdvice注解配置的类中的@ExceptionHandler注解的方法(全局)。这2种方式构造的ExceptionHandlerMethodResolver中都有1个key为Throwable,value为Method的缓存。之后通过发生的异常找出对应的Method,然后调用这个方法进行处理。这里异常还有个优先级的问题,比如发生的是NullPointerException,但是声明的异常有Throwable和Exception,这时候ExceptionHandlerMethodResolver找Method的时候会根据异常的最近继承关系找到继承深度最浅的那个异常,即Exception
ResponseStatusExceptionResolver 主要在异常及异常父类中找到@ResponseStatus注解。@ResponseStatus注解 让1个方法或异常有状态码(status)和理由(reason)返回。这个状态码是http响应的状态码。
DefaultHandlerExceptionResolver 如果有些异常比如NoSuchRequestHandlingMethodException会发生404错误。没配置@ExceptionHandler以及该异常没有@ResponseStatus注解,最终由DefaultHandlerExceptionResolver解析
全局@ExceptionHandler注解的异常处理handler
@ControllerAdvice
public class CustomizeExceptionHandler {
private Logger logger = LoggerFactory.getLogger(CustomizeExceptionHandler.class);
@ExceptionHandler(value={RuntimeException.class, Exception.class})
public Map<String, Object> returnNoPage(Throwable ex) {
logger.error("", ex);
Map<String, Object> responseMap = new HashMap<String, Object>();
responseMap.put("status", "false");
responseMap.put("message", ex.getMessage());
return responseMap;
}
}
SpringMVC中TestController
@RequestMapping("/test")
@Controller
public class TestController {
@RequestMapping("/exception")
public void testException() {
throw new NullPointerException();
}
}
在浏览器上输入 http://localhost:8080/test/exception.json 结果会以json数据返回,返回如下
{ "message":null, "status":"1" }
在浏览器上输入http://localhost:8080/test/exception 结果会以html返回,将跳入到错误页面
© 2015 Morly Tang. All Rights Reserved.
版权归属:寂寞的男人