在使用spring-boot2开发微服务的时候, 如果系统出现错误是就需要提供一套统一的响应码
比如:
{
"error_code": 50001,
"error_message": "No handler found for GET /api/xxx",
"error_data": null
}
常规的配置很简单,如下
@RestControllerAdvice
@Slf4j
public class ExceptionHandlerAdvice
// extends ResponseEntityExceptionHandler
{
// @Override
// protected ResponseEntity<Object> handleNoHandlerFoundException(
// NoHandlerFoundException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
// log.error("Exception", ex);
// //return handleExceptionInternal(ex, null, headers, status, request);
// return ResponseEntity.status(400).body(new ErrorResponse(ApiErrorCode.NO_4_00_02.getErrorCode(), ex.getMessage()));
//
// }
@ExceptionHandler(Exception.class)
@ResponseBody
public ResponseEntity<Object> Exception(Exception e) {
log.error("Exception", e);
return ResponseEntity.status(500).body(new ErrorResponse(ApiErrorCode.NO_5_00_01.getErrorCode(),e.getMessage()));
}
@ExceptionHandler(ApiException.class)
@ResponseBody
public ResponseEntity<Object> ApiException(ApiException e) {
log.error("ApiException", e);
return ResponseEntity.status(400).body(new ErrorResponse(e.getErrorCode(), e.getErrorMessage(), e.getErrorData()));
}
@ExceptionHandler(ValidationException.class)
@ResponseBody
public ResponseEntity<Object> ValidationException(ValidationException e) {
log.error("ValidationException", e);
return ResponseEntity.status(400).body(new ErrorResponse(ApiErrorCode.NO_4_00_01.getErrorCode(),e.getMessage()));
}
}
如上很简单的就实现了异常的统一处理,可以返回上述的json格式数据
但是当我们访问一个没有的资源时,并没有按照我们的预期进入ExceptionHandlerAdvice
比如我们访问: /api/xxx1
此时这个资源是不存在的,响应内容如下
{
"timestamp": "2019-11-28 17:47:07",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/api/xxx1"
}
很明显并没有按照我们的数据格式输出
这究竟是什么原因导致404的时候不走我们的 ExceptionHandlerAdvice
呢 ?
经过一番源代码的解读, 我们就很容易发现根本原因
源代码类文件 org.springframework.web.servlet.doDispatch(HttpServletRequest request, HttpServletResponse response)
这也是所有请求的入口
从上面代码可以看到, 程序并没有抛出异常,而是直接返回了
问题的根本原因找到了, 就很容易了, 我们直接在配置中将这个值设置为throwExceptionIfNoHandlerFound = true
即可
spring:
mvc:
throw-exception-if-no-handler-found: true
再次启动程序验证,即可验证此时已经进入到我们定义的 ExceptionHandlerAdvice
中, 可以自定义封装,返回我们想要的数据格式
细心的同学想必也看到了, 上面的ExceptionHandlerAdvice
我注释了一段代码 // extends ResponseEntityExceptionHandler
有兴趣的可以深入阅读下这个类 , 可以发现框架已经帮我们封装好了各种异常的处理, 我们可以采用继承的方式来简化处理, 如果需要自定义,只需重写对应的handle
方法
番外篇: 如果是有静态资源的访问如果想排除这个异常的拦截(减少系统无效的并发压力),也是可以配置的
spring:
mvc:
throw-exception-if-no-handler-found: true
resources:
add-mappings: false