zoukankan      html  css  js  c++  java
  • Spring MVC异常统一处理的三种方式

    目录

    正文

    Spring 统一异常处理有 3 种方式,分别为:

    1. 使用 @ ExceptionHandler 注解
    2. 实现 HandlerExceptionResolver 接口
    3. 使用 @controlleradvice 注解

    使用 @ ExceptionHandler 注解

    使用该注解有一个不好的地方就是:进行异常处理的方法必须与出错的方法在同一个Controller里面。使用如下:

    @Controller
    public class GlobalController {
    
       /**
         * 用于处理异常的
         * @return
         */
        @ExceptionHandler({MyException.class})
        public String exception(MyException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
            return "exception";
        }
    
        @RequestMapping("test")
        public void test() {
            throw new MyException("出错了!");
        }
    }

    可以看到,这种方式最大的缺陷就是不能全局控制异常。每个类都要写一遍。

    实现 HandlerExceptionResolver 接口

    这种方式可以进行全局的异常控制。例如:

    @Component
    public class ExceptionTest implements HandlerExceptionResolver{
    
        /**
         * TODO 简单描述该方法的实现功能(可选).
         * @see org.springframework.web.servlet.HandlerExceptionResolver#resolveException(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception)
         */
        public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
                Exception ex) {
            System.out.println("This is exception handler method!");
            return null;
        }
    }

    然后在spring配置文件中配置刚才新建的类,或者加上@Component注解。

    <!--全局异常捕捉 -->
    <bean class="com.xxx.exception.GlobalExceptionResolver" />

    注意:如果 HandlerExceptionResolver接口的实现类,要返回接口,暂定可以如下实现

        public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
                Exception ex) {
            response.setContentType("application/json;charset=UTF-8");
            response.setCharacterEncoding("UTF-8");
            try {
                response.getWriter().print(JSONString);
                response.getWriter().flush();
                response.getWriter().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    
    
    //
    
        public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
                Exception ex) {
            ModelAndView mv = new ModelAndView();
            MappingJackson2JsonView view = new MappingJackson2JsonView();
            mv.setView(view);
            mv.addObject("status", "fail");
            mv.addObject("message", "系统错误");
            return mv;
        }

    使用 @ControllerAdvice+ @ ExceptionHandler 注解

    上文说到 @ ExceptionHandler 需要进行异常处理的方法必须与出错的方法在同一个Controller里面。那么当代码加入了 @ControllerAdvice,则不需要必须在同一个 controller 中了。这也是 Spring 3.2 带来的新特性。从名字上可以看出大体意思是控制器增强。 也就是说,@controlleradvice + @ ExceptionHandler 也可以实现全局的异常捕捉。

    请确保此WebExceptionHandle 类能被扫描到并装载进 Spring 容器中。

    @ControllerAdvice
    @ResponseBody
    public class WebExceptionHandle {
        private static Logger logger = LoggerFactory.getLogger(WebExceptionHandle.class);
        /**
         * 400 - Bad Request
         */
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        @ExceptionHandler(HttpMessageNotReadableException.class)
        public ServiceResponse handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
            logger.error("参数解析失败", e);
            return ServiceResponseHandle.failed("could_not_read_json");
        }
    
        /**
         * 405 - Method Not Allowed
         */
        @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
        @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
        public ServiceResponse handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
            logger.error("不支持当前请求方法", e);
            return ServiceResponseHandle.failed("request_method_not_supported");
        }
    
        /**
         * 415 - Unsupported Media Type
         */
        @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
        @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
        public ServiceResponse handleHttpMediaTypeNotSupportedException(Exception e) {
            logger.error("不支持当前媒体类型", e);
            return ServiceResponseHandle.failed("content_type_not_supported");
        }
    
        /**
         * 500 - Internal Server Error
         */
        @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
        @ExceptionHandler(Exception.class)
        public ServiceResponse handleException(Exception e) {
            if (e instanceof BusinessException){
                return ServiceResponseHandle.failed("BUSINESS_ERROR", e.getMessage());
            }
    
            logger.error("服务运行异常", e);
            e.printStackTrace();
            return ServiceResponseHandle.failed("server_error");
        }
    }

    如果 @ExceptionHandler 注解中未声明要处理的异常类型,则默认为参数列表中的异常类型。所以还可以写成这样:

    @ControllerAdvice
    public class GlobalExceptionHandler {
    
        @ExceptionHandler()
        @ResponseBody
        String handleException(Exception e){
            return "Exception Deal! " + e.getMessage();
        }
    }

    参数对象就是 Controller 层抛出的异常对象!

    继承 ResponseEntityExceptionHandler 类来实现针对 Rest 接口 的全局异常捕获,并且可以返回自定义格式:

    @Slf4j
    @ControllerAdvice
    public class ExceptionHandlerBean  extends ResponseEntityExceptionHandler {
    
        /**
         * 数据找不到异常
         * @param ex
         * @param request
         * @return
         * @throws IOException
         */
        @ExceptionHandler({DataNotFoundException.class})
        public ResponseEntity<Object> handleDataNotFoundException(RuntimeException ex, WebRequest request) throws IOException {
            return getResponseEntity(ex,request,ReturnStatusCode.DataNotFoundException);
        }
    
        /**
         * 根据各种异常构建 ResponseEntity 实体. 服务于以上各种异常
         * @param ex
         * @param request
         * @param specificException
         * @return
         */
        private ResponseEntity<Object> getResponseEntity(RuntimeException ex, WebRequest request, ReturnStatusCode specificException) {
    
            ReturnTemplate returnTemplate = new ReturnTemplate();
            returnTemplate.setStatusCode(specificException);
            returnTemplate.setErrorMsg(ex.getMessage());
    
            return handleExceptionInternal(ex, returnTemplate,
                    new HttpHeaders(), HttpStatus.OK, request);
        }
    
    }

    以上就是 Spring 处理程序统一异常的三种方式。

    参考资料

    @ControllerAdvice + @ExceptionHandler 全局处理 Controller 层异常

    http://c.biancheng.net/view/4466.html

    转 : https://www.cnblogs.com/junzi2099/p/7840294.html

  • 相关阅读:
    oracle常规操作
    shell 的算数运算
    sed 命令小结
    swing
    索引失效
    poj--1258--Agri-Net(最小生成树)
    CodeForces--626C--Block Towers (二分)
    Codeforces--629A--Far Relative’s Birthday Cake(暴力模拟)
    Codeforces--629B--Far Relative’s Problem(模拟)
    hdoj--5104--Primes Problem(素数打表)
  • 原文地址:https://www.cnblogs.com/fps2tao/p/13526773.html
Copyright © 2011-2022 走看看