Spring-SpringMVC-全局异常处理

Spring-SpringMVC-全局异常处理

系列文章目录

  1. Spring-IOC
  2. Spring-SpringMVC-原理
  3. Spring-拦截器
  4. Spring-SpringMVC-全局异常处理

0x01 摘要

SpringMVC全局异常处理有好几种方式,每种都有自己的应用场景,在这里做一个整理,仅供参考。

0x02 error-code方式-全局

2.1 web.xml配置

方式有两种,都是在web.xml中配置。可以通过匹配http错误代码,来进行相应的处理:

  • 直接配置异常界面
<error-page>
     <error-code>404error-code>
     <location>/WEB-INF/velocity/template/404.vmlocation>
error-page>
  • 配置异常处理url
<error-page>
     <error-code>404error-code>
     <location>/error/exception/404location>
error-page>

2.2 Controller代码

然后再在Controller中加入以下代码,可以按需加入一些逻辑:

@RequestMapping("/error/exception/404")
public String return404Vm(HttpServletRequest request,Model model){
    model.addAttribute("errorMsg", "404 not found,host:" + request.getRemoteAddr());
    return "404";
}

2.3 404界面

最后,附上简易的404界面:

<div>
    your page is 404.
    detail: ${errorMsg}
div>

2.4 小结

error-code方式配置简便,一目了然,适合处理一些固定的http的错误代码的异常。

0x03 @ExceptionHandler方式-Controller级别

3.1 Controller代码

@ExceptionHandler可以对指定的异常或者所有异常编写特定的处理逻辑。

3.1.1 处理一类异常

@ExceptionHandler单独使用时,必须和要处理的方法在一个Controller类里面。

这种配置方式处理的优先级最高,可以返回多种类型数据。下面这个例子处理CustomException,打印错误栈,并返回提示信息给客户端:

@ResponseBody
@ExceptionHandler({CustomException.class})
public String exception(CustomException e) {
    e.printStackTrace();
    return "ExceptionHandler has handled this " + e.getMessage();
}

3.1.2 处理多类异常

下面的例子将会展示处理本Controller内抛出的CustomExceptionCustom2Exception异常。

如果不指定@ExceptionHandler的value,就处理所有Exception。

注意方法内的参数,指定多个异常类时需要包括value中的参数,否则不会生效。

@ResponseBody
@ExceptionHandler(value={CustomException.class,Custom2Exception.class})
public String exception(Exception e) {
    e.printStackTrace();
    return "ExceptionHandler has handled this " + e.getMessage();
}

3.2 小结

@ExceptionHandler单独使用时,必须与需要处理异常的方法处于同一个Controller,代码侵入性高。

而且,只能处理当前Controller中的异常,代码冗余度高。

但是,请牢记一点,这种用法的处理优先级是最高的。

0x04 @ControllerAdvice + @ExceptionHandler方式-全局

这种配置方式可以在全局范围内处理异常,下面是示例代码。

4.1 异常类代码

@ControllerAdvice
public class GlobalControllerAdvice {
    private static final Logger logger = LoggerFactory
            .getLogger(AControllerAdvice.class);
    /**
     * 处理NullPointerException,并返回错误信息字符串
     * @param ex
     * @return
     */
    @ExceptionHandler(NullPointerException.class)
    @ResponseBody
    public String handleIOException(NullPointerException ex) {
        return  ex.getMessage();
    }

    /**
     * 处理IOException,并返回502错误, 即"Bad Gateway"
     * @param ex
     * @return
     */
    @ExceptionHandler(IOException.class)
    @ResponseStatus(HttpStatus.BAD_GATEWAY)
    public void handleIOException(IOException ex) {

    }

    /**
     * 处理Custom3Exception异常,并返回带指定错误消息的界面aca
     * @param ex
     * @return
     */
    @ExceptionHandler(Custom3Exception.class)
    public ModelAndView handleCustom3Exception(Custom3Exception ex) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("errorMsg", "Custom3Exception=" + ex.getMessage());
        modelAndView.setViewName("aca");
        return modelAndView;
    }

    /**
     * 处理所有Exception类型异常
     * 但请注意,如果该ControllerAdvice内已经有其他方法处理了指定异常,那就不会进入到该方法处理
     * 比如发生Custom3Exception异常,那么只会在@ExceptionHandler(Custom3Exception.class)的方法中处理
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    public ModelAndView Exception(Exception e) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("errorMsg", "服务器处理发生错误,详细信息:" + e.getMessage());
        modelAndView.setViewName("global-error");
        return modelAndView;
    }
}

4.2 spring配置

请务必保证上述使用了@ControllerAdvice注解的类被Spring容器管理。

4.3 小结

使用@ControllerAdvice的方式,优先级仅次于单独使用@ExceptionHandler方式。该方式可以全局处理异常,处理逻辑灵活,最为推荐

0x05 HandlerExceptionResolver方式

5.1 实现HandlerExceptionResolver接口

必须实现HandlerExceptionResolver接口,重写resolveException方法,可以按需加入一些逻辑:

public class GlobalExceptionResolver implements HandlerExceptionResolver
{

    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
    {
        ModelAndView modelAndView = new ModelAndView();

        //设置默认错误界面
        modelAndView.setViewName("/default-error");

        //传入错误消息
        modelAndView.addObject("errorMsg", ex);

        //处理CustomException的url
        if(ex instanceof CustomException){
            modelAndView.setViewName("/custom-exception");
        }
        //处理Custom2Exception的url
        if(ex instanceof Custom2Exception){
            modelAndView.setViewName("/custom2-exception");
        }

        return modelAndView;
    }
}

5.2 applicationContext.xml配置

在applicationContext.xml中加入以下配置,向spring注册该类:

	<bean class="com.chengc.demos.web.demo1.exception.resolver.GlobalExceptionResolver"/>

5.3 小结

实现HandlerExceptionResolver接口,可以处理全局异常,配置简便。但请注意,该方法处理异常的匹配优先级最低

0xFF 参考文档

Stackoverflow-what-are-the-advantages-of-controlleradvice-over-exceptionhandler-or-handlerex

你可能感兴趣的:(spring)