Spring Boot ExceptionHandler for MethodArgumentNotValidExcep



我使用的是Spring Boot v2.2.10和Spring v5.2.9。我创建了一个带有@Valid @RequestBody注释的Rest控制器。验证工作得很好(当提交超出约束的值时,我得到一个400 BAD REQUEST响应),但我不喜欢默认的错误消息,因为它暴露了太多的内部信息。因此,我定义了一个@ExceptionHandler(MethodArgumentNotValidException.class)方法,但是这个方法从来没有被调用过。

这是带有异常处理程序的控制器:

import java.util.List;
import java.util.stream.Collectors;
import javax.validation.Valid;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/data")
public class DataController {
@PostMapping(path = "/{id}", consumes = MediaType.APPLICATION_JSON_VALUE)
private void postData(
@PathVariable String id,
@Valid @RequestBody MyDTO dto) {

// DO SOMETHING
}

@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public List<String> handleValidationExceptions(MethodArgumentNotValidException ex) {
System.out.println("Handling method argument not valid exception");
return ex.getBindingResult()
.getAllErrors().stream()
.map(ObjectError::getDefaultMessage)
.collect(Collectors.toList());
} 
}

DTO:

import javax.validation.constraints.Max;
import lombok.Getter;
@Getter
public class MyDTO {

@Max(value = 1, message = "Value should not be greater than 1")
private float value;

}

我也试着把ExceptionHandler放到一个额外的类中:

// Imports
@Order(Ordered.HIGHEST_PRECEDENCE)
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
// Same as before
}

正如我所说的,我的ExceptionHandler永远不会被调用。我可能做错了什么?

尝试从ResponseEntityExceptionHandler类扩展并覆盖handleMethodArgumentNotValid

@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
@Slf4j
public class ExceptionController extends ResponseEntityExceptionHandler {
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
HttpHeaders headers, HttpStatus status, WebRequest request) {
return ...;
}

您可以尝试在此链接中应用相同的方法:https://www.baeldung.com/spring-boot-bean-validation

我得到了同样的问题,我像下面的代码一样解决了它,这是链接中样本的稍微修改版本。

我认为问题是在你的handleValidationExceptions方法的返回类型。你应该使用Map<>而不是List。

@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, String>> handleValidationExceptions(
MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getAllErrors().forEach((error) -> {
String fieldName = ((FieldError) error).getField();
String errorMessage = error.getDefaultMessage();
errors.put(fieldName, errorMessage);
});
return ResponseEntity.badRequest().body(errors);
}
}

因为我使用了@ControllerAdvice而不是@RestControllerAdvice,所以我需要返回ResponseEntity类型。我在返回中确定响应类型ResponseEntity.badRequest().body(errors);但是如果你想使用RestControllerAdvise注释那么你可以直接返回Map<>在这种情况下,你可以继续使用@ResponseStatus(HttpStatus.BAD_REQUEST)在异常处理程序方法上。因此,尝试在您的GlobalExceptionHandler类中应用代码。

在WebFlux中,也许你可以捕获WebExchangeBindException而不是MethodArgumentNotValidException。

你也可以从那里取bindingResult。

相关内容

  • 没有找到相关文章

最新更新