SpringBoot的JSR-303数据校验

一、 JSR-303 介绍

  JSR 是Java Specification Requests 的缩写,是指向 JCP(Java Community Process) 提出新增一个标准化技术规范的正式请求。
  任何人都可以提交 JSR,以向 Java 平台增添新的 API 和服务,已审核通过的规范涉及 Java 各个领域,有兴趣可以了解一下。
  Bean Validation 是一个运行时的数据验证框架,为 JavaBean 验证定义了相应的元数据模型和 API。
  默认的元数据是 Java Annotations,当然也可以使用 XML 可以对已存在的元数据信息进行覆盖和扩展。
  在应用中通过使用 Bean Validation 或是你自己定义的 constraint,例如 @NotNull, @Max, @ZipCode, 就可以确保数据模型的正确性。
  constraint 可以注解到字段,getter 方法,类或者接口上面。对于一些特定的需求,用户可以很容易的开发定制化的 constraint。
  这里只列举了 javax.validation 包下的注解,同理在 spring-boot-starter-web 包中也存在 hibernate-validator 验证包,里面包含了一些 javax.validation 没有的注解,有兴趣的可以看看 https://www.ibm.com/developerworks/cn/java/j-lo-jsr303/

SR-303数据校验分为:普通参数属性验证 和 对象的验证

二、普通参数属性验证

类上面配置@Validated,需要校验的参数配置上对应的注解,当方法被调用的时候自动对参数校验,如果校验的结果不通过就抛出异常,会打印配置的message的内容。

@Service
@Validated
public class RedisService {

	@Autowired
	JedisPool jedisPool;

	public <T> T get(@NotNull(message = "rh不能为空") RedisHelper rh, String key, Class<T> clazz) {
		if (clazz == null||key==null||rh==null) {
			return null;
		}
		Jedis jedis = null;
		try {
			jedis = jedisPool.getResource();
			// 生成真正的key
			String realKey = rh.prefix() + key;
			String res = jedis.get(realKey);
			T t = parseStringToBean(res, clazz);
			return t;
		} finally {// 使用完后返回到连接池
			returnToPool(jedis);
		}
	}
}

结合AOP环绕增强可以进行异常的处理。

三、对象的验证

@RequestMapping("doLogin")
	@ResponseBody
	Result<String> doLogin(@Valid LoginVo lv,HttpServletResponse resp,BindingResult bindingResult) {
		logger.info(lv.toString());
		if (bindingResult.hasErrors()) {
            List<ObjectError> errorList = bindingResult.getAllErrors();
		}
		String token=sus.login(resp,lv);
		return Result.success(token);
	}
package pers.lbw.seckill.vo;

import javax.validation.constraints.NotNull;

import org.hibernate.validator.constraints.Length;

import pers.lbw.seckill.validator.IsMobile;

public class LoginVo {
	
	@NotNull
	@IsMobile//我们自定义的验证器
	private String mobile;
	
	@NotNull
	@Length(min=6)
	private String password;
	
	public String getMobile() {
		return mobile;
	}
	public void setMobile(String mobile) {
		this.mobile = mobile;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	@Override
	public String toString() {
		return "LoginVo [mobile=" + mobile + ", password=" + password + "]";
	}
	
}

被校验的参数上用@Valid注解,被校验成参数类中用注解配置规则,当然也可以自定义规则,如上面用的@IsMobile自定义注解。
通过bindingResult进行异常的处理。当然也可以用结合AOP环绕增强可以进行异常的处理。

四、自定义注解

package pers.lbw.seckill.validator;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

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, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = { IsMobileValidator.class })//自定义验证器类
public @interface IsMobile {
	
	boolean reqired() default true;
	
	String message() default "手机号码格式错误";//校验非法的时候返回的信息

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

	Class<? extends Payload>[] payload() default { };
	
}
package pers.lbw.seckill.validator;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

import org.springframework.util.StringUtils;

import pers.lbw.seckill.util.ValidatorUtil;
//自定义验证器
//IsMobile是被校验的注解,String是用的时候IsMobile修饰字段的类型,Constraint:约束
//所以这里是对String字段上加了IsMobile注解的进行参数校验
//校验注解在String类上,可以有多个验证器分别校验不同类型,但记得在IsMobile的validatedBy 那也要配置多个
public class IsMobileValidator implements ConstraintValidator<IsMobile,String>{
	private boolean required;
	
	@Override
	//这里的value就是注解所在字段的值
	public boolean isValid(String value, ConstraintValidatorContext context) {
		if(required) {
			return ValidatorUtil.isMobile(value);//偷个懒,直接用我们之前写的来校验
		}else {
			//非必须的话如果为空按照逻辑的话因该返回true,也就是合法
			if(StringUtils.isEmpty(value)) {
				return true;
			}else {
				return ValidatorUtil.isMobile(value);//偷个懒,直接用我们之前写的来校验
			}
		}
	}
	
	@Override
	public void initialize(IsMobile constraintAnnotation) {
		required=constraintAnnotation.reqired();
	}

}

基本校验规则

空检查
@Null 验证对象是否为null
@NotNull 验证对象是否不为null, 无法查检长度为0的字符串
@NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.
@NotEmpty 检查约束元素是否为NULL或者是EMPTY.

Booelan检查
@AssertTrue 验证 Boolean 对象是否为 true
@AssertFalse 验证 Boolean 对象是否为 false

长度检查
@Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内
@Length(min=, max=) Validates that the annotated string is between min and max included.

日期检查
@Past 验证 Date 和 Calendar 对象是否在当前时间之前,验证成立的话被注释的元素一定是一个过去的日期
@Future 验证 Date 和 Calendar 对象是否在当前时间之后 ,验证成立的话被注释的元素一定是一个将来的日期
@Pattern 验证 String 对象是否符合正则表达式的规则,被注释的元素符合制定的正则表达式,regexp:正则表达式 flags: 指定 Pattern.Flag 的数组,表示正则表达式的相关选项。

数值检查
建议使用在Stirng,Integer类型,不建议使用在int类型上,因为表单值为“”时无法转换为int,但可以转换为Stirng为”“,Integer为null
@Min 验证 Number 和 String 对象是否大等于指定的值
@Max 验证 Number 和 String 对象是否小等于指定的值
@DecimalMax 被标注的值必须不大于约束中指定的最大值. 这个约束的参数是一个通过BigDecimal定义的最大值的字符串表示.小数存在精度
@DecimalMin 被标注的值必须不小于约束中指定的最小值. 这个约束的参数是一个通过BigDecimal定义的最小值的字符串表示.小数存在精度
@Digits 验证 Number 和 String 的构成是否合法
@Digits(integer=,fraction=) 验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度。
@Range(min=, max=) 被指定的元素必须在合适的范围内
@Range(min=10000,max=50000,message=”range.bean.wage”)
@Valid 递归的对关联对象进行校验, 如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验.(是否进行递归验证)
@CreditCardNumber信用卡验证
@Email 验证是否是邮件地址,如果为null,不进行验证,算通过验证。
@ScriptAssert(lang= ,script=, alias=)
@URL(protocol=,host=, port=,regexp=, flags=)

你可能感兴趣的:(深度好文)