Spring Boot @ControllerAdvice / @Valid

4

我正在开发一个关于Spring Boot中异常处理的示例应用程序。我尝试使用@ControllerAdvice进行异常处理。

我想要处理验证器抛出的异常,它可以处理其他异常但不能处理MethodArgumentNotValidException异常。

以下是我正在处理的类的详细信息:

Query.java

@Getter
@Setter
@NoArgsConstructor
@Validated
public class Query implements Serializable{
    @Size(min = 7, max = 24, message = "Size must be between 7 and 24")
    @Pattern(regexp = "[a-zA-Z0-9 ]+", Invalid characters")
    private String number;

    @Size(max = 2, message = "Size must be between 0 and 2")
    @Pattern(regexp = "[a-zA-Z0-9 ]+", message="Invalid characters")
    private String language;
}

ErrorResponse.java

@Setter
@Getter
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
@Data
public class ErrorResponse 
{

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss")
    private LocalDateTime timestamp;

    private HttpStatus status;

    private int code;

    private String error;

    private String exception;

    private String message;

    private String path;

    private List<String> errors;

}

CustomExceptionHandler.java

@SuppressWarnings({"unchecked","rawtypes"})
@ControllerAdvice
@Component("error")
public class CustomExceptionHandler extends ResponseEntityExceptionHandler {

    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(NotFoundException.class)
    public final ResponseEntity<Object> handleNotFoundError(NotFoundException ex, final HttpServletRequest request) {
        ErrorResponse error = new ErrorResponse();
        error.setTimestamp(LocalDateTime.now());
        error.setMessage(ex.getMessage());
        error.setCode(HttpStatus.NOT_FOUND.value());
        return new ResponseEntity(error, HttpStatus.NOT_FOUND);
    }

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(InternalServerException.class)
    public final ResponseEntity<Object> handleInternelServorError(InternalServerException ex, final HttpServletRequest request) {
        ErrorResponse error = new ErrorResponse();
        error.setTimestamp(LocalDateTime.now());
        error.setMessage(ex.getMessage());
        error.setCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
        return new ResponseEntity(error, HttpStatus.INTERNAL_SERVER_ERROR);
    }

    @ExceptionHandler(ConstraintViolationException.class)
    public void constraintViolationException(HttpServletResponse response) throws IOException {
        response.sendError(HttpStatus.BAD_REQUEST.value());
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        List<String> errorList = ex
                .getBindingResult()
                .getFieldErrors()
                .stream()
                .map(fieldError -> fieldError.getDefaultMessage())
                .collect(Collectors.toList());
        ErrorResponse error = new ErrorResponse();
        error.setCode(HttpStatus.BAD_REQUEST.value());
        return new ResponseEntity(error, HttpStatus.BAD_REQUEST);
    }
}

请求

public ResponseEntity<?> getData(HttpServletRequest httpServletRequest,
            @Valid @ApiParam(value = "MANDATORY. The number") @PathVariable(value = "number", required = true) final String partNumber,
            @Valid @ApiParam(value = "OPTIONAL. The language") @RequestParam(value = "language", required = false) final String languageKey) {
.............
}

2
尝试对 handleMethodArgumentNotValid 方法进行注释,使用 @ExceptionHandler(MethodArgumentNotValidException.class),看看会发生什么? - Faraz
你没有处理这个MethodArgumentNotValidException异常... - Ernesto
3个回答

2
我刚遇到了这个问题,以下是我解决它的方法:
@ControllerAdvice
public class ApplicationExceptionHandler extends ResponseEntityExceptionHandler {   
    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        // handle validation exception here
    }
}

注意:如果您有多个扩展了ResponseEntityExceptionHandler的类,并且都是@ControllerAdvice,您可能会遇到一些麻烦,以便执行此重写函数。我不得不在所有异常处理程序的基类中覆盖它,以便最终使用它。将来,我可能会将所有异常处理程序放入一个类中,以避免这种情况。

source: https://www.youtube.com/watch?v=Q0hwXOeMdUM


0
你没有处理 MethodArgumentNotValidException 的处理程序。添加这个:
    ...
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public void methodArgumentNotValidException(HttpServletResponse response) throws IOException {
        response.sendError(HttpStatus.BAD_REQUEST.value());
    }
    ...

要让你的CustomExceptionHandler起作用。

0

你创建了 List<String> errorList 但从未使用它,最终返回了空的 ErrorResponse


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接