这篇文章将为大家详细讲解有关Spring如何实现校验validator和JSR-303,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
JSR 303是Java EE 6中的一项子规范,叫做Bean Validation,官方参考实现是hibernate Validator,此实现与Hibernate ORM没有任何关系。JSR 303用于对Java Bean中的字段的值进行验证。
Spring-mvc.xml配置:
<!--JSR-303-->
<mvc:annotation-driven validator="validator"/>
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
<property name="validationMessageSource" ref="messageSource"/>
</bean>
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="validatemessage"/>
<property name="useCodeAsDefaultMessage" value="false"/>
<property name="defaultEncoding" value="UTF-8"/>
<property name="cacheSeconds" value="60"/>
</bean>
<bean id="webBindingInitializer" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="conversionService">
<bean class="org.springframework.format.support.FormattingConversionServiceFactoryBean"></bean>
</property>
<property name="validator" ref="validator"/>
</bean>
这里贴出部分代码,知道如何加注解即可:
import com.lemontree.common.utils.AjaxResult;
import com.lemontree.common.utils.StringUtil;
import com.lemontree.common.utils.email.EmailUtils;
import org.hibernate.validator.constraints.NotEmpty;
import java.util.Date;
public class User {
/**
* This field was generated by MyBatis Generator.
* This field corresponds to the database column user.id
*
* @mbg.generated Thu Mar 16 13:27:38 CST 2017
*/
private Integer id;
/**
* This field was generated by MyBatis Generator.
* This field corresponds to the database column user.user_name
*
* @mbg.generated Thu Mar 16 13:27:38 CST 2017
*/
@NotEmpty(message = "用户名不能为空")
private String userName;
/**
* This field was generated by MyBatis Generator.
* This field corresponds to the database column user.password
*
* @mbg.generated Thu Mar 16 13:27:38 CST 2017
*/
@NotEmpty(message = "密码不能为空")
private String password;
}
将@Validated 注解跟在实体类前面,BindingResult紧跟其后:
@RequestMapping(value = "/login.htm", method = RequestMethod.POST)
public @ResponseBody AjaxResult login(@Validated User user, BindingResult bindingResult,
HttpServletRequest request, HttpServletResponse response) {
if (bindingResult.hasErrors()){
List<FieldError> errorses = bindingResult.getFieldErrors();
if (CollectionUtils.isNotEmpty(errorses)){
errorses.forEach(item->{
System.out.println(item.getDefaultMessage());
});
}
}
}
JSR-303是JAVA EE 6中的一项子规范,叫做 Bean Validation,Hibernate Validator是Bean Validation 的参考实现。
实际使用就是通过注解来给字段添加约束,然后校验字段是否符合规范,如果不符合就会抛出异常,以此来减少校验数据的代码,并保证拿到的数据都是符合规范的,也可以和Spring框架配合使用
官方文档
https://mvnrepository.com/artifact/org.hibernate/hibernate-validator
https://mvnrepository.com/artifact/javax.validation/validation-api
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.10.Final</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.1-b09</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
校验对象
public class JsrTest {
@NotNull(message = "id不能为空!")
@Min(value = 1, message = "Id只能大于等于1")
Integer id;
@NotNull(message = "姓名不能为空!")
String name;
public void validateParams() {
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();//获取一个验证器
Set<ConstraintViolation<JsrTest>> violationSet = validator.validate(this);//验证数据,获取到错误集合
Iterator<ConstraintViolation<JsrTest>> iterator = violationSet.iterator();
if (iterator.hasNext()) {
String errorMessage = iterator.next().getMessage();//获取到错误信息
throw new ValidationException(errorMessage);
}
}
public static void main(String args[]) {
JsrTest req = new JsrTest();
req.id = 1;
req.validateParams();
}
}
像上面那样将在属性上添加注解即可声明约束
校验属性
上面是校验整个对象,也可以单独校验某个字段:
validator.validateProperty(object, "name");
分组校验
public class JsrTest {
@NotNull(message = "id不能为空!", groups = {ValidationGroup.class})
@Min(value = 1, message = "Id只能大于等于1")
Integer id;
@NotNull(message = "姓名不能为空!", groups = {ValidationGroup.class})
String name;
@DecimalMin(value = "1.1")
double price;
int date;
public static void validateParams(JsrTest jsrTest) {
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
Set<ConstraintViolation<JsrTest>> violationSet = validator.validate(jsrTest, ValidationGroup.class);
Iterator<ConstraintViolation<JsrTest>> iterator = violationSet.iterator();
if (iterator.hasNext()) {
String errorMessage = iterator.next().getMessage();
throw new ValidationException(errorMessage);
}
}
public static void main(String args[]) {
JsrTest req = new JsrTest();
validateParams(req);
}
public interface ValidationGroup {
}
}
分组校验所指定的calss必须是一个接口,可以指定多个
自定义约束
通常情况下,框架提供的注解已经可以满足正常的验证需求,但是我们也可以自定义注解来满足我们的需求
我们这里的例子是所注释的字符串中不能包含指定字符
@Target(FIELD) //元注解,定义该注解使用在字段上
@Retention(RUNTIME) //定义注解的生命周期
@Constraint(validatedBy = CustomValidator.class)//指明该注解的校验器
@Documented //表示该注解会被添加到JavaDoc中
public @interface CustomConstraints {
String message() default "默认异常message";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {}; //这个属性可以用来标注错误的严重等级,但是并不被API自身所使用
String value() default " ";
}
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
/**
* 需要实现ConstraintValidator接口
* 泛型的第一个参数是自定义的注解,第二个参数注解所注释的字段的类型
*/
public class CustomValidator implements ConstraintValidator<CustomConstraints, String> {
private String value;
/**
* 初始化调用,拿到注解所指定的value
*
* @param constraintAnnotation
*/
@Override
public void initialize(CustomConstraints constraintAnnotation) {
value = constraintAnnotation.value();
}
/**
* @param value 注释的字段的值
* @param context
* @return true 通过验证,false 未通过验证
*/
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value != null && value.contains(this.value)) {
context.disableDefaultConstraintViolation();//禁用默认的消息
context.buildConstraintViolationWithTemplate("新添加的错误消息").addConstraintViolation();
return false;
}
return true;
}
}
然后就可以和其他注解一样使用它了
封装
或者是将验证参数的代码提取去出来,单独写一个方法
public static void validateParams(Object object) {
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();//获取一个验证器
Set<ConstraintViolation<Object>> violationSet = validator.validate(object);//验证数据,获取到错误集合
Iterator<ConstraintViolation<Object>> iterator = violationSet.iterator();
if (iterator.hasNext()) {
String errorMessage = iterator.next().getMessage();//获取到错误信息
throw new ValidationException(errorMessage);
}
}
当然这里也可以不抛出异常,而返回一个boolean值,如何封装看实际需求
配合Spring使用
@GetMapping("/test")
public Integer lookCanBuyGoods(@Valid JsrTest req, BindingResult result) throws Exception {
if (result.hasErrors()) {
throw new ValidationException(result.getAllErrors().get(0).getDefaultMessage());
}
//do something...
return 1;
}
@Valid添加这个注解之后就会对参数进行验证,如果在其后没有跟BindingResult,验证不通过就会直接抛出异常,如果添加了BindingResult参数,就不会直接抛出异常,而会把异常信息存储在BindingResult中,供开发者自行处理
如果想要使用分组可以这样
@GetMapping("/test")
public Integer test(@Validated (JsrTest.ValidationGroup.class) JsrTest req, BindingResult result) throws Exception {
if (result.hasErrors()) {
throw new ValidationException(result.getAllErrors().get(0).getDefaultMessage());
}
//do something...
return 1;
}
@Validated如果不使用分组其作用和@Valid一致
Constraint | 详细信息 |
---|---|
@Null | 被注释的元素必须为 null |
@NotNull | 被注释的元素必须不为 null |
@AssertTrue | 被注释的元素必须为 true |
@AssertFalse | 被注释的元素必须为 false |
@Min(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 |
@Max(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
@DecimalMin(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 |
@DecimalMax(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
@Size(max, min) | 被注释的元素的大小必须在指定的范围内 |
@Digits (integer, fraction) | 被注释的元素必须是一个数字,其值必须在可接受的范围内 |
@Past | 被注释的元素必须是一个过去的日期 |
@PastOrPresent | 被注释的元素必须是过去或现在的日期 |
@Future | 被注释的元素必须是一个将来的日期 |
@FutureOrPresent | 被注释的元素必须是将来或现在的日期 |
@Pattern(value) | 被注释的元素必须符合指定的正则表达式 |
@Digits(integer =, fraction =) | 验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度 |
验证是否是邮件地址,如果为null,不进行验证,算通过验证 | |
@NotBlank | 字符串不能是Null还有被Trim的长度要大于0 |
@NotEmpty | 不能为null,且长度大于0 |
@Negative | 被注释的元素必须是负数 |
@NegativeOrZero | 被注释的元素必须是负数或0 |
@Positive | 必须是正数 |
@PositiveOrZero | 必须是正数或0 |
关于“Spring如何实现校验validator和JSR-303”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。