MethodArgumentNotValidException 的短消息

Short messages for MethodArgumentNotValidException

提问人:Jason 提问时间:7/20/2023 更新时间:7/20/2023 访问量:50

问:

为我的应用程序的用户提供了一个简单的 DTO,我在其中使用 jakarta 验证器来确定密码的长度。

public class UserDto {

  @NonNull
  @NotBlank private String username;

  @JsonProperty(access = WRITE_ONLY)
  @NonNull
  @ToString.Exclude
  @Size(min = 8, max = 30, message = "Please provide a password between 8 and 30 characters long.")
  private String password;
}

我确保使用控制器上的注释来注册用户:@Valid

@PostMapping(value = "/register")
public ResponseEntity<UserDto> registerUser(@RequestBody @Valid UserDto user) {
  return new ResponseEntity<>(userDetailsService.save(user), HttpStatus.CREATED);
}

现在,如果我尝试使用太短的密码注册用户,例如密码:"pass"

{
  "username": "memeuser",
  "password": "pass"
}

我收到一条 400 和一条非常冗长的错误消息,其中揭示了几个 API 内部结构:

{
  "message": "Validation failed for argument [0] in public org.springframework.http.ResponseEntity<com.agilebank.model.user.UserDto> com.agilebank.controller.JwtAuthenticationController.registerUser(com.agilebank.model.user.UserDto): [Field error in object 'userDto' on field 'password': rejected value [pass]; codes [Size.userDto.password,Size.password,Size.java.lang.String,Size]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [userDto.password,password]; arguments []; default message [password],30,8]; default message [Please provide a password between 8 and 30 characters long.]] "
}

我正在装饰通过以下类和方法抛出的东西:Exception

@RestControllerAdvice
public class ExceptionAdvice {

  @ResponseBody
  @ExceptionHandler({
    HttpMessageNotReadableException.class,
    InsufficientBalanceException.class,
    SameAccountException.class,
    InvalidTransactionCurrencyException.class,
    OneOfTwoCurrenciesMissingException.class,
    InvalidSortByFieldSpecifiedException.class,
    MethodArgumentNotValidException.class // <---- Here is the type that interests us
  })
  @ResponseStatus(HttpStatus.BAD_REQUEST)
  public ResponseEntity<ExceptionMessageContainer> badRequestStatusMessage(Exception exc) {
    return new ResponseEntity<>(new ExceptionMessageContainer(exc.getMessage()), HttpStatus.BAD_REQUEST);
  }
}

其中 is a simple container for the exception message:ExceptionMessageContainer

@AllArgsConstructor
public class ExceptionMessageContainer {
    private String message;
}

查看此异常类型的官方文档,我不太确定除了为我处理返回的异常之外,还有一种简单的方法可以获取我在约束中拥有的内容,这不是一个可推广的解决方案。关于我如何能够获得我在约束级别提供的东西的任何想法?当然,我也可以通过内部的单独方法定位实例,并具有类似以下内容:message@SizeStringgetMessage()messageMethodArgumentNotValidExceptionExceptionAdvice

 @ResponseBody
 @ExceptionHandler({
    MethodArgumentNotValidException.class
  })
  @ResponseStatus(HttpStatus.BAD_REQUEST)
  public ResponseEntity<ExceptionMessageContainer> methodArgumentNotValidExceptionSpecificHandler(MethodArgumentNotValidException exc) {
    return new ResponseEntity<>(new ExceptionMessageContainer("Password should be between 8 and 30 characters long"), HttpStatus.BAD_REQUEST);
  }

但在其他情况下,可能会抛出此异常类型,因为我有其他具有不同验证器约束的 DTO 可以抛出此异常类型。因此,这在一般情况下效果不佳,并且会误导用户。

java spring exception exceptionhandler 控制器-建议

评论

0赞 M. Deinum 7/20/2023
你为什么决定编写自己的异常处理程序?Spring 只会打印出消息。旁边,如果你想为这种情况(the)做一些特别的事情,那就写出来。异常包含实际消息。MethodArgumentNotValidException.class
0赞 Jason 7/23/2023
编写我自己的异常处理程序的原因更多地与确保发送 400 Http 代码有关,而不是与消息本身有关。您对包含实际消息的异常是正确的。除了用 、 等解析字符串之外,还有什么方法可以获得更用户友好的消息吗?BAD_REQUESTsubstr()lastIndexOf()
0赞 M. Deinum 7/24/2023
你不需要。字段在那里,您需要更改 .这包括所有消息,甚至已经转置了。MethodArgumentNotValidException

答: 暂无答案