zoukankan      html  css  js  c++  java
  • 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"))
     3  public class User {
     4     private Integer id;
     5    @Size(min = 4, max = 15, message = "用户名长度为4-15位")
     6    private String username;
     7    @Size(min = 6, max = 18, message = "密码长度为6-18位")
     8    private String password;
     9    @Pattern(regexp = "^([a-z0-9A-Z]+[-|\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\.)+[a-zA-Z]{2,}$", message = "邮箱格式不正确")
    10    private String email;
    11     @Pattern(regexp = "^((13[0-9])|(15[^4,\D])|(18[0,5-9]))\d{8}$", message = "手机号填写错误")
    12     private String phone;
    13     @NotEmpty(message = "性别不能为空")
    14     private String sex;
    15     private Date creat_time;
    16     private Date update_time;
    17     @Id
    18     @GeneratedValue
    19        public Integer getId() {
    20             return id;
    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
     2  public class FooController {
     3  @RequestMapping("/foo")
     4     public String foo(@Validated Foo foo <1>, BindingResult bindingResult <2>) {
     5         if(bindingResult.hasErrors()){
     6             for (FieldError fieldError : bindingResult.getFieldErrors()) {
     7                 //...
     8             }
     9             return "fail";
    10         }
    11         return "success";
    12     }
    13 }

      <1> 参数Foo前需要加上 @Validated 注解,表明需要spring对其进行校验,而校验的信息会存放到其后的 BindingResult 中。注意,必须相邻,如果有多个参数需要校验,形式可以如下。 foo(@Validated Foo foo, BindingResult fooBindingResult ,@Validated Bar bar, BindingResult barBindingResult){ //*** }  ;即一个校验类对应一个校验结果。
      <2> 校验结果会被自动填充,在controller中可以根据业务逻辑来决定具体的操作,如跳转到错误页面。

    3.页面获取message里的错误信息

      现、在Form里 th:Object 里添加实体的对象,通过 #fields.hasErrors('字段名') 判断该字段是否有错误,如果有错误,通过 th:errors=“*{字段名}” 显示messages里的错误信息提示。例如:

    <p th:if="${#fields.hasErrors('username')} " th:errors="*{username}" class="text-danger"></p>

    4.分组校验

      例如:

    1 Class Foo{
    2       @Min(value = 18,groups = {Adult.class})
    3       private Integer age;
    4       public interface Adult{}
    5       public interface Minor{}
    6           }  

      这个里的age只有在Adult的分组下才会背校验,例如:

    1 @RequestMapping("/drink")
    2 public String drink(@Validated({Foo.Adult.class}) Foo foo, BindingResult bindingResult) {
    3     if(bindingResult.hasErrors()){
    4         for (FieldError fieldError : bindingResult.getFieldErrors()) {}......

    5.自定义校验

      (1)我们尝试添加一个“字符串不能包含空格”的限制。

     1 @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
     2 @Retention(RUNTIME)
     3 @Documented
     4 @Constraint(validatedBy = {CannotHaveBlankValidator.class})<1>
     5 public @interface CannotHaveBlank {
     6     //默认错误消息
     7     String message() default "不能包含空格";
     8     //分组
     9     Class<?>[] groups() default {};
    10     //负载
    11     Class<? extends Payload>[] payload() default {};
    12     //指定多个时使用
    13     @Target({FIELD, METHOD, PARAMETER, ANNOTATION_TYPE})
    14     @Retention(RUNTIME)
    15     @Documented
    16     @interface List {
    17         CannotHaveBlank[] value();
    18     }
    19 }

      我们不需要关注太多东西,使用spring validation的原则便是便捷我们的开发,例如payload,List ,groups,都可以忽略。

         <1>自定义注解中指定了这个注解真正的验证者类。

    (2)编写真正的校验者类

     1 public class CannotHaveBlankValidator implements <1> ConstraintValidator<CannotHaveBlank, String> {
     2     @Override
     3     public void initialize(CannotHaveBlank constraintAnnotation) {
     4     }
     5     @Override
     6     public boolean isValid(String value, ConstraintValidatorContext context <2>) {
     7         //null时不进行校验
     8         if (value != null && value.contains(" ")) {
     9             <3>
    10             //获取默认提示信息
    11             String defaultConstraintMessageTemplate = context.getDefaultConstraintMessageTemplate();
    12             System.out.println("default message :" + defaultConstraintMessageTemplate);
    13             //禁用默认提示信息
    14             context.disableDefaultConstraintViolation();
    15             //设置提示语
    16             context.buildConstraintViolationWithTemplate("can not contains blank").addConstraintViolation();
    17             return false;
    18         }
    19         return true;
    20     }
    21 }

    <1> 所有的验证者都需要实现ConstraintValidator接口,它的接口也很形象,包含一个初始化事件方法,和一个判断是否合法的方法。

    1 public interface ConstraintValidator<A extends Annotation, T> {
    2 
    3     void initialize(A constraintAnnotation);
    4 
    5     boolean isValid(T value, ConstraintValidatorContext context);
    6 }

    <2>  ConstraintValidatorContext  这个上下文包含了认证中所有的信息,我们可以利用这个上下文实现获取默认错误提示信息,禁用错误提示信息,改写错误提示信息等操作。
    <3> 一些典型校验操作,或许可以对你产生启示作用。
    值得注意的一点是,自定义注解可以用在METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER之上, ConstraintValidator 的第二个泛型参数T,是需要被校验的类型。

  • 相关阅读:
    Mac root Operation not permitted
    case_for_if 各种嵌套相结合
    RANDOM 的用法
    hdu 6681 Rikka with Cake(扫描线)
    2019牛客暑期多校训练营(第十场)F.Popping Balloons(线段树)
    2019 Multi-University Training Contest 2 Harmonious Army(最小割)
    P1361 小M的作物 (最小割)
    2019 Multi-University Training Contest 1 String(序列自动机+贪心)
    2019牛客暑期多校训练营(第九场)E.All men are brothers(并查集+排列组合)
    2019 Multi-University Training Contest 1 Path(最短路+最小割)
  • 原文地址:https://www.cnblogs.com/jin-zhe/p/8203105.html
Copyright © 2011-2022 走看看