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