应用软件在实际开发和运行过程当中,总有这样那样的错误,若是每个接口的错误逻辑都让本身处理,这样显然是很麻烦的,并且说不定还有漏捕获的错误,这样的接口显然是不友好的,为了让接口只专一于处理业务的自己,SpringBoot提供了@ExceptionHandler注解来全局错误拦截处理。java
import com.wusy.demo.exception.BusinessException; import com.wusy.demo.model.ResultObjectModel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.MethodParameter; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.servlet.NoHandlerFoundException; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; import javax.servlet.http.HttpServletRequest; /** * @author wusy * Company: xxxxxx科技有限公司 * Createtime : 2020/2/28 22:04 * Description : rest full 全局统一返回封装 */ @RestControllerAdvice public class GlobalControllerAdvice implements ResponseBodyAdvice<Object> { private Logger logger = LoggerFactory.getLogger(GlobalControllerAdvice.class); /** * 判断哪些须要拦截 * @param returnType * @param converterType * @return */ @Override public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { return true; } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { //若是返回的数据是ResultObjectModel、Byte类型则不进行封装 if( body instanceof ResultObjectModel || body instanceof Byte || body instanceof String) { return body; } return this.getWrapperResponse(request , body); } /** * 默认异常处理,返回500错误 * @param req * @param e * @return */ @ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public ResultObjectModel<String> defaultExceptionHandler(HttpServletRequest req, Exception e) { return getExpResponse(req, e); } /** * 没法找到映射handler的异常处理,返回404错误 * @param req * @param e * @return */ @ExceptionHandler(NoHandlerFoundException.class) @ResponseStatus(HttpStatus.NOT_FOUND) public ResultObjectModel<String> noHandlerFoundExceptionHandler(HttpServletRequest req, Exception e) { return getExpResponse(req, e); } /** * 异常信息返回 * @param request * @param e * @return */ private ResultObjectModel<String> getExpResponse(HttpServletRequest request, Exception e) { return new ResultObjectModel<>(false, e.getMessage() , null); } /** * 返回正常的信息 * @param request * @param data * @return */ private ResultObjectModel<Object> getWrapperResponse(ServerHttpRequest request, Object data) { return new ResultObjectModel<>(true, "请求成功" , data); } }
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; /** * @author wusy * Company: xxxxxx科技有限公司 * Createtime : 2020/2/24 21:54 * Description : */ @RestController @RequestMapping("/api/demo") public class HelloWorldController { @RequestMapping(value = "/exception", method = RequestMethod.GET) public void exception() throws Exception { throw new Exception("这是错误的接口"); } }
运行应用,打开浏览器,在地址栏输入http://127.0.0.1:8787/api/demo/exception,观察结果web
从结果看出,全局错误的配置起做用了。一般为了写业务方便会自定义一些错误类。spring
import lombok.Getter; import lombok.Setter; /** * @author wusy * Company: xxxxxx科技有限公司 * Createtime : 2020/3/2 21:44 * Description : */ @Getter @Setter public class BusinessException extends RuntimeException { private String message; private Object data; public BusinessException(String message) { super(message); this.message = message; } public BusinessException(String message ,Object data) { super(message); this.message = message; this.data = data; } }
全局错误添加自定义错误处理api
/** * 业务层异常 * @param request * @param e * @return */ @ExceptionHandler(BusinessException.class) @ResponseStatus(HttpStatus.OK) public ResultObjectModel<Object> businessExceptionHandler(HttpServletRequest request, Exception e) { BusinessException ex = (BusinessException)e; // 记录错误信息 logger.info((request.getRequestURI().replaceAll("[\r\n]",""))+", message : ["+ e.getMessage().replaceAll("[\r\n]","")+"]"); return new ResultObjectModel(true , ex.getMessage(),ex.getData()); }
修改rest full接口类浏览器
import com.wusy.demo.exception.BusinessException; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; /** * @author wusy * Company: xxxxxx科技有限公司 * Createtime : 2020/2/24 21:54 * Description : */ @RestController @RequestMapping("/api/demo") public class HelloWorldController { @RequestMapping(value = "/exception", method = RequestMethod.GET) public void exception() throws Exception { throw new BusinessException("这是自定义错误的接口"); } }
运行应用,打开浏览器,在地址栏输入http://127.0.0.1:8787/api/demo/exception,观察结果mvc
观察后台日志能够看到app
至此全局错误拦截配置演示结束ide