我正在使用弹簧验证来验证 Rest 控制器输入,如果有人能告诉我是否有可能在异常情况下抛出自定义消息并且自定义消息应该来自属性文件,我将不胜感激。
用户控制器.java
@CrossOrigin(origins = "http://localhost:3000")
@RequestMapping(
value="/",
method=RequestMethod.POST,
consumes = MimeTypeUtils.APPLICATION_JSON_VALUE,
produces = MimeTypeUtils.APPLICATION_JSON_VALUE
)
public Object[] createUser(@ModelAttribute("user") User user, BindingResult bindingResult) {
new UserValidator().validate(user,bindingResult);
if (bindingResult.hasErrors()) {
return bindingResult.getFieldErrors().toArray();
}
}
用户验证器.java
public class UserValidator implements Validator{
@Override
public boolean supports(Class<?> aClass) {
return User.class.equals(aClass);
}
@Override
public void validate(Object obj, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "user.firstName.empty");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastName", "user.lastName.empty");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "slug", "user.slug.empty");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email", "user.email.empty");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "user.password.empty");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "phone", "user.phone.empty");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "address", "user.address.empty");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "country", "user.country.empty");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "gender", "user.gender.empty");
User user = (User) obj;
Pattern pattern = Pattern.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,6}$",
Pattern.CASE_INSENSITIVE);
if(!errors.hasErrors()) {
if (!(pattern.matcher(user.getEmail()).matches())) {
errors.rejectValue("email", "user.email.invalid");
}
}
}
}
消息.属性
# messages.properties
user.firstName.empty=Enter a valid first name.
user.lastName.empty = Enter a valid last name.
user.slug.empty = Select gender.
user.phone.empty = Select gender.
user.address.empty = Select gender.
user.country.empty = Select gender.
user.password.empty = Select gender.
user.gender.empty = Select gender.
user.email.empty = Enter a valid email.
user.email.invalid = Invalid email! Please enter valid email.
自定义消息源配置.java
@Configuration
public class CustomMessageSourceConfiguration {
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new
ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
@Bean
public LocalValidatorFactoryBean getValidator() {
LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
bean.setValidationMessageSource(messageSource());
return bean;
}
}
浏览器响应
{codes: ["user.firstName.empty.user.firstName", "user.firstName.empty.firstName",…], arguments:
null,…}
codes: ["user.firstName.empty.user.firstName", "user.firstName.empty.firstName",…]
0: "user.firstName.empty.user.firstName"
1: "user.firstName.empty.firstName"
2: "user.firstName.empty.java.lang.String"
3: "user.firstName.empty"
arguments: null
defaultMessage: null
objectName: "user"
field: "firstName"
rejectedValue: null
bindingFailure: false
code: "user.firstName.empty"
另一种验证方式
我们可以添加第 4 个参数作为错误消息,而无需使用 messages.properties 文件。
public class UserValidator implements Validator{
@Override
public boolean supports(Class<?> aClass) {
return User.class.equals(aClass);
}
@Override
public void validate(Object obj, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName",
"user.firstName.empty","Error Message Here");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastName",
"user.lastName.empty","Error Message Here");
...
...
}
}
另一种验证方式
我们可以自动将 MessageSource 连接到 UserController.java这是在 CustomMessageSourceConfiguration 中配置的.java以获取 messages.properties 文件。
@Autowired
private MessageSource messageSource;
public User createUser(@Valid @ModelAttribute("user") @RequestBody User
user) {
final ArrayList errorList = new ArrayList<>() {};
bindingResult.getFieldErrors().forEach(fieldError -> {
errorList.add(new
ObjectError(fieldError.getField(),messageSource.getMessage(fieldError.getCode(),
null, Locale.getDefault())));
});
现在我们从 messages.properties 文件中获取所需的错误消息映射。
验证方式
我们可以创建单独的 bean 验证。
用户.java
@Entity
@Table(name = "users")
public class User{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NotNull
@InBetweenNumberCustom(min = 12,max = 18)
private Integer age;
//getters and setters
}
在这里,我们将创建@InBetweenNumberCustom验证注释。
import com.something.validator.ConstraintValidator.InBetweenNumberValidator;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE,
ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(InBetweenNumberCustom.List.class)
@Documented
@Constraint(validatedBy = {InBetweenNumberValidator.class})
public @interface InBetweenNumberCustom {
String message() default "Must be in between {min} and {max}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
int min() default 0;
int max() default 2147483647;
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE,
ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface List {
InBetweenNumberCustom[] value();
}
}
InBetweenNumberValidator.java
import com.something.validator.annonations.InBetweenNumberCustom;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class InBetweenNumberValidator implements
ConstraintValidator<InBetweenNumberCustom,Integer> {
private int minValue;
private int maxValue;
@Override
public void initialize(InBetweenNumberCustom inBetweenNumberCustom) {
this.minValue = inBetweenNumberCustom.min();
this.maxValue = inBetweenNumberCustom.max();
}
@Override
public boolean isValid(Integer aInteger, ConstraintValidatorContext
constraintValidatorContext) {
// null values are not valid
if ( aInteger == null ) return false;
else return aInteger <= this.maxValue && aInteger >= this.minValue;
}
}
用户控制器.java
public JSONObject createUser(@Validated @RequestBody User user,
BindingResult bindingResult) {
...
...
}