繁体   English   中英

在 Spring Boot 应用程序中 bean 验证失败时没有得到正确的响应

[英]Not getting proper response while bean validation failed in spring boot app

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

用户控制器类

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

用户类

@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
}

自定义异常处理程序

@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",
}

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

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

<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>

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

当我的应用程序中的验证失败时,自定义类级约束验证器会抛出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);
    }

}

错误响应类:

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ErrorResponse {

    private LocalDateTime timestamp;
    private int status;
    private String error;
    private String message;
    private String path;
}

我希望这有帮助。 如果您需要有关类级约束的详细说明,请观看此视频

从 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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM