首页 > 解决方案 > 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 异常)并获取以下信息:

有没有可能做到这一点,也许不用注释每个方法@ExceptionHandler

标签: javaspringspring-boot

解决方案


好吧,你可以使用@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());
    }
}



推荐阅读