Spring MVC中Hibernate-validator的使用
当我们在写具体业务功能的时候,入参校验是不可或缺的一部分,所以我们的项目逻辑中就会存在大量书写
为了能够优雅的解决这个问题,我们在项目选择引入 Hibernate Validator 来执行常见的参数校验,而一些含有逻辑的,比如根据用户ID确认人员是否存在只能靠我们自己逻辑去判断了。
null!=object
的情况。为了能够优雅的解决这个问题,我们在项目选择引入 Hibernate Validator 来执行常见的参数校验,而一些含有逻辑的,比如根据用户ID确认人员是否存在只能靠我们自己逻辑去判断了。
一、验证器的引入与配置
在Spring MVC中,任何支持JSR-303,JSR-349的validator都能够通过简单的配置引入,我们只要引入POM并设置好配置项就可以。<dependency>
<groupid>org.hibernate</groupid>
<artifactid>hibernate-validator</artifactid>
<version>5.4.1.Final</version>
</dependency>
我们使用的是其相关简化的配置,没有配置具体的提示语,只要能把具体的参数问题抛出就可以了,毕竟是面向开发的一个项目,没必要做得这么人性化:
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
</bean>
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor">
<property name="validator" ref="validator" />
</bean>
当然如果有国际化的需要的,可以增加如下的语言配置项
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<!-- 在web环境中一定要定位到classpath 否则默认到当前web应用下找 -->
<value>classpath:messages</value>
</list>
</property>
<property name="defaultEncoding" value="UTF-8"/>
<property name="cacheSeconds" value="60"/>
</bean>
如果你的验证器是用在Controller层的话,我们还需要在配置文件中设置如下的扫描项<mvc:annotation-driven />
二、多级别验证
Bean Validation一开始刚出来的规范是JSR-303,他是是只支持类级别验证的规范,我们使用的时候会有很大的局限性,因为将基础类型作为函数参数是不可避免的事情。
后来直到Bean Validation更新到1.1版本,新增加了对JSR-349的支持,我们能够如鱼得水的使用它。
(一)JavaBean级别的验证
我们以给学校School这个类增加一名学生为例,首先我们需要定义一名学生,他的名字和年龄需要符合相关要求而他的个人简介则可以适当的放宽限制,因此该类定义如下
import javax.validation.constraints.DecimalMin;
import org.hibernate.validator.constraints.NotBlank;
public class Student {
@NotBlank
private String name;
@DecimalMin("18")
private Integer age;
private String desc;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
类中各字段的注解就是其对应的约束,当我们要对其执行具体的限制时,可以在入参上增加@Valid来执行
public void addStudent(@Valid Student student){
/*
...
Do add !
...
*/
}
(二)method级别的验证
要使用method级别的验证,先要给method所处的类加上@Validated的申明,使Spring能够扫描到它,然后直接在参数之前使用即可
public void deleteStudent(@NotNull Long studentId){
/*
...
Do delete by id!
...
*/
}
三、在控制器Controller中使用
当我们在控制器中使用校验器的时候,在配置文件中增加一个annotation-driven就可以了,它会自动将@Valid申明的校验器代理,但是如果还是使用了Method级别的校验器的话,那针对该Controller就需要增加@Validated注解了.
四、在Service层的使用
虽然网上的很多示例都是在Controller层做校验示例的,但我们认为控制器层只是将Service的接口通过HTTP暴露出去了,而且我们在Service也可能通过其他的方式暴露给外部,因此我们均在Service层做了参数校验。而Service无法通过annotation-driven来进行扫描,因此需要每个Service增加@Validated的类注解。
在Service层中,校验注解是作用于interface的,而不是具体的实现类,这是由Bean Validation 所定义的
当我们在Service中使用validation的分组功能时,首先需要在类上面使用@Validated,然后在具体的方法中使用@Validated({CommonAdd.class})类似的具体的分组注解以覆盖类分组,具体内容可参考Validated具体说明
在Service层中,校验注解是作用于interface的,而不是具体的实现类,这是由Bean Validation 所定义的
当我们在Service中使用validation的分组功能时,首先需要在类上面使用@Validated,然后在具体的方法中使用@Validated({CommonAdd.class})类似的具体的分组注解以覆盖类分组,具体内容可参考Validated具体说明
五、目前支持的注解
Bean Validation 中内置的 constraint
@Null 被注释的元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max=, min=) 被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式
Hibernate Validator 附加的 constraint
@NotBlank(message =) 验证字符串非null,且长度必须大于0
@Email 被注释的元素必须是电子邮箱地址
@Length(min=,max=) 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range(min=,max=,message=) 被注释的元素必须在合适的范围内
@Null 被注释的元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max=, min=) 被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式
Hibernate Validator 附加的 constraint
@NotBlank(message =) 验证字符串非null,且长度必须大于0
@Email 被注释的元素必须是电子邮箱地址
@Length(min=,max=) 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range(min=,max=,message=) 被注释的元素必须在合适的范围内
六、在Service中由循环引用导致的问题
我们在开发时,虽然理论上来说不应该产生循环依赖,但我们实际工程开发时,Service层中经常是互相调用的,循环依赖很难避免。
而我们的校验代理是实现的BeanPostProcessor,这样就无可避免的发生循环依赖,bean冲突的问题了。具体原因我在另一篇博客中详细说明,这里我们可以使用一种妥善的解决方案解决这个问题。
当发生循环应用时,我们可以使用@PostConstruct注解,在所有类初始化完成后手动将依赖注入
Independent specialists play, evaluation and rank the best live dealer on-line casinos for Korea. So how do you go about finding an internet casino that accepts South Korean players AND ticks all of the above boxes? Trying to do the legwork on all that analysis yourself would take way too long, so save yourself that unnecessary effort by benefiting from our exhausting work! This site has been designed to give you all the data you need to|you should|you have to} determine which areas are price your time and which aren't. To ensure that 카지노 that|be positive that} an internet casino in Korea is secure and authorized, we only included the sites which have an official and legitimate license from a good regulatory body. Moreover, every casino on our listing is often audited for fairness by an impartial company, which means the games aren't rigged and the general fairness is the best possible.
回复删除