繁体   English   中英

无法使用@Valid 在 Spring 引导中验证请求正文

[英]Not able to validate request body in Spring boot with @Valid

我想使用@Valid注释验证我的请求正文,但它在 Spring Boot 中不起作用

我在 JAR 文件中有一个请求 class,我无法用两个字段对其进行修改。 一个字段的类型是 Object。我的 controller class 接受这个 class object 作为请求主体。 当我将下面的 JSON 传递给 controller 时,验证不起作用。 以下是代码示例。

请求 Class:

public class Request {

    Object data;
    Map<String, Object> meta;

    public <T> T getData() throws ClassCastException {
        return (T) this.data;
    }
}

另一个Class:

public class StudentSignUpRequest {

     @NotNull(message = "First Name should not be empty")
     @Size(max = 64, message = "FirstName should not exceed 64 characters")
     private String firstName;

     @NotNull(message = "Last Name should not be empty")
     @Size(max = 64, message = "LastName should not exceed 64 characters")
     private String lastName;

     @NotNull(message = "Email cannot be empty")
     @Size(max = 50, message = "Email cannot exceed 50 characters")
     @Pattern(regexp = EMAIL_REGEX_PATTERN, message = "Email should contain a valid email address.")
     private String email;

     // other fields
}

Controller Class:

@PostMapping(value = Constants.STUDENT_SIGN_UP)
public Response signUpStudent(@Valid @RequestBody Request request, HttpServletRequest servletRequest) {

    // retrieving the actual resource from request payload
    StudentSignUpRequest signUpRequest = request.getData(StudentSignUpRequest.class);
    // call service to sign-up student
    return loginRegistrationService.signUpStudent(signUpRequest);
}

调用代码设置请求如下:

StudentSignUpRequest studentSignUpRequest = new StudentSignUpRequest();
//setter methods

Request payload = new Request();
payload.setData(studentSignUpRequest);

这是我发送的请求:

对于 firstName 超过 64 个字符:

样本 JSON:

{
    "data": {
        "firstName": "student111111111111111111111111111111111111111111111111111111111111",
        "lastName": "somesurname",
        "email": "developer@gmail.com"
    }
}

不包括名字的地方:

{
    "data": {
        "lastName": "somesurname",
        "email": "developer@gmail.com"
    }
}

这里@Size@NotNull注释都不起作用。

任何解决方案?

如果Request类是这样的,验证就会起作用;

public class Request {

    @Valid
    StudentSignUpRequest data;

    // other stuff
}

您没有data类类型这一事实使得无法对其应用验证,忽略字段上甚至没有@Valid注释的事实。 @Valid注释用于传播验证级联。

但是由于您无法修改Request对象,让我们继续使用另一种方法来处理验证,而无需手动进行。


另一种方法是在从request对象中获取StudentSignUpRequest后触发验证;

StudentSignUpRequest signUpRequest = request.getData(StudentSignUpRequest.class);
loginRegistrationService.signUpStudent(signUpRequest) // validation will trigger with this call

你可以做的如下;

@Service
@Validated
public class LoginRegistrationService {

    public void signUpStudent(@Valid StudentSignUpRequest signUpRequest) {
        // some logic
    }
}

使用@Validated批注,您将激活对该类中public方法中的任何@Valid批注参数的验证检查。

可与方法级别验证一起使用,表示应该在方法级别验证特定类(充当相应验证拦截器的切入点)

这可能是昂贵的,因为您希望尽快获得任何违反约束的情况,而无需为已经注定的请求做任何昂贵的工作。

没有验证将按照您使用它的方式工作,您需要将 @valid 放在请求对象内的对象上,但由于您无法控制该类,因此另一种方法是扩展 Request 对象并覆盖 getData 方法并应用 @valid在这种方法上,它应该以这种方式工作。

因此,您可以使用以下代码进行验证。

public <T> T getData() throws ClassCastException, SomeCustomValidationException {
    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    validator = factory.getValidator();
    Set s = validator.validate(this.data);
    //throw SomeCustomValidationException if set is not empty else return this.data
}

首先对字符串使用@NotEmpty@Notblank 然后确保您导入javax.validation.constraints而不是 hibernate 的。 如果您使用自定义验证器,则需要(final BindingResult bindingResult)作为控制器方法变量的一部分。

这里有几件事: Request类中data Object类型使验证器不可能知道它是StudentSignUpRequest类型。 所以改变数据类型。

public class Request {
    StudentSignUpRequest data;
    Map<String, Object> meta;
}

其次,虽然你已经添加@Valid在控制器的方法,以在验证领域StudentSignUpRequest你必须添加@Valid这里。 现在,如果在 API 请求中传递数据,将对其进行验证。 如果不存在,则不会进行验证。 如果你想让数据被强制传递,也添加@NotNull。

public class Request {

    @Valid
    @NotNull
    StudentSignUpRequest data;
    Map<String, Object> meta;
}

您是否添加了以下依赖项?

spring-boot-starter-validation

还要检查https://www.baeldung.com/spring-boot-bean-validation

暂无
暂无

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

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