zoukankan      html  css  js  c++  java
  • 轻松搞定数据验证(二)

    SpringBoot 是为了简化 Spring 应用的创建、运行、调试、部署等一系列问题而诞生的产物,自动装配的特性让我们可以更好的关注业务本身而不是外部的XML配置,我们只需遵循规范,引入相关的依赖就可以轻易的搭建出一个 WEB 工程

    一起来学SpringBoot | 第十九篇:轻松搞定数据验证(一) 中介绍了数据有效性校验的重要性,也简单介绍了如何用轻松的方式搞定数据有效性校验,但是当系统自带的注解无法满足我们的要求时候应该咋办呢?这就是本章将给各位介绍的自定义 Validator 注解

    为何要自定义

    javax.validation 包与 hibernate-validator 包中存在的注解几乎可以满足大部分的要求,又拥有基于正则表达式的@Pattern,为什么还需要自己去定义呢?

    原因如下

    • 正则效率不高
    • 正则可读性不好
    • 正则门槛较高,很多开发者并不会编写正则表达式

    本章目标

    熟悉 ConstraintValidator 接口并且编写自己的数据验证注解

    具体代码

    非常简单…

    导入依赖

    在 pom.xml 中添加上 spring-boot-starter-web 的依赖即可

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <dependencies>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    </dependency>
    </dependencies>

    自定义注解

    这里定义了一个 @DateTime 注解,在该注解上标注了 @Constraint 注解,它的作用就是指定一个具体的校验器类

    关键字段(强制性)

    • message: 验证失败提示的消息内容
    • groups: 为约束指定验证组(非常不错的一个功能,下一章介绍)
    • payload: 不太清楚(欢迎留言交流)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    package com.battcn.annotation;


    import com.battcn.validator.DateTimeValidator;

    import javax.validation.Constraint;
    import javax.validation.Payload;
    import java.lang.annotation.Retention;
    import java.lang.annotation.Target;

    import static java.lang.annotation.ElementType.FIELD;
    import static java.lang.annotation.ElementType.PARAMETER;
    import static java.lang.annotation.RetentionPolicy.RUNTIME;

    /**
    * @author Levin
    * @since 2018/6/6 0006
    */
    @Target({FIELD, PARAMETER})
    @Retention(RUNTIME)
    @Constraint(validatedBy = DateTimeValidator.class)
    public @interface DateTime {

    String message() default "格式错误";

    String format() default "yyyy-MM-dd";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
    }

    具体验证

    定义校验器类 DateTimeValidator 实现 ConstraintValidator 接口,实现接口后需要实现它里面的 initialize: 与 isValid: 方法。

    方法介绍

    • initialize: 主要用于初始化,它可以获得当前注解的所有属性
    • isValid: 进行约束验证的主体方法,其中 value 就是验证参数的具体实例,context 代表约束执行的上下文环境。

    这里的验证方式虽然简单,但职责明确;为空验证可以使用 @NotBlank@NotNull@NotEmpty 等注解来进行控制,而不是在一个注解中做各种各样的规则判断,应该职责分离

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    package com.battcn.validator;

    import com.battcn.annotation.DateTime;

    import javax.validation.ConstraintValidator;
    import javax.validation.ConstraintValidatorContext;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;

    /**
    * 日期格式验证
    *
    * @author Levin
    * @version 1.0.0
    * @since 2018-06-06
    */
    public class DateTimeValidator implements ConstraintValidator<DateTime, String> {

    private DateTime dateTime;

    @Override
    public void initialize(DateTime dateTime) {
    this.dateTime = dateTime;
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
    // 如果 value 为空则不进行格式验证,为空验证可以使用 @NotBlank @NotNull @NotEmpty 等注解来进行控制,职责分离
    if (value == null) {
    return true;
    }
    String format = dateTime.format();
    if (value.length() != format.length()) {
    return false;
    }
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
    try {
    simpleDateFormat.parse(value);
    } catch (ParseException e) {
    return false;
    }
    return true;
    }
    }

    控制层

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    package com.battcn.controller;

    import com.battcn.annotation.DateTime;
    import org.springframework.validation.annotation.Validated;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;

    /**
    * 参数校验
    *
    * @author Levin
    * @since 2018/6/04 0031
    */
    @Validated
    @RestController
    public class ValidateController {

    @GetMapping("/test")
    public String test(@DateTime(message = "您输入的格式错误,正确的格式为:{format}", format = "yyyy-MM-dd HH:mm") String date) {
    return "success";
    }
    }

    主函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    package com.battcn;

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;


    /**
    * @author Levin
    */
    @SpringBootApplication
    public class Chapter19Application {

    public static void main(String[] args) {
    SpringApplication.run(Chapter19Application.class, args);
    }
    }

    测试

    完成准备事项后,启动 Chapter19Application 自行测试即可,测试手段相信大伙都不陌生了,如 浏览器postmanjunitswagger,此处基于 postman,如果你觉得自带的异常信息不够友好,那么配上一起来学SpringBoot | 第十八篇:轻松搞定全局异常 可以轻松搞定…

    错误格式

    错误格式错误格式

    正确格式

    正确格式正确格式

  • 相关阅读:
    CornerNet 算法笔记
    弱监督学习下商品识别:CVPR 2018细粒度识别挑战赛获胜方案简介
    弱监督学习总结(1)
    【机器学习】模型融合方法概述
    目标检测评价标准
    目标检测Anchor-free分支:基于关键点的目标检测
    空洞卷积(dilated convolution)
    【Android】Android程序保护与破解浅析
    【随笔】入世
    【Android】Android部分问题记录
  • 原文地址:https://www.cnblogs.com/lywJ/p/10715290.html
Copyright © 2011-2022 走看看