无法使用@Valid 在 Spring 引导中验证请求正文
Not able to validate request body in Spring boot with @Valid
我想用 @Valid
注释验证我的请求正文,但它在 Spring Boot
中不起作用
我在 JAR 文件中有一个请求 class,我无法用两个字段对其进行修改。一个字段是对象类型。我的控制器 class 接受此 class 对象作为请求主体。当我将下面的 JSON 传递给控制器时,验证不起作用。以下是代码示例。
请求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
}
控制器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);
这是我发送的请求:
名字超过 64 个字符:
样本JSON:
{
"data": {
"firstName": "student111111111111111111111111111111111111111111111111111111111111",
"lastName": "somesurname",
"email": "developer@gmail.com"
}
}
不包括名字的地方:
{
"data": {
"lastName": "somesurname",
"email": "developer@gmail.com"
}
}
此处 @Size
和 @NotNull
注释均无效。
有什么解决办法吗?
验证不会像您使用的那样工作,您需要将 @valid 放在请求对象内的对象上,但由于您无法控制它 class 另一种方法是扩展请求对象并覆盖 getData 方法并在该方法上应用 @valid,它应该这样工作。
首先对字符串使用@NotEmpty
、@Notblank
。然后确保你导入 javax.validation.constraints
而不是休眠的。如果您使用的是自定义验证器,则需要 (final BindingResult bindingResult)
作为控制器方法变量的一部分。
如果 Request
class 是这样,验证就会起作用;
public class Request {
@Valid
StudentSignUpRequest data;
// other stuff
}
您没有 class 类型 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
注释,您将激活 class 中 public
方法中任何 @Valid
注释参数的验证检查。
Can be used with method level validation, indicating that a
specific class is supposed to be validated at the method level (acting
as a pointcut for the corresponding validation interceptor)
这可能代价高昂,因为您希望尽快解决任何约束违规问题,而无需为已经注定失败的请求做任何代价高昂的工作。
这里有几件事:
Request
class 中 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;
}
所以你可以使用下面的代码来验证它。
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
}
我想用 @Valid
注释验证我的请求正文,但它在 Spring Boot
我在 JAR 文件中有一个请求 class,我无法用两个字段对其进行修改。一个字段是对象类型。我的控制器 class 接受此 class 对象作为请求主体。当我将下面的 JSON 传递给控制器时,验证不起作用。以下是代码示例。
请求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
}
控制器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);
这是我发送的请求:
名字超过 64 个字符:
样本JSON:
{
"data": {
"firstName": "student111111111111111111111111111111111111111111111111111111111111",
"lastName": "somesurname",
"email": "developer@gmail.com"
}
}
不包括名字的地方:
{
"data": {
"lastName": "somesurname",
"email": "developer@gmail.com"
}
}
此处 @Size
和 @NotNull
注释均无效。
有什么解决办法吗?
验证不会像您使用的那样工作,您需要将 @valid 放在请求对象内的对象上,但由于您无法控制它 class 另一种方法是扩展请求对象并覆盖 getData 方法并在该方法上应用 @valid,它应该这样工作。
首先对字符串使用@NotEmpty
、@Notblank
。然后确保你导入 javax.validation.constraints
而不是休眠的。如果您使用的是自定义验证器,则需要 (final BindingResult bindingResult)
作为控制器方法变量的一部分。
如果 Request
class 是这样,验证就会起作用;
public class Request {
@Valid
StudentSignUpRequest data;
// other stuff
}
您没有 class 类型 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
注释,您将激活 class 中 public
方法中任何 @Valid
注释参数的验证检查。
Can be used with method level validation, indicating that a specific class is supposed to be validated at the method level (acting as a pointcut for the corresponding validation interceptor)
这可能代价高昂,因为您希望尽快解决任何约束违规问题,而无需为已经注定失败的请求做任何代价高昂的工作。
这里有几件事:
Request
class 中 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;
}
所以你可以使用下面的代码来验证它。
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
}