簡體   English   中英

Spring攔截一類中的異常

[英]Spring intercept exceptions in one class

我正在為我的 REST 服務使用 Spring Boot。 現在我想在一個中心位置實現一個通用的日志記錄。 這是我的結構:

休息

@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());
    }
}


您可以使用@ControllerAdvice 來自https://mkyong.com/spring-boot/spring-rest-error-handling-example/ 的示例代碼

@ControllerAdvice
 public class CustomGlobalExceptionHandler extends ResponseEntityExceptionHandler 
 {

//...

// @Validate For Validating Path Variables and Request Parameters
@ExceptionHandler(ConstraintViolationException.class)
public void constraintViolationException(HttpServletResponse response) throws IOException {
    response.sendError(HttpStatus.BAD_REQUEST.value());
}

// error handle for @Valid
@Override
protected ResponseEntity<Object>
handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
                             HttpHeaders headers,
                             HttpStatus status, WebRequest request) {

    Map<String, Object> body = new LinkedHashMap<>();
    body.put("timestamp", new Date());
    body.put("status", status.value());

    //Get all fields errors
    List<String> errors = ex.getBindingResult()
            .getFieldErrors()
            .stream()
            .map(x -> x.getDefaultMessage())
            .collect(Collectors.toList());

    body.put("errors", errors);

    return new ResponseEntity<>(body, headers, status);

}}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM