【问题标题】:Not getting proper response while bean validation failed in spring boot app在 Spring Boot 应用程序中 bean 验证失败时没有得到正确的响应
【发布时间】:2018-11-22 09:55:56
【问题描述】:

我正在使用 spring boot 2.0.6、hibernate 验证器 6.0、validation-api 2.0 和 apache cxf。我在控制器方法中使用了@Valid 注释,然后我在 bean 属性中设置了 @NotNull、@Email 和正确的消息。然后我创建了一个 CustomExceptionHandler 来处理 MethodArgumentNotValidException。在邮递员对其进行测试时,我的验证消息没有得到正确的响应。

UserController.class

@Path("/user")
@Component
public class UserController {

@POST
@Path("/register")
@Consumes(MediaType.APPLICATION_JSON_VALUE)
@Produces(MediaType.APPLICATION_JSON_VALUE)
public Response registerUser(@Valid User user) {

    String status = "";

    Boolean isEmailIdExist = UserAuthService.checkUserByMailId(user.getEmail());
    Boolean isUserNameExist = UserAuthService.checkUserByUserName(user.getUserName());

    if(!isEmailIdExist) {
        if(!isUserNameExist) {
            status = UserAuthService.registerUser(user);
        }else {
            status = "Username already taken. Try with different name";
        }
    }else {
        status = "Email ID already exist";
    }

    return Response.ok(status).build();
}
}

User.class

@Entity
@Table(name = "USER")
public class User {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "UID")
private int userId;

@NotBlank(message = "Please provide first name")
@Column(name = "FIRST_NAME", length = 50)
private String firstName;

@NotBlank(message = "Please provide email")
@Column(name = "EMAIL", length = 100, unique = true)
@Email(message = "Please provide a valid email")
private String email;}

getter/setter
}

CustomExceptionHandler.java

@ControllerAdvice
@Component
public class CustomExceptionHandler extends ResponseEntityExceptionHandler {

@ExceptionHandler(Exception.class)
public final ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request) {
    ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false));
    return new ResponseEntity<Object>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR);
}

@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
        HttpHeaders headers, HttpStatus status, WebRequest request) {
    ErrorDetails errorDetails = new ErrorDetails(new Date(), "Validation Failed", ex.getBindingResult().toString());
    return new ResponseEntity<Object>(errorDetails, HttpStatus.BAD_REQUEST);
}
}

Json 结构

{
    "firstName":"",
    "email":"prakashkumar@xyz.com",
}

【问题讨论】:

  • 你能提供你所期望的和你得到的吗?
  • 嗨@PoojaAggarwal。你可以看到我的 json 结构。我在邮递员中发送这个 json,我应该得到一个带有验证消息“请提供名字”的响应,但我得到了完整的异常堆栈跟踪。
  • 你能评论一下这个方法handleMethodArgumentNotValid并尝试一下吗。
  • 我又遇到了同样的异常。在 Eclipse 控制台中,我可以看到验证消息。
  • 约束违规列表:[ ConstraintViolationImpl{interpolatedMessage='请提供名字', propertyPath=firstName, rootBeanClass=class com.airbus.argo.model.ArgoUser, messageTemplate='请提供名字' } ]]

标签: java spring-boot cxf hibernate-validator


【解决方案1】:

如果您遇到以下问题,例如:无法看到返回给客户端的验证错误(默认消息),您可以这样做:

最佳解决方案 1: 只需添加开发工具。这应该可以解决问题。在我这样做之后,我所有的绑定结果都返回给了客户端。我建议你先测试一下:

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
</dependency>

解决方案 2:

我发现这是由于使用 Spring Boot 2.3+ 因此,如果您使用的是 Spring Boot 2.3 或更高版本,请将此依赖项添加到您的 pom.xml 文件中,因为它不再包含在“web”依赖项本身中。

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

现在有必要将 java/resources/application.properties 中的“包含绑定错误”设置为“始终”。 “消息”也是如此,尽管我认为这是可选的。

server.error.include-message=always
server.error.include-binding-errors=always

解决方案 3:(在我发现解决方案 2 也可能有用之前)

所以我发现这是由于 Spring boot 2.3+ 造成的。但是我在 Spring Boot v2.3+​​ 中找不到关于 @Valid 的新更新用法的警告消息。

所以我最终通过调整 pom.xml 文件中的发布版本切换回 Spring boot v2.2.10(2.2 的最新版本),如下所示:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.10.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

通过回滚到旧版本,这对我来说非常有效。虽然我想有一天更新我的 Spring Boot 版本。 (重温解决方案 1 和 2)

【讨论】:

    【解决方案2】:

    Springboot 2.3+以下需要添加依赖进行验证

    <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>
    

    添加上述依赖项将进行验证并将消息记录在 cosole 中。但是,如果您想获取带有 http 响应的消息,则需要将以下内容添加到资源文件夹中的 application.properties 文件中

    server.error.include-message=always
    server.error.include-binding-errors=always
    

    【讨论】:

      【解决方案3】:

      当我的应用程序中的验证失败时,自定义类级约束验证器会抛出 MethodArgumentNotValidException。我已经从bindingResult 提取了这个异常的错误信息,如下所示:

      @RestControllerAdvice
      public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
      
      @Override
          protected ResponseEntity<Object> handleMethodArgumentNotValid(
                  MethodArgumentNotValidException ex, HttpHeaders headers,
                  HttpStatus status, WebRequest request) {
              //to extract the default error message from a diagnostic
              // information about the errors held in MethodArgumentNotValidException
              Exception exception = new Exception(ex.getBindingResult().getAllErrors().get(0).getDefaultMessage());
              return this.createResponseEntity(HttpStatus.BAD_REQUEST, exception, request);
          }
      
      private ResponseEntity<Object> createResponseEntity(
                  HttpStatus httpStatus, Exception ex, WebRequest request) {
              ErrorResponse errorResponse = ErrorResponse.builder()
                      .timestamp(LocalDateTime.now())
                      .status(httpStatus.value())
                      .error(httpStatus.getReasonPhrase())
                      .message(ex.getMessage())
                      .path(request.getDescription(true))
                      .build();
              return handleExceptionInternal(ex, errorResponse,
                      new HttpHeaders(), httpStatus, request);
          }
      
      }
      

      ErrorResponse 类:

      @Data
      @Builder
      @NoArgsConstructor
      @AllArgsConstructor
      public class ErrorResponse {
      
          private LocalDateTime timestamp;
          private int status;
          private String error;
          private String message;
          private String path;
      }
      

      我希望这会有所帮助。如果您需要关于类级别约束的详细说明,请查看this video

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-09-04
        • 2019-03-28
        • 1970-01-01
        • 2020-09-25
        • 1970-01-01
        • 1970-01-01
        • 2014-01-09
        • 2020-10-26
        相关资源
        最近更新 更多