java - Spring在一个类中拦截异常
问题描述
我将 Spring Boot 用于我的 REST 服务。现在我想在一个中心位置实现一个通用日志记录。这是我的结构:
休息
@GetMapping(value="/rest/test/{userId}")
public User getUserById(@PathVariable String userId) {
return userService.findById(userId);
}
用户服务
public User findById(@NotNull String userId) {
if(noUserFound) {
throw new InvalidArgumentException();
}
}
我的目标是有一个中心类来拦截所有异常(还有 BeanValidation 异常)并获取以下信息:
- 调用的 API 端点
- 传递的所有参数
- 异常及其消息
- 发送请求的用户名/ID(我使用带有 OpenAuth 的 Keycloak)
有没有可能做到这一点,也许不用注释每个方法@ExceptionHandler
?
解决方案
好吧,你可以使用@ControllerAdvice 来实现这个目标。
这是一个示例代码:
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
@ControllerAdvice
public class ErrorHandler extends ResponseEntityExceptionHandler {
// Build-in exceptions, this one is for Validation errors
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request
) {
// info about endpoint
var path = request.getDescription(false);
// request params map
var params = request.getParameterMap();
// authenticated principal
var user = request.getUserPrincipal();
log.debug("path: {}, params: {}, user: {}", path, params.keySet(), user.getName());
return super.handleMethodArgumentNotValid(ex, headers, status, request);
}
// Custom exception
@ExceptionHandler(NoAccessException.class)
public ResponseEntity<Error> noAccessException(NoAccessException ex, WebRequest request) {
return ResponseEntity
.status(HttpStatus.FORBIDDEN)
.body(Error.builder().message(ex.getMessage()).build());
}
}
推荐阅读
- node.js - 如何从mongodb的多个集合中同时获取数据
- python-3.x - 远程调试时按 F5 在 VS Code 中启动 Docker 容器
- java - 推送通知在android studio中不起作用
- angularjs - 如何找出究竟是什么触发了AngularJS中的摘要循环
- mobx - Mobx 状态树入门第 2 部分
- c# - 使用 ImageResizer 调整图像流的大小
- ios - 如何为具有动态单元格宽度的表格视图单元格内的单元格使用 UICollectionView 动态高度?
- php - 在 Woocommerce 结帐中添加基于国家/地区的弹出窗口和自定义消息
- symfony - Symfony 3 - 在每个视图渲染上添加调试
- spring - 处理程序映射的显式注册