zoukankan      html  css  js  c++  java
  • springboot全局异常拦截

    1.异常拦截类的创建

    package com.liqi.web.core.exception;
     
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.bind.annotation.RestControllerAdvice;
     
    import com.liqi.common.base.Constants;
    import com.liqi.common.base.ResultBean;
    import com.liqi.common.exception.BusinessInterfaceException;
    import com.liqi.common.exception.bean.ErrorBean;
     
    import lombok.extern.slf4j.Slf4j;
     
    /**
     * 自定义异常处理器
     *
     * @author ieflex
     */
    @RestControllerAdvice
    @Slf4j
    public class InterfaceExceptionHandler {
     
        /**
         * 接口 业务异常
         */
        @ResponseBody
        @ExceptionHandler(BusinessInterfaceException.class)
        public String businessInterfaceException(BusinessInterfaceException e) {
            log.error(e.getMessage(), e);
            ErrorBean error = e.getError();
            ResultBean resultBean = new ResultBean(error.hashCode(), error.getErrorMsg());
            return resultBean.toString();
        }
     
        /**
         * 拦截所有运行时的全局异常   
         */
        @ExceptionHandler(RuntimeException.class)
        @ResponseBody
        public String runtimeException(RuntimeException e) {
            log.error(e.getMessage(), e);
            // 返回 JOSN
            ResultBean resultBean = new ResultBean(Constants.INTERFACE_MSG_301, Constants.INTERFACE_MSG_301_TEXT);
            return resultBean.toString();
        }
     
        /**
         * 系统异常捕获处理
         */
        @ExceptionHandler(Exception.class)
        @ResponseBody
        public String exception(Exception e) {
            log.error(e.getMessage(), e);
            ResultBean resultBean = new ResultBean(Constants.INTERFACE_MSG_301, Constants.INTERFACE_MSG_301_TEXT);
            // 返回 JOSN
            return resultBean.toString();
        }
    }

    2.controller 测试

      package com.springboot_Error.ErrorController;
            
            import org.springframework.stereotype.Controller;
            import org.springframework.web.bind.annotation.RequestMapping;
            
            @Controller
            public class ErrorControllerTest {
                //全局异常拦截 测试
                @RequestMapping("/ErrorTest")
                public String index2(){
                    System.err.println("请求成功!");
                    int i = 1/0; //这里会有一个运算异常
                    return "index";
                }
                
            }    

    3.启动 springboot 工程

    package com.springboot_Error.ErrorRun;
            
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.context.annotation.ComponentScan;
     
            
            //扫描 com.springboot_Error.ErrorController 包下 controller 注解过的类
            @ComponentScan(basePackages={"com.springboot_Error.ErrorController"})
            @EnableAutoConfiguration
            public class ErrorRun {
                
                public static void main(String[] args) {
                    SpringApplication.run(ErrorRun.class, args);
                }
                
            }

    4.测试

    /**
     * 功能描述: 模拟自定义异常
     * @return
     */
    @RequestMapping(value = "/api/test")  
    public Object myext() {
        throw new BusinessInterfaceException("500", "my ext异常");
    }

    经过测试发现可以捕获到Controller层的异常,当前前提是Controller层没有对异常进行catch处理,如果Controller层对异常进行了catch处理,那么在这里就不会捕获到Controller层的异常了,所以这一点要注意。

    5.基于Springboot自身的全局异常统一处理
    主要是实现ErrorController接口或者继承AbstractErrorController抽象类或者继承BasicErrorController类

     
    @Controller
    @RequestMapping(value = "error")
    @EnableConfigurationProperties({ServerProperties.class})
    public class ExceptionController implements ErrorController {
     
        private ErrorAttributes errorAttributes;
     
        @Autowired
        private ServerProperties serverProperties;
     
     
        /**
         * 初始化ExceptionController
         * @param errorAttributes
         */
        @Autowired
        public ExceptionController(ErrorAttributes errorAttributes) {
            Assert.notNull(errorAttributes, "ErrorAttributes must not be null");
            this.errorAttributes = errorAttributes;
        }
     
     
        /**
         * 定义404的ModelAndView
         * @param request
         * @param response
         * @return
         */
        @RequestMapping(produces = "text/html",value = "404")
        public ModelAndView errorHtml404(HttpServletRequest request,
                                      HttpServletResponse response) {
            response.setStatus(getStatus(request).value());
            Map<String, Object> model = getErrorAttributes(request,
                    isIncludeStackTrace(request, MediaType.TEXT_HTML));
            return new ModelAndView("error/404", model);
        }
     
        /**
         * 定义404的JSON数据
         * @param request
         * @return
         */
        @RequestMapping(value = "404")
        @ResponseBody
        public ResponseEntity<Map<String, Object>> error404(HttpServletRequest request) {
            Map<String, Object> body = getErrorAttributes(request,
                    isIncludeStackTrace(request, MediaType.TEXT_HTML));
            HttpStatus status = getStatus(request);
            return new ResponseEntity<Map<String, Object>>(body, status);
        }
     
        /**
         * 定义500的ModelAndView
         * @param request
         * @param response
         * @return
         */
        @RequestMapping(produces = "text/html",value = "500")
        public ModelAndView errorHtml500(HttpServletRequest request,
                                      HttpServletResponse response) {
            response.setStatus(getStatus(request).value());
            Map<String, Object> model = getErrorAttributes(request,
                    isIncludeStackTrace(request, MediaType.TEXT_HTML));
            return new ModelAndView("error/500", model);
        }
     
     
        /**
         * 定义500的错误JSON信息
         * @param request
         * @return
         */
        @RequestMapping(value = "500")
        @ResponseBody
        public ResponseEntity<Map<String, Object>> error500(HttpServletRequest request) {
            Map<String, Object> body = getErrorAttributes(request,
                    isIncludeStackTrace(request, MediaType.TEXT_HTML));
            HttpStatus status = getStatus(request);
            return new ResponseEntity<Map<String, Object>>(body, status);
        }
     
     
        /**
         * Determine if the stacktrace attribute should be included.
         * @param request the source request
         * @param produces the media type produced (or {@code MediaType.ALL})
         * @return if the stacktrace attribute should be included
         */
        protected boolean isIncludeStackTrace(HttpServletRequest request,
                                              MediaType produces) {
            ErrorProperties.IncludeStacktrace include = this.serverProperties.getError().getIncludeStacktrace();
            if (include == ErrorProperties.IncludeStacktrace.ALWAYS) {
                return true;
            }
            if (include == ErrorProperties.IncludeStacktrace.ON_TRACE_PARAM) {
                return getTraceParameter(request);
            }
            return false;
        }
     
     
        /**
         * 获取错误的信息
         * @param request
         * @param includeStackTrace
         * @return
         */
        private Map<String, Object> getErrorAttributes(HttpServletRequest request,
                                                       boolean includeStackTrace) {
            RequestAttributes requestAttributes = new ServletRequestAttributes(request);
            return this.errorAttributes.getErrorAttributes(requestAttributes,
                    includeStackTrace);
        }
     
        /**
         * 是否包含trace
         * @param request
         * @return
         */
        private boolean getTraceParameter(HttpServletRequest request) {
            String parameter = request.getParameter("trace");
            if (parameter == null) {
                return false;
            }
            return !"false".equals(parameter.toLowerCase());
        }
     
        /**
         * 获取错误编码
         * @param request
         * @return
         */
        private HttpStatus getStatus(HttpServletRequest request) {
            Integer statusCode = (Integer) request
                    .getAttribute("javax.servlet.error.status_code");
            if (statusCode == null) {
                return HttpStatus.INTERNAL_SERVER_ERROR;
            }
            try {
                return HttpStatus.valueOf(statusCode);
            }
            catch (Exception ex) {
                return HttpStatus.INTERNAL_SERVER_ERROR;
            }
        }
     
        /**
         * 实现错误路径,暂时无用
         * @see ExceptionMvcAutoConfiguration#containerCustomizer()
         * @return
         */
        @Override
        public String getErrorPath() {
            return "";
        }
     
    }

    6.AOP也可以实现异常的全局处理

     
    @Component
    @Aspect
    public class ExceptionAspectController {
        public static final Logger logger = LoggerFactory.getLogger(ExceptionAspectController.class);
     
        @Pointcut("execution(* com.test.test.*.*(..))")//此处基于自身项目的路径做具体的设置
        public void pointCut(){}
     
        @Around("pointCut()")
        public Object handleControllerMethod(ProceedingJoinPoint pjp) {
            Stopwatch stopwatch = Stopwatch.createStarted();
     
            APIResponse<?> apiResponse;
            try {
                logger.info("执行Controller开始: " + pjp.getSignature() + " 参数:" + Lists.newArrayList(pjp.getArgs()).toString());
                apiResponse = (APIResponse<?>) pjp.proceed(pjp.getArgs());
                logger.info("执行Controller结束: " + pjp.getSignature() + ", 返回值:" + apiResponse.toString());
                logger.info("耗时:" + stopwatch.stop().elapsed(TimeUnit.MILLISECONDS) + "(毫秒).");
            } catch (Throwable throwable) {
                apiResponse = handlerException(pjp, throwable);
            }
     
            return apiResponse;
        }
     
        private APIResponse<?> handlerException(ProceedingJoinPoint pjp, Throwable e) {
            APIResponse<?> apiResponse = null;
            if(e.getClass().isAssignableFrom(MessageCenterException.class) ){
                MessageCenterException messageCenterException = (MessageCenterException)e;
                logger.error("RuntimeException{方法:" + pjp.getSignature() + ", 参数:" + pjp.getArgs() + ",异常:" + messageCenterException.getException().getMessage() + "}", e);
                apiResponse = messageCenterException.getApiResponse();
            } else if (e instanceof RuntimeException) {
                logger.error("RuntimeException{方法:" + pjp.getSignature() + ", 参数:" + pjp.getArgs() + ",异常:" + e.getMessage() + "}", e);
                apiResponse = new APIResponse(APIResponse.FAIL,null,e.getMessage());
            } else {
                logger.error("异常{方法:" + pjp.getSignature() + ", 参数:" + pjp.getArgs() + ",异常:" + e.getMessage() + "}", e);
                apiResponse = new APIResponse(APIResponse.FAIL,null,e.getMessage());
            }
     
            return apiResponse;
        }
    }
  • 相关阅读:
    重打技术征集系统第七稿开发第1、2天
    关于centos7右上角网络图标消失的解决办法
    记录一下hbase踩的坑
    在jsp中,单选按钮的点击事件(点击隐藏或显示输入框)
    input中禁止输入特殊字符
    《软件方法》阅读笔记——1
    随手快递app开发第十七天
    Codeforces Round #284 (Div. 1) B. Name That Tune(最大流)
    hihocoder 1310岛屿(dfs,一个搜索技巧)
    Codeforces Round #294 (Div. 2) E. A and B and Lecture Rooms(lca+思维,树上寻找与给定两个点距离相等的点的个数)
  • 原文地址:https://www.cnblogs.com/deityjian/p/12485329.html
Copyright © 2011-2022 走看看