zoukankan      html  css  js  c++  java
  • SpringBoot定义全局统一业务异常,且处理filter里面的异常

    定义统一异常类:BusinessException.java

    package com.miaoying;
    
    import lombok.Data;
    
    @Data
    public class BusinessException extends RuntimeException {
    
        /**
         * 错误码
         */
        private Integer code;
    
        /**
         * 错误信息
         */
        private String message;
    
        public BusinessException(Integer code, String message) {
            super(message);
            this.code = code;
            this.message = message;
        }
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
    
            BusinessException that = (BusinessException) o;
    
            if (!code.equals(that.code)) return false;
            return message.equals(that.message);
    
        }
    
        @Override
        public int hashCode() {
            int result = code != null ? code.hashCode() : 0;
            result = 31 * result + (message != null ? message.hashCode() : 0);
            return result;
        }
    }

    定义统一的数据返回的结构:ResultResponse<T>.java

    package com.miaoying;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    import java.io.Serializable;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class ResultResponse<T> implements Serializable {
    
        private static final long serialVersionUID = 5261844042861308860L;
        private int retCode;
    
        private String retMsg;
    
        private T rsp;
    
        public static <T> ResultResponse<T> wrapSuccessfulResult(T data) {
            ResultResponse<T> result = new ResultResponse<T>();
            result.rsp = data;
            result.retCode = 200;
            result.retMsg = "ok";
            return result;
        }
    }

    定义异常拦截器:BusinessExceptionFilter.java

    package com.miaoying
    
    import com.miaoying.BusinessException;
    import com.miaoying.ResultResponse;
    import com.alibaba.fastjson.JSONObject;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import javax.servlet.http.HttpServletRequest;
    
    @ControllerAdvice
    @Slf4j
    public class BusinessExceptionFilter {
    
        @ExceptionHandler(BusinessException.class)
        @ResponseBody
        public Object handleBusinessException(HttpServletRequest request, BusinessException ex) {
            log.error("BusinessException code:{},msg:{}", ex.getCode(), ex.getMessage());
            ResultResponse response = new ResultResponse(ex.getCode(), ex.getMessage(), null);
            return JSONObject.toJSON(response);
        }
    
        @ExceptionHandler(Exception.class)
        @ResponseBody
        public Object handleException(HttpServletRequest request, Exception ex) {
            log.error("Exception code:{},msg:{}", 500, ex.getMessage());
            ResultResponse response = new ResultResponse(500, "目前业务繁忙,请您稍后!", null);
            return JSONObject.toJSON(response);
        }
    }

    在需要自定义异常的地方可以直接以如下形式抛出:

    throw new BusinessException(503, "异常测试");

    可以将错误码、错误信息统一管理成常量,总之,还有优化的空间~

    使用上述方式,对filter里抛出的异常捕获不到,所以需要额外处理,如下所示:

    @Component
    @Slf4j
    public class RequestFilter implements Filter {
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
            String path = ((HttpServletRequest) servletRequest).getRequestURI();
            if (path.contains("/exception")) {
                throw new BusinessException(401, "filter内部抛出异常");
            }
            filterChain.doFilter(servletRequest, servletResponse);
        }
    
    }

    如上代码所示的filter里面抛出异常,是不会转换为BusinessException的,而是直接抛出:

    所以我采取了一个比较low的方式:直接向页面response出文字内容(据说可以采用Order改变类的执行顺序,进行异常捕获,但我还没尝试过):

      @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
            String path = ((HttpServletRequest) servletRequest).getRequestURI();
            try {
                if (path.contains("/exception")) {
                    throw new BusinessException(401, "filter内部抛出异常");
                }
                filterChain.doFilter(servletRequest, servletResponse);
                return;
            } catch (Exception e) {
                log.error(e.getMessage());
                ResultResponse response = new ResultResponse();
    
                if (e instanceof BusinessException) {
                    BusinessException be = (BusinessException) e;
                    response.setRetCode(be.getCode());
                    response.setRetMsg(be.getMessage());
                } else {
                    response.setRetCode(500);
                    response.setRetMsg(e.getMessage());
                }
                servletResponse.setCharacterEncoding("utf-8");
                servletResponse.getWriter().print(JSONObject.toJSON(response));
                return;
    
            }
        }
  • 相关阅读:
    053-146
    053-659
    053-658
    053-657
    053-656
    053-654
    053-655
    053-652
    053-651
    053-650
  • 原文地址:https://www.cnblogs.com/miaoying/p/12305624.html
Copyright © 2011-2022 走看看