我想使用@Valid
批注验证我的请求正文,但在Spring Boot中不起作用
我在JAR文件中有一个Request类,无法使用两个字段进行修改。一个字段是对象类型。我的控制器类接受该类对象作为请求主体。当我将下面的JSON传递给控制器时,验证不起作用。下面是代码示例。
请求类别:
public class Request {
Object data;
Map<String, Object> meta;
public <T> T getData() throws ClassCastException {
return (T) this.data;
}
}
另一个类:
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
}
控制器类:
@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
注释均无效。
有解决方案吗?
答案 0 :(得分:5)
如果Request
类是什么样的,验证就可以了;
public class Request {
@Valid
StudentSignUpRequest data;
// other stuff
}
您没有data
的类类型这一事实使得无法在其上进行验证,而忽略了在字段上甚至没有@Valid
注释的事实。 @Valid
批注用于传播验证级联。
但是由于您无法修改Request
对象,让我们继续另一种无需手动进行验证的处理方式。
另一种方法是从StudentSignUpRequest
对象获得request
后触发验证;
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
批注,您将激活该类内@Valid
方法中任何带有public
注释的参数的验证检查。
可以与方法级别验证一起使用,表明 应该在方法级别验证特定类(执行 作为相应验证拦截器的切入点)
这可能是昂贵的,因为您希望尽快得到任何违反约束的信息,而不必为已经注定的请求做任何昂贵的工作。
答案 1 :(得分:1)
没有验证会以您使用它的方式工作,您需要在请求对象内的对象上放置@valid,但是由于您对该类没有控制权,因此另一种方法是扩展Request对象并覆盖getData方法和在该方法上应用@valid,它应该可以那样工作。
答案 2 :(得分:1)
因此,您可以使用以下代码进行验证。
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
}
答案 3 :(得分:0)
首先对字符串使用@NotEmpty
,@Notblank
。然后,请确保您导入的javax.validation.constraints
不是休眠的。如果您使用的是自定义验证器,则需要(final BindingResult bindingResult)
作为控制器方法变量的一部分。
答案 4 :(得分:0)
这里有几件事:
Object
类中data
的类型Request
使验证者无法知道它的类型为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;
}