zoukankan      html  css  js  c++  java
  • Spring_数据校验和自定义检验规则和分组校验

    @Validated  :绑定需要校验的数据.

    数据校验规则:为数据绑定校验的规则

    private Long booId;
    @NotNull(message = "不能为空")
    private String bookName;
    private String author;
    private String publisher;
    @DecimalMin(value = "20",message = "不能低于20元")
    @DecimalMax(value = "100",message = "不能多于100")
    private Float price;
    //正则表达式检验
    //正则表达式用来判断某个字符串是否符合某个规则
    //或者用来提取一整个字符 串中满足某个规则的子串
    @Pattern(regexp = "1[345678][0-9]{9}")
    private String Mobile;

    为是实体类属性绑定检验规则:
    message为检验不合格时的提示信息.
    import javax.validation.constraints.*;
    
    public class BookBean  {
        private Long booId;
        @NotNull(message = "书名不能为空")
        private String bookName;
        private String author;
        private String publisher;
        @DecimalMin(value = "20",message = "不能低于20元")
        @NotNull(message = "价格不能为空")
        @DecimalMax(value = "100",message = "不能多于100")
        private Float price;
    
        //正则表达式检验
        //正则表达式用来判断某个字符串是否符合某个规则
        //或者用来提取一整个字符 串中满足某个规则的子串
        @Pattern(regexp = "1[345678][0-9]{9}")
        private String Mobile;public String getIdCard() {
            return idCard;
        }
    
        public void setIdCard(String idCard) {
            this.idCard = idCard;
        }
    
        public String getMobile() {
            return Mobile;
        }
    
        public void setMobile(String mobile) {
            Mobile = mobile;
        }
    
        public Long getBooId() {
            return booId;
        }
    
        public void setBooId(Long booId) {
            this.booId = booId;
        }
    
        public String getBookName() {
            return bookName;
        }
    
        public void setBookName(String bookName) {
            this.bookName = bookName;
        }
    
        public String getAuthor() {
            return author;
        }
    
        public void setAuthor(String author) {
            this.author = author;
        }
    
        public String getPublisher() {
            return publisher;
        }
    
        public void setPublisher(String publisher) {
            this.publisher = publisher;
        }
    
        public Float getPrice() {
            return price;
        }
    
        public void setPrice(Float price) {
            this.price = price;
        }
    }

    绑定数据检验:

    注意:校验结果:BindingResult  result必须经跟在@Validated BokBean bokBean 后面.用于接受检验的结果.

        @RequestMapping("/book/creat")
       public String create(@Validated BokBean bokBean, BindingResult result, Model model){
    
            //可以通过BindingResult对象拿到校验的错误信息.
            //注意:该参数必须要紧跟在被校验的对象的后面
            if (result.hasErrors()){
                //判断是否有检验的错误
    //            result.getFieldError("bookName").getDefaultMessage();
                for (FieldError error : result.getFieldErrors()) {
                    //获取被校验对象的所有错误
                    String message = error.getDefaultMessage();
                    System.out.println(message);
                }
                //可以直接把错误信息的集合都放到集合里
                 model.addAttribute("erros", result.getFieldErrors());
                return "erro";
            }
            return "success";
       }

    自定义检验规则,有时候spring自带的检验规则不满足我们使用时,可以自定义检验规则.

    检验规则:

    public class IDValidator implements ConstraintValidator<IDVlidation,String> {
        @Override
        public boolean isValid(String value, ConstraintValidatorContext context) {
            //这里引用了一个身份证检验的工具类
            return IdCardUtils.isIDCard(value);
        }
        
    //这个方法可不实现 @Override
    public void initialize(IDVlidation constraintAnnotation) { } }

    自定义一个检验规则的注解,自定义注解见自定义注解章节:https://www.cnblogs.com/zhouchangyang/p/10908343.html

    定义这个注解为了方便,可仿造spring定义的注解规则写(赋值粘贴)

    @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })  //表明该注解可用在哪里
    @Retention(RUNTIME)   //表明生效时间
    @Repeatable(IDVlidation.List.class)
    @Constraint(validatedBy = {IDValidator.class})  //注明该注解所实现的规则是哪个类
    public @interface IDVlidation {
    
        String message() default "";
    
        Class<?>[] groups() default { };
    
        Class<? extends Payload>[] payload() default { };
    
        @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
        @Retention(RUNTIME)
        @interface List {
    
            IDVlidation[] value();
        }
    
    }

    这样就定义好了一个规则的注解,

    使用自定义注解和使用系统的注解一样,添加到需要校验的属性上面即可:

        @IDVlidation(message = "省份证不符合规范")
        private String idCard;

    获取校验的后不满足规则的错误信息方式有两种:

    一种就像上面一样在 方法参数中检验的对象后面添加 BindingResult result,

     @RequestMapping("/book/creat")
        public String create(@Validated BokBean bokBean, BindingResult result, Model model){

    第二种是单独写一个获取错误信息的方法,在方法上添加注解,@ExceptionHandler(BindException.class),

    通过 BindException ex  一样能获得第一种方法的BindingResult 对象.对错误信息的进一步操作和第一种方法一样.

        @ExceptionHandler(BindException.class)
        public String resolveBindinngExcrption(BindException ex){
            //获取错误结果集.
            BindingResult result = ex.getBindingResult();
            FieldError error = ex.getFieldError();
            System.out.println(result);
            return "erro";
        }

    分组校验:

    某些时候,我们前端的某些请求需要对某个对象的一部分属性进行校验,有一部分属性不需要校验.

    这时我们就需要对校验的属性进行分组,根据前端的需求对属性进行分类.

    比如登录和注册业务,他们引用的都是用户对象,但是登录只需要校验用户名和密码,而注册除了校验登录和注册还需要校验很多数据,

    假如规定了注册时手机号不能为空,在登陆时不需要手机号,就会报错,这时就需要用分组来针对性的校验.

    创建一个实体类,并对属性添加校验规则和分组信息,

    public class UserBean  {
    
        //登录分组
        public interface LoginGroup{}
        //注册分组
        public interface RegisterGroup{}
    
        @NotBlank(message = "不能为空",groups = {LoginGroup.class,RegisterGroup.class})
        private String username;
        @JsonIgnore  //表示不想序列化的数据
        @NotBlank(groups = {LoginGroup.class,RegisterGroup.class})
        private String password;
        @Pattern(message = "手机号错误",regexp = "1[3-9][\d]{9}",groups = {RegisterGroup.class})
        @NotNull(message = "手机号不能为空",groups = {RegisterGroup.class})
        private String mobile;
        @AssertTrue(groups = {RegisterGroup.class})
        private boolean agree;
        @JsonFormat(pattern = "yyyy-MM-dd-HH:mm:ss",timezone = "GMT+8")
        private Date birthday;
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public String getMobile() {
            return mobile;
        }
    
        public void setMobile(String mobile) {
            this.mobile = mobile;
        }
    
        public boolean isAgree() {
            return agree;
        }
    
        public void setAgree(boolean agree) {
            this.agree = agree;
        }
    }

    分组校验用法:

    在实体类中创建内部接口类(可以是普通类),用来对业务进行分类,

    public class UserBean  {
    
        //登录分组
        public interface LoginGroup{}
        //注册分组
        public interface RegisterGroup{}

    在属性的检验规则中添加分组属性 : 

    @NotBlank(message = "不能为空",groups = {LoginGroup.class,RegisterGroup.class})
    表示这个不能为空的检验规则登录和注册都需要满足.
       //登录分组
        public interface LoginGroup{}
        //注册分组
        public interface RegisterGroup{}
    
        @NotBlank(message = "不能为空",groups = {LoginGroup.class,RegisterGroup.class})
        private String username;
        @JsonIgnore  //表示不想序列化的数据
        @NotBlank(groups = {LoginGroup.class,RegisterGroup.class})
        private String password;
        @Pattern(message = "手机号错误",regexp = "1[3-9][\d]{9}",groups = {RegisterGroup.class})
        @NotNull(message = "手机号不能为空",groups = {RegisterGroup.class})
        private String mobile;
        @AssertTrue(message = "必须为真",groups = {RegisterGroup.class})
        private boolean agree;

    规定好校验规则和分组后,只需在需要校验的地方使用就可以,

    用法:在方法参数检验标记中添加分组属性:@Validated(UserBean.LoginGroup.class)

    表示只有被UserBean.LoginGroup.class分组的校验规则才会被列入本次校验

    @Controller
    public class UserController {
    
        @RequestMapping("/login")
        public String login(@Validated(UserBean.LoginGroup.class) UserBean userBean){
            return "success";
        }
    
        @RequestMapping("/register")
        public String register(@Validated(UserBean.RegisterGroup.class) UserBean userBean){
            return "success";
        }
    
    
  • 相关阅读:
    技术实践 | 聊聊网易云信的信令网络库实践
    打破传统降噪技术 看网易云信在语音降噪的实践应用
    聊聊前端日志库在 SaaS 产品中的应用与设计
    WebRTC 系列之音频会话管理
    简单五步,轻松构建本土「Clubhouse」
    网易云信服务监控平台实践
    基于 Elasticsearch 的数据报表方案
    基于 WebRTC 实现自定义编码分辨率发送
    Python 设计模式—原型模式
    网络层—简单的面试问题
  • 原文地址:https://www.cnblogs.com/zhouchangyang/p/10914528.html
Copyright © 2011-2022 走看看