我是Java新手,我刚刚创建了一个spring引导应用程序来练习一下。
我创建了一个控制器来接收一个POST请求json:
{
"team1": {
"score": 10,
"colour": "RED"
},
"team2": {
"score": 3,
"colour": "BLUE"
}
}
控制器:
public @ResponseBody
ResponseEntity<Response<Game>> saveGame(
@Valid @RequestBody PostedGameRequest postedGameRequest
) {
// ...
}
PostedGameRequest得到验证,并且工作得很好,但是有两个属性:PostedGameRequestTeam类型的team1和team2,并且它们没有得到验证。我在那里添加了一些@NotEmpty
属性,但这不起作用。
所以现在我创建了一个自定义的TeamValidator,它验证Team中的字段,但是当它失败时,它将只显示我在@Team
属性类中指定的消息。如果我能单独验证每个字段就好了。
@Builder
public class PostedGameRequest {
@Team()
private final PostedGameRequestTeam team1;
@Team()
private final PostedGameRequestTeam team2;
public PostedGameRequestTeam getTeam1() {
return team1;
}
public PostedGameRequestTeam getTeam2() {
return team2;
}
}
public class TeamValidator implements ConstraintValidator<Team, PostedGameRequestTeam> {
List<String> colours = Arrays.asList("RED","BLUE");
@Override
public boolean isValid(@Valid PostedGameRequestTeam team, ConstraintValidatorContext context) {
if (team == null || team.getColour() == null || team.getScore() == null) {
return false;
}
if (team.getScore() < 0 || team.getScore() > 11) {
// This will only lead to an invalid team message, should get a message about the score in this case
return false;
}
if (!colours.contains(team.getColour())) {
// This will only lead to an invalid team message, should get a message about the colour in this case
return false;
}
return (team.getId() != null || team.getName() != null);
}
}
我有一种感觉,我没有按照我应该做的去做。为什么我的第一个方法不起作用?是否需要添加什么来使验证器同时运行team1和team2属性而不添加自定义Validator@Team
?
代替@NotEmpty
try with
@NotNull
这将确保team1和team2总是包含一个不为空的对象
如果您想对team1和team2的每个属性进行更多验证,请在java中进入该对象并向这些字段添加更多注释。对于string
属性,您可以添加
@NotNull
@Size (min = 1)
确保它总是包含一个值
也可以在验证中添加@Valid
这样你的对象就变成了
public class PostedGameRequest {
@NotNull
@Valid
private final PostedGameRequestTeam team1;
@NotNull
@Valid
private final PostedGameRequestTeam team2;
然后在
里面public class PostedGameRequestTeam {
@Min(0)
integer score;
@NotNull
@Size (min=1)
String color;
}
编辑:@Size
只适用于字符串字段,不适用自定义对象
不要使用处理所有验证逻辑的@Team
自定义验证器(我认为这在这种情况下不是很有用),您应该在每个PostedGameRequestTeam
对象中单独声明验证注释。
public class PostedGameRequestTeam {
@NotBlank(message = "The team colour value must not be null, empty or blank!")
@TeamColour(message = "The team colour must be RED or BLUE")
private String colour;
@Min(value = 0, message = "The score value must be higher than 0!")
@Max(value = 11, message = "The score value must be lesser than 11!")
private Integer score;
// Getters and Setters
}
请注意,我使用了@Min
和@Max
注释,这是因为javax.validation.constraints.Size
只验证字符串的长度。
现在您可以添加@TeamColour
的自定义约束验证。
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Constraint(validatedBy = { StatusNotaFiscalValidator.class })
public @interface TeamColour {
String message() default "The team colour must be RED or BLUE!";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
public class TeamColourValidator implements ConstraintValidator<TeamColour, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
boolean valid = true;
if (value != null) {
if (!value.equals("BLUE") && !value.equals("RED")) {
valid = false;
}
}
return valid;
}
}
然后,你应该在你的父对象上添加@NotNull
属性,这样你就可以验证具有team
对象的JSON主体。
@Builder
public class PostedGameRequest {
@NotNull
@Valid
private final PostedGameRequestTeam team1;
@NotNull
@Valid
private final PostedGameRequestTeam team2;
public PostedGameRequestTeam getTeam1() {
return team1;
}
public PostedGameRequestTeam getTeam2() {
return team2;
}
}
public @ResponseBody
ResponseEntity<Response<Game>> saveGame(
@Valid @RequestBody PostedGameRequest postedGameRequest
) {
// ...
}
这个逻辑处理所有你想使用的级联验证。