SpringBoot搭建全局异常拦截
作者:ieflex
这篇文章主要介绍了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类
以下是网上一位博主给出的示例代码,博客地址为:https://blog.csdn.net/king_is_everyone/article/details/53080851
@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; } }
到此这篇关于SpringBoot搭建全局异常拦截的文章就介绍到这了,更多相关Springboot全局异常内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!