java validation 后台参数验证的使用详解

一、前言

在后台开发过程中,对参数的校验成为开发环境不可缺少的一个环节。比如参数不能为null,email那么必须符合email的格式,如果手动进行if判断或者写正则表达式判断无意开发效率太慢,在时间、成本、质量的博弈中必然会落后。所以把校验层抽象出来是必然的结果,下面说下几种解决方案。

二、几种解决方案

1、struts2的valid可以通过配置xml,xml中描述规则和返回的信息,这种方式比较麻烦、开发效率低,不推荐

2、validation bean 是基于JSR-303标准开发出来的,使用注解方式实现,及其方便,但是这只是一个接口,没有具体实现.Hibernate Validator是一个hibernate独立的包,可以直接引用,他实现了validation bean同时有做了扩展,比较强大 ,实现图如下:

点此查看中文官方手册

3、oval 是一个可扩展的Java对象数据验证框架,验证的规则可以通过配置文件、Annotation、POJOs 进行设定。可以使用纯 Java 语言、JavaScript 、Groovy 、BeanShell 等进行规则的编写,本次不过多讲解

三、bean validation 框架验证介绍

bean validation 包放在maven上维护,最新包的坐标如下:

<dependency>

  <groupId>javax.validation</groupId>

  <artifactId>validation-api</artifactId>

  <version>1.1.0.Final</version>

</dependency>

点击这里查看最新的坐标地址

下载之后打开这个包,有个package叫constraints,里面放的就是验证的的注解:

  

下面开始用代码实践一下:

1、定义一个待验证的bean:Student.java

package com.shishang;

import javax.validation.constraints.*;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;

public class Student implements Serializable {

  @NotNull(message = "名字不能为空")
  private String name;

  @Size(min = 6,max = 30,message = "地址应该在6-30字符之间")
  private String address;

  @DecimalMax(value = "100.00",message = "体重有些超标哦")
  @DecimalMin(value = "60.00",message = "多吃点饭吧")
  private BigDecimal weight;

  private String friendName;
  @AssertTrue
  private Boolean isHaveFriend(){
    return friendName != null?true:false;
  }

  @Future(message = "生日必须在当前实践之前")
  private Date birthday;

  @Pattern(regexp = "^(.+)@(.+)$",message = "邮箱的格式不合法")
  private String email;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getAddress() {
    return address;
  }

  public void setAddress(String address) {
    this.address = address;
  }

  public BigDecimal getWeight() {
    return weight;
  }

  public void setWeight(BigDecimal weight) {
    this.weight = weight;
  }

  public String getFriendName() {
    return friendName;
  }

  public void setFriendName(String friendName) {
    this.friendName = friendName;
  }

  public Date getBirthday() {
    return birthday;
  }

  public void setBirthday(Date birthday) {
    this.birthday = birthday;
  }

  public String getEmail() {
    return email;
  }

  public void setEmail(String email) {
    this.email = email;
  }
}

2、测试类:StudentTest.java

package com.use;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

public class StudentTest implements Serializable {
  public static void main(String[] args) {
    Student xiaoming = getBean();
    List<String> validate = validate(xiaoming);
    validate.forEach(row -> {
      System.out.println(row.toString());
    });

  }

  private static Student getBean() {
    Student bean = new Student();
    bean.setName(null);
    bean.setAddress("北京");
    bean.setBirthday(new Date());
    bean.setFriendName(null);
    bean.setWeight(new BigDecimal(30));
    bean.setEmail("xiaogangfan163.com");
    return bean;
  }

  private static ValidatorFactory factory = Validation.buildDefaultValidatorFactory();

  public static <T> List<String> validate(T t) {
    Validator validator = factory.getValidator();
    Set<ConstraintViolation<T>> constraintViolations = validator.validate(t);

    List<String> messageList = new ArrayList<>();
    for (ConstraintViolation<T> constraintViolation : constraintViolations) {
      messageList.add(constraintViolation.getMessage());
    }
    return messageList;
  }
}

3、运行testValidation()方法,输处如下:

  1. 地址应该在6-30字符之间
  2. 邮箱的格式不合法
  3. 生日必须在当前时间之前
  4. 多吃点饭吧
  5. 名字不能为空

4、总结

  1. 像@NotNull、@Size等比较简单也易于理解,不多说
  2. 因为bean validation只提供了接口并未实现,使用时需要加上一个provider的包,例如hibernate-validator
  3. @Pattern 因为这个是正则,所以能做的事情比较多,比如中文还是数字、邮箱、长度等等都可以做
  4. @AssertTRue 这个与其他的校验注解有着本质的区别,这个注解适用于多个字段。例子中isHaveFriend方法依赖friendName字段校验
  5. 验证的api是经过我加工了一下,这样可以批量返回校验的信息
  6. 有时我们需要的注解可能没有提供,这时候就需要自定义注解,写实现类,下面说一下自定义注解的使用

四、自定义bean validation 注解验证

有时框架自带的没法满足我们的需求,这时就需要自己动手丰衣足食了,恩恩 ,这个不难,下面说下。

这个例子验证字符串是大写还是小写约束标注,代码如下:

1、枚举类型CaseMode, 来表示大写或小写模式

 package com.defineconstrain;

/**
 * created by xiaogangfan
 * on 16/10/25.
 */
public enum CaseMode {
  UPPER,
  LOWER;
}

2、定义一个CheckCase的约束标注

package com.defineconstrain;

/**
 * created by xiaogangfan
 * on 16/10/25.
 */
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

@Target( { METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = CheckCaseValidator.class)
@Documented
public @interface CheckCase {

  String message() default "{com.mycompany.constraints.checkcase}";

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

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

  CaseMode value();

}

3、约束条件CheckCase的验证器

package com.defineconstrain;

/**
 * created by xiaogangfan
 * on 16/10/25.
 */
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class CheckCaseValidator implements ConstraintValidator<CheckCase, String> {

  private CaseMode caseMode;

  public void initialize(CheckCase constraintAnnotation) {
    this.caseMode = constraintAnnotation.value();
  }

  public boolean isValid(String object, ConstraintValidatorContext constraintContext) {

    if (object == null)
      return true;

    if (caseMode == CaseMode.UPPER)
      return object.equals(object.toUpperCase());
    else
      return object.equals(object.toLowerCase());
  }

}

4、在Student.java中增加一个属性

@CheckCase(value = CaseMode.LOWER,message = "名字的拼音需要小写")
private String spellName;

5、在StudentTest.java的getBean()方法中增加一行

bean.setSpellName("XIAOGANGFAN");

6、运行testValidation()方法,输处如下:

  1. 地址应该在6-30字符之间
  2. 邮箱的格式不合法
  3. 生日必须在当前时间之前
  4. 多吃点饭吧
  5. 名字的拼音需要小写
  6. 名字不能为空

7、说明新增的约束生效了,大功告成

代码下载地址:git@github.com:xiaogangfan/vaidation.git

命令: git clone git@github.com:xiaogangfan/vaidation.git

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • java正则表达式验证邮箱、电话号码示例

    下面的代码使用正则表达式验证输入格式包括了验证邮箱和验证手机号码 复制代码 代码如下: package com.firewolf.utils; import java.util.regex.Matcher; import java.util.regex.Pattern; /**  * 使用正则表达式验证输入格式  * @author liuxing  *  */ public class RegexValidateUtil {  public static void main(String[]

  • Java 随机生成验证码(支持大小写字母、数字、随机字体)的实例

    代码如下所示: 复制代码 代码如下: package com.hoo.util; import java.awt.Color;  import java.awt.Font;  import java.awt.Graphics;  import java.awt.image.BufferedImage;  import java.util.Random; import javax.imageio.ImageIO;  import javax.servlet.http.HttpServletRequ

  • java 图片验证码的实现代码

    复制代码 代码如下: makeCertPic.java package pic; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.OutputStream; import java.util.Random; import javax.imagei

  • java正则表达式表单验证类工具类(验证邮箱、手机号码、qq号码等)

    java使用正则表达式进行表单验证工具类,可以验证邮箱.手机号码.qq号码等 复制代码 代码如下: package util; import java.util.regex.Matcher;import java.util.regex.Pattern; /** * 使用正则表达式进行表单验证 *  */ public class RegexValidateUtil {    static boolean flag = false;    static String regex = ""

  • java中servlet实现登录验证的方法

    login.java: 复制代码 代码如下: package com.ncu;import java.io.PrintWriter; import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class login extends HttpServlet{ public void do

  • java用户名密码验证示例代码分享

    类:NameII    权限:public方法:main    权限:public 参数:name,password,denglu,i;参数介绍:name,数据类型 String ,用来存储一个从 input 中获取的值,在本程序当中用作用户名的存放:password,数据类型 String ,用来存储一个从 input 中获取的值,在本程序当中用作密码的存放:denglu,数据类型 boolean,用来存储默认账户的登录状态,true 表示登录成功,false 表示尚未登录:i,数据类型 in

  • java登录验证码实现代码

    VerifyCodeServlet.java类: 复制代码 代码如下: package com.spring.controller;import java.awt.Color;         import java.awt.Font;         import java.awt.Graphics2D;         import java.awt.image.BufferedImage;         import java.util.Random;         import ja

  • Java注册邮箱激活验证实现代码

    最近从项目分离出来的注册邮箱激活功能,整理一下,方便下次使用 RegisterValidateService.java 复制代码 代码如下: package com.app.service.impl; import java.text.ParseException;import java.util.Date; import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stere

  • Java实现验证码具体代码

    这里实现我使用到了struts2模拟一个登录功能来验证java实现的验证码功能. Java实现验证码的步骤: 1.创建RandomImageGenerator.java类,该类实现验证码图片的生成 2.创建一个servlet类,RandomImageServlet.java,将生成的验证码输出到页面 3.创建一个Action类,LoginAction.java,控制登录 4.配置struts.xml一个web.xml文件 5.编写页面 具体实现用代码表达 1.创建RandomImageGener

  • java validation 后台参数验证的使用详解

    一.前言 在后台开发过程中,对参数的校验成为开发环境不可缺少的一个环节.比如参数不能为null,email那么必须符合email的格式,如果手动进行if判断或者写正则表达式判断无意开发效率太慢,在时间.成本.质量的博弈中必然会落后.所以把校验层抽象出来是必然的结果,下面说下几种解决方案. 二.几种解决方案 1.struts2的valid可以通过配置xml,xml中描述规则和返回的信息,这种方式比较麻烦.开发效率低,不推荐 2.validation bean 是基于JSR-303标准开发出来的,使

  • java 用泛型参数类型构造数组详解及实例

    java 用泛型参数类型构造数组详解及实例 前言: 前一阵子打代码的时候突然想到一个问题.平时我们的数组都是作为一个参数传入方法中的,如果我们要想在方法中创建一个数组怎么样呢?在类型明确的情况下,这是没什么难度的.如果我们传入的参数是泛型类型的参数呢? public static <T> T[] creArray (T obj){ T[] arr = new T[10]; } 像上面这种用T来直接new数组的方法是错误的,会编译时出现一个:Cannot create a generic arr

  • SpringBoot + validation 接口参数校验的思路详解

    有参数传递的地方都少不了参数校验.在web开发中,前端的参数校验是为了用户体验,后端的参数校验是为了安全.试想一下,如果在controller层中没有经过任何校验的参数通过service层.dao层一路来到了数据库就可能导致严重的后果,最好的结果是查不出数据,严重一点就是报错,如果这些没有被校验的参数中包含了恶意代码,那就可能导致更严重的后果. 实践 一.引入依赖 <!--引入spring-boot-starter-validation--> <dependency> <gr

  • Java Controller实现参数验证与统一异常处理流程详细讲解

    目录 一,前期数据及类准备 1.1 统一状态码 1.2 统一返回格式 1.3 自定义接口API异常类 1.4 参数封装类 二,参数验证 2.1 pom.xml 2.2 修改参数封装类 2.3 controller 2.4 测试 三,统一异常处理 3.1 方法参数验证异常处理 3.2 其他异常处理 最近开发了比较多的接口,因为没有可参考的案例,所以一开始一直按照我的理解进行开发.开发多了发现自己每个结果都写了相同的代码:try() {} catch() {}, 和关于参数判空的:StringUti

  • Java身份证验证方法实例详解

    Java身份证验证方法实例详解 身份证号码验证 1.号码的结构 公民身份号码是特征组合码,由十七位数字本体码和一位校验码组成.排列顺序从左至右依次为:六位数字地址码, 八位数字出生日期码,三位数字顺序码和一位数字校验码. 2.地址码(前六位数) 表示编码对象常住户口所在县(市.旗.区)的行政区划代码,按GB/T2260的规定执行. 3.出生日期码(第七位至十四位) 表示编码对象出生的年.月.日,按GB/T7408的规定执行,年.月.日代码之间不用分隔符. 4.顺序码(第十五位至十七位) 表示在同

  • SpringBoot常见get/post请求参数处理、参数注解校验及参数自定义注解校验详解

    目录 springboot常见httpget,post请求参数处理 PathVaribale获取url路径的数据 RequestParam获取请求参数的值 注意 GET参数校验 POSTJSON参数校验 自定义注解校验 总结 spring boot 常见http get ,post请求参数处理 在定义一个Rest接口时通常会利用GET.POST.PUT.DELETE来实现数据的增删改查:这几种方式有的需要传递参数,后台开发人员必须对接收到的参数进行参数验证来确保程序的健壮性 GET一般用于查询数

  • java 中maven pom.xml文件教程详解

    maven pom.xml文件教程详解,具体内容如下所示: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.x

  • SpringBoot集成JWT实现登陆验证的方法详解

    1:首先,我们需要在项目中导入两个依赖: <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.10.3</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifa

  • java中Executor,ExecutorService,ThreadPoolExecutor详解

    java中Executor,ExecutorService,ThreadPoolExecutor详解 1.Excutor 源码非常简单,只有一个execute(Runnable command)回调接口 public interface Executor { /** * Executes the given command at some time in the future. The command * may execute in a new thread, in a pooled thre

  • java中注解机制及其原理的详解

    java中注解机制及其原理的详解 什么是注解 注解也叫元数据,例如我们常见的@Override和@Deprecated,注解是JDK1.5版本开始引入的一个特性,用于对代码进行说明,可以对包.类.接口.字段.方法参数.局部变量等进行注解.它主要的作用有以下四方面: 生成文档,通过代码里标识的元数据生成javadoc文档. 编译检查,通过代码里标识的元数据让编译器在编译期间进行检查验证. 编译时动态处理,编译时通过代码里标识的元数据动态处理,例如动态生成代码. 运行时动态处理,运行时通过代码里标识

随机推荐