SpringBoot + Thymeleaf + Validate验证
本文内容纲要:
在开发业务时,不可避免的需要处理一些校验,如果是写if-else这种代码去校验,那会有一大段这样的代码。不过还好有个校验插件:javax.validation.validation-api,不过一般会引用hibernate的校验组件:org.hibernate.hibernate-validator,它已经引用了validation-api组件。
1.基础校验类型
JSR303是一套JavaBean参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注解加在我们JavaBean的属性上面,就可以在需要校验的时候进行校验了。注解如下:
创建需要被校验的实体类,使用一些比较常用的校验注解,还是比较浅显易懂的,字段上的注解名称即可推断出校验内容,每一个注解都包含了message字段,用于校验失败时作为提示信息,
特殊的校验注解,如Pattern(正则校验),还可以自己添加正则表达式,在实体类上加上@notnull@size等验证,例如:
1@Entity
2@Table(name="userinfo",uniqueConstraints=@UniqueConstraint(columnNames="username"))
3publicclassUser{
4privateIntegerid;
5@Size(min=4,max=15,message="用户名长度为4-15位")
6privateStringusername;
7@Size(min=6,max=18,message="密码长度为6-18位")
8privateStringpassword;
9@Pattern(regexp="^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$",message="邮箱格式不正确")
10privateStringemail;
11@Pattern(regexp="^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$",message="手机号填写错误")
12privateStringphone;
13@NotEmpty(message="性别不能为空")
14privateStringsex;
15privateDatecreat_time;
16privateDateupdate_time;
17@Id
18@GeneratedValue
19publicIntegergetId(){
20returnid;
21}
//省略后面set和get方法
说明:
@null被注释的元素必须为空
@notnull被注释的元素必须不为空
@AssertTrue被注释的元素必须为true
@AssertFalse被注释的元素必须为false
@Min被注释的元素必须是一个数字,其值必须大于等于指定的最小数
@Max被注释的元素必须是一个数字,其值必须小于等于指定的最大数
@DecimalMin被注释的元素必须是一个数字,其值必须大于等于指定的最小数
@DecimalMax被注释的元素必须是一个数字,其值必须小于等于指定的最大数
@Size(min,max)被注释的元素的大小必须在指定的范围内
@Digits(integer,fraction)被注释的元素必须是一个数字,其值必须在可接受的范围内
@past被注释的元素必须是一个过去的日期
@Future被注释的元素必须是一个将来的日期
@Pattern(value)被注释的元素必须符合指定的正则表达式
@Email被注释的元素必须是电子邮箱
@Length被注释的字符串的大小必须在指定的范围内
@NotEmpty被注释的字符串必须非空
@Range被注释的元素必须在合适的范围内
**@NotNull和@NotEmpty和@NotBlank区别:**
@NotEmpty用在集合类上面,@NotBlank用在String上面,@NotNull用在基本类型上。
我们可以看到我们在username、password和age对应的get方法上都加上了一个注解,这些注解就是JSR-303里面定义的限制,把对应的校验错误信息放到Spring的Errors对象中。
2.在@Controller中校验数据
接着我们来定义一个使用User对象作为参数接收者的Controller,其代码如下所示:
1@Controller
2publicclassFooController{
3@RequestMapping("/foo")
4publicStringfoo(@ValidatedFoofoo<1>,BindingResultbindingResult<2>){
5if(bindingResult.hasErrors()){
6for(FieldErrorfieldError:bindingResult.getFieldErrors()){
7//...
8}
9return"fail";
10}
11return"success";
12}
13}
<1>参数Foo前需要加上@Validated注解,表明需要spring对其进行校验,而校验的信息会存放到其后的BindingResult中。注意,必须相邻,如果有多个参数需要校验,形式可以如下。foo(@ValidatedFoofoo,BindingResultfooBindingResult,@ValidatedBarbar,BindingResultbarBindingResult){//***};即一个校验类对应一个校验结果。
<2>校验结果会被自动填充,在controller中可以根据业务逻辑来决定具体的操作,如跳转到错误页面。
3.页面获取message里的错误信息
现、在Form里th:Object里添加实体的对象,通过#fields.hasErrors('字段名')判断该字段是否有错误,如果有错误,通过th:errors=“*{字段名}”显示messages里的错误信息提示。例如:
<pth:if="${#fields.hasErrors('username')}"th:errors="*{username}"class="text-danger"></p>
4.分组校验
例如:
1ClassFoo{
2@Min(value=18,groups={Adult.class})
3privateIntegerage;
4publicinterfaceAdult{}
5publicinterfaceMinor{}
6}
这个里的age只有在Adult的分组下才会背校验,例如:
1@RequestMapping("/drink")
2publicStringdrink(@Validated({Foo.Adult.class})Foofoo,BindingResultbindingResult){
3if(bindingResult.hasErrors()){
4for(FieldErrorfieldError:bindingResult.getFieldErrors()){}......
5.自定义校验
(1)我们尝试添加一个“字符串不能包含空格”的限制。
1@Target({METHOD,FIELD,ANNOTATION_TYPE,CONSTRUCTOR,PARAMETER})
2@Retention(RUNTIME)
3@Documented
4@Constraint(validatedBy={CannotHaveBlankValidator.class})<1>
5public@interfaceCannotHaveBlank{
6//默认错误消息
7Stringmessage()default"不能包含空格";
8//分组
9Class<?>[]groups()default{};
10//负载
11Class<?extendsPayload>[]payload()default{};
12//指定多个时使用
13@Target({FIELD,METHOD,PARAMETER,ANNOTATION_TYPE})
14@Retention(RUNTIME)
15@Documented
16@interfaceList{
17CannotHaveBlank[]value();
18}
19}
我们不需要关注太多东西,使用springvalidation的原则便是便捷我们的开发,例如payload,List,groups,都可以忽略。
<1>自定义注解中指定了这个注解真正的验证者类。
(2)编写真正的校验者类
1publicclassCannotHaveBlankValidatorimplements<1>ConstraintValidator<CannotHaveBlank,String>{
2@Override
3publicvoidinitialize(CannotHaveBlankconstraintAnnotation){
4}
5@Override
6publicbooleanisValid(Stringvalue,ConstraintValidatorContextcontext<2>){
7//null时不进行校验
8if(value!=null&&value.contains("")){
9<3>
10//获取默认提示信息
11StringdefaultConstraintMessageTemplate=context.getDefaultConstraintMessageTemplate();
12System.out.println("defaultmessage:"+defaultConstraintMessageTemplate);
13//禁用默认提示信息
14context.disableDefaultConstraintViolation();
15//设置提示语
16context.buildConstraintViolationWithTemplate("cannotcontainsblank").addConstraintViolation();
17returnfalse;
18}
19returntrue;
20}
21}
<1>所有的验证者都需要实现ConstraintValidator接口,它的接口也很形象,包含一个初始化事件方法,和一个判断是否合法的方法。
1publicinterfaceConstraintValidator<AextendsAnnotation,T>{
2
3voidinitialize(AconstraintAnnotation);
4
5booleanisValid(Tvalue,ConstraintValidatorContextcontext);
6}
<2>ConstraintValidatorContext这个上下文包含了认证中所有的信息,我们可以利用这个上下文实现获取默认错误提示信息,禁用错误提示信息,改写错误提示信息等操作。
<3>一些典型校验操作,或许可以对你产生启示作用。
值得注意的一点是,自定义注解可以用在METHOD,FIELD,ANNOTATION_TYPE,CONSTRUCTOR,PARAMETER之上,ConstraintValidator的第二个泛型参数T,是需要被校验的类型。
本文内容总结:
原文链接:https://www.cnblogs.com/jin-zhe/p/8203105.html