Spring的异常统一处理非常简单,首先我们需要看一下Spring中定义的HandlerExceptionResolver接口:
1. /**
2. * Interface to be implemented by objects than can resolve exceptions thrown
3. * during handler mapping or execution, in the typical case to error views.
4. * Implementors are typically registered as beans in the application context.
5. *
6. * <p>Error views are analogous to the error page JSPs, but can be used with
7. * any kind of exception including any checked exception, with potentially
8. * fine-granular mappings for specific handlers.
9. *
10. * @author Juergen Hoeller
11. * @since 22.11.2003
12. */
13. public interface HandlerExceptionResolver {
14.
15. /**
16. * Try to resolve the given exception that got thrown during on handler execution,
17. * returning a ModelAndView that represents a specific error page if appropriate.
18. * <p>The returned ModelAndView may be {@linkplain ModelAndView#isEmpty() empty}
19. * to indicate that the exception has been resolved successfully but that no view
20. * should be rendered, for instance by setting a status code.
21. * @param request current HTTP request
22. * @param response current HTTP response
23. * @param handler the executed handler, or <code>null</code> if none chosen at the
24. * time of the exception (for example, if multipart resolution failed)
25. * @param ex the exception that got thrown during handler execution
26. * @return a corresponding ModelAndView to forward to,
27. * or <code>null</code> for default processing
28. */
29. ModelAndView resolveException(
30. HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);
31.
32. }
他定义了一个resolveException方法,我们如果要处理异常的话,需要实现这个接口类,并且实现resolveException方法,在resolveException方法中处理自己的异常逻辑。
例如我设计一个自定义的异常处理类:
1. /**
2. * 自定义一个异常捕获处理类
3. * @author zhuli
4. * @date 2014-9-3
5. */
6. public class MyExceptionResolver implements HandlerExceptionResolver {
7.
8. private static final Logger logger = LoggerFactory.getLogger(MyExceptionResolver.class);
9.
10. @Override
11. public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
12.
13. //可以自由处理各种异常逻辑
14. if (ex instanceof org.springframework.web.HttpRequestMethodNotSupportedException) {
15. "Http Method Error");
16. }
17. return null;
18. }
19.
20. }
然后需要将我们的我们自定义的MyExceptionResolver类注入到bean中
1. <bean id="MyExceptionResolver" class="com.tiantian.xxx.web.handler.MyExceptionResolver"/>
具体Spring是怎么调用的?我们可以先看下Spring中的doDispatch方法中,有这么一段代码:
1. catch (ModelAndViewDefiningException ex) {
2. "ModelAndViewDefiningException encountered", ex);
3. mv = ex.getModelAndView();
4. }
5. catch (Exception ex) {
6. null ? mappedHandler.getHandler() : null);
7. mv = processHandlerException(processedRequest, response, handler, ex);
8. null);
9. }
其中processHandlerException方法就是来捕获异常处理的,那么继续看processHandlerException这个方法:
1. protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,
2. throws Exception {
3.
4. // Check registered HandlerExceptionResolvers...
5. null;
6. for (HandlerExceptionResolver handlerExceptionResolver : this.handlerExceptionResolvers) {
7. exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
8. if (exMv != null) {
9. break;
10. }
11. }
12. if (exMv != null) {
13. if (exMv.isEmpty()) {
14. return null;
15. }
16. // We might still need view name translation for a plain error model...
17. if (!exMv.hasView()) {
18. exMv.setViewName(getDefaultViewName(request));
19. }
20. if (logger.isDebugEnabled()) {
21. "Handler execution resulted in exception - forwarding to resolved error view: " + exMv, ex);
22. }
23. WebUtils.exposeErrorRequestAttributes(request, ex, getServletName());
24. return exMv;
25. }
26.
27. throw ex;
28. }
这个方法中的handlerExceptionResolver.resolveException就是用来捕获异常的,并且Spring允许多个自定义的异常类实现。
可以看this.handlerExceptionResolvers方法,跟踪进去
1. private void initHandlerExceptionResolvers(ApplicationContext context) {
2. this.handlerExceptionResolvers = null;
3.
4. if (this.detectAllHandlerExceptionResolvers) {
5. // Find all HandlerExceptionResolvers in the ApplicationContext, including ancestor contexts.
6. Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils
7. class, true, false);
8. if (!matchingBeans.isEmpty()) {
9. this.handlerExceptionResolvers = new ArrayList<HandlerExceptionResolver>(matchingBeans.values());
10. // We keep HandlerExceptionResolvers in sorted order.
11. this.handlerExceptionResolvers);
12. }
13. }
14. else {
15. try {
16. HandlerExceptionResolver her =
17. class);
18. this.handlerExceptionResolvers = Collections.singletonList(her);
19. }
20. catch (NoSuchBeanDefinitionException ex) {
21. // Ignore, no HandlerExceptionResolver is fine too.
22. }
23. }
24.
25. // Ensure we have at least some HandlerExceptionResolvers, by registering
26. // default HandlerExceptionResolvers if no other resolvers are found.
27. if (this.handlerExceptionResolvers == null) {
28. this.handlerExceptionResolvers = getDefaultStrategies(context, HandlerExceptionResolver.class);
29. if (logger.isDebugEnabled()) {
30. "No HandlerExceptionResolvers found in servlet '" + getServletName() + "': using default");
31. }
32. }
33. }
可以清洗看到这个方法是将handlerExceptionResolvers进行了初始化,并将自定义的异常处理类(可以多个)写入this.handlerExceptionResolvers