对Java Spring Boot风格的web服务有点陌生——所以请温柔一点。为什么大多数Spring Boot Controller示例不显示任何被捕获的异常?我看到我的一些开发人员经常这样做。答案是:这是一个共同的约定。但是为什么。我是否错过了使用Spring Boot创建web服务的关键概念?
例如:
@PostMapping(path = "/sampleEndpoint/v1/myEndpoint", produces = "application/json")
public ResponseEntity<String> myEndpoint(@RequestBody MyEndpointRequest myEndpointRequest) {
MyEndpointResponse response = someService.myEndpoint(myEndpointRequest);
return new ResponseEntity<>(response, HttpStatus.OK);
}
我认为,考虑到架构,你应该至少添加一个try/catch块,比如一些日志记录,并抛出一个新的异常,异常消息:
@PostMapping(path = "/sampleEndpoint/v1/myEndpoint", produces = "application/json")
public ResponseEntity<String> myEndpoint(@RequestBody MyEndpointRequest myEndpointRequest) {
try{
MyEndpointResponse response = someService.myEndpoint(myEndpointRequest);
return new ResponseEntity<>(response, HttpStatus.OK);
}catch(Exception ex){
//Your favorite logger:
log.error("STACK_TRACE: {}", StaticClass.stackTraceToString(ex));
//throw exception for calling or consuming system/application:
throw new MiscException(ex.getMessage());
}
}
为这个问题(观察)提供一些背景信息:
- 使用多个数据源:几个数据库和一些其他web服务(给我们的客户端一个一站式的地方获得他们的数据。
- 在潜在的4种不同的客户端/表示层类型的应用程序中使用这个web服务。
- 我的团队希望捕获来自我们挖掘的数据源的意外异常…并记录它们。
如何实现异常捕获机制取决于开发者。但是定义异常类型和错误代码/消息是一个很好的做法。假设您有一个端点获取具有id的产品,但没有具有该id的产品,在这种情况下,客户端将接收带有internal server error
消息的http 500
代码。这会让用户和开发人员感到困惑,到底是什么导致了这个错误。
所以防止这些,你可以从@ControllerAdvice
注释中得到帮助,这将允许将异常处理程序应用于多个或所有控制器。首先,您将定义自定义异常,如:
public class ProductNotFoundException extends RuntimeException {
public ProductNotFoundException(Long id) {
super(String.format("Product with id %d not found", id));
}
}
,然后你可以定义你的ControllerAdvice
类:
@ControllerAdvice
public class ExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(ProductNotFound.class)
public ResponseEntity<Object> handleProductNotFoundException(
ProductNotFoundException ex, WebRequest request) {
Map<String, Object> body = new LinkedHashMap<>();
body.put("timestamp", LocalDateTime.now());
body.put("message", "Product not found");
return new ResponseEntity<>(body, HttpStatus.NOT_FOUND);
}
}