SpringMVC(八)使用@Validated注解实现后台表单校验

 

 

 

 

 

 


依赖jar

          
            javax.validation  
            validation-api  
            1.1.0.Final  
          
          
            org.hibernate  
            hibernate-validator  
            5.2.1.Final  
        

 @valid,java的jsr303声明了这类接口,hibernate-validator对接口进行实现

配置

1. 配置校验器

 
    
        
        
    
    
    
    
        
        
            
                classpath:validationMessageSource
            
        
        
        
        
        
    

2.  将校验器配置到处理器适配器中

 
 

 

JSR303定义的校验类型

空检查

@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 对象是否符合正则表达式的规则

 

数值检查,建议使用在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=) Checks whether the annotated value lies between (inclusive) the specified minimum and maximum.

@Range(min=10000,max=50000,message="range.bean.wage")
private BigDecimal wage;

 

@Valid 递归的对关联对象进行校验, 如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验.(是否进行递归验证)

@CreditCardNumber信用卡验证

@Email  验证是否是邮件地址,如果为null,不进行验证,算通过验证。

@ScriptAssert(lang= ,script=, alias=)

@URL(protocol=,host=, port=,regexp=, flags=)

需要注意的是,NotEmpty,NotNull,NotBlank的区别

@NotEmpty 用在集合上

@NotNull用在基本类型上

@NotBlank用在String上

如何使用

创建一个校验器的分组类

分组类设置到注解的groups属性上,表示只有存在这个分组类,才回去校验

//自定义接口类,用于校验分组
public interface ValidateGroup {

}

创建一个pojo类

对于类中需要校验的字段,加上需要的校验注解

public class User implements Serializable{
	private static final long serialVersionUID = 1L;
	@NotBlank(groups={VolidateGroup.class},message="{user.id.is.notnull}")
	private String id;
	private String usercode;
	@NotBlank(message="{user.name.is.notnull}")
	@Length(max=30,min=1,message="{user.name.length.error}")
	private String username;
	private String password;
	private String salt;
	private String locked;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getUsercode() {
		return usercode;
	}
	public void setUsercode(String usercode) {
		this.usercode = usercode;
	}
	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 getSalt() {
		return salt;
	}
	public void setSalt(String salt) {
		this.salt = salt;
	}
	public String getLocked() {
		return locked;
	}
	public void setLocked(String locked) {
		this.locked = locked;
	}
	}

controller中触发参数校验

1. 在提交的校验pojo前面加上@Valid注解,BindingResult的hasError方法检查是否字段校验失败,并获取到校验失败的信息

2. 注解@Validated属性value上设置分组类的信息,只有groups属性上存在分组类,就会生效

  下面的add方法中,id的校验和其他默认的校验都生效

   update方法中,不会校验id,分组类只设置了default.class(pojo的校验注解上没有指定groups的值,默认都是default.class)

@Controller
public class UserController {
	private static final Logger logger = LoggerFactory.getLogger(UserController.class);
	@RequestMapping(value="/add_user.action",method=RequestMethod.POST)
	public String add(Model model,BindingResult result,
			@RequestBody @Validated(value={ValidateGroup.class,Default.class}) User user){
		//需要在controller的形参中,对需要校验的对象加上@validated注解
		//获取校验信息
		if (result.hasErrors()) {
            if (model != null) {
                FieldError error = result.getFieldErrors().get(0);// 为了避免大量的校验在前端堆积,影响用户体验,只返回一个错误提示
                logger.debug("validate error: " + error.getDefaultMessage());
                model.addAttribute("error", error.getDefaultMessage());
            }
        }
		//省略
		return "redirect:list.action";
	}
	@RequestMapping(value="/update_user.action",method=RequestMethod.PUT)
	public String update(Model model,BindingResult result,@RequestBody @Validated(value={Default.class}) User user){
		//省略....
		return "";
	}
}

错误信息的展示,前段使用thymeleaf模板的话,可以使用th:error输出错误信息。

自定义校验注解

@Retention(RetentionPolicy.RUNTIME)
@Target(value={ElementType.FIELD})
@Constraint(validatedBy=PassValidation.class)
public @interface PasswordValidate {
	  //默认消息
	  String message() default "请输入8位小写英文字母";
     //分组
	    Class[] groups() default { };
	 //负载
	   Class[] payload() default { };

}

public class PassValidation implements ConstraintValidator{
	@Override
	public void initialize(Annotation arg0) {
		
	}
	@Override
	public boolean isValid(String str, ConstraintValidatorContext context) {
		//密码是小写的8位字母,通过校验
		if(str.matches("[a-z]{8}")){
			return true;
		}
		return false;
	}

}

硬编码校验

如果注解@Valid失效情况,可以使用下面方式进行校验

 /**
     * 返回空,表示校验成功,否则校验失败
     * @param object
     * @param 
     * @return
     */
    private  String  validateParam(T object){
        Validator validator =  Validation.buildDefaultValidatorFactory().getValidator();
        Set>  set =  validator.validate(object);
        if(set!=null&&set.size()>0){
            StringBuilder sb = new StringBuilder();
            for (ConstraintViolation ct: set
            ) {
               if(ct.getMessage()!=null&&ct.getMessage().trim().length()>0){
                   sb.append("field:"+ct.getPropertyPath()+",error message:"+ct.getMessage());
               }

            }
            return sb.toString();
        }
        return null;
    }

使用AOP的方式实现校验

对需要参数校验的方法,织入增强,减少代码

@Aspect
@Component
public class CustomerValidatorAOP {
    @Before("execution(* com.example.chapter_1_web.controller.*.update*(..))")
    public void validatorBook(JoinPoint point) {
        //返回目标方法的参数
        Object[] objects =  point.getArgs();
        //获取目标方法签名
        MethodSignature methodSignature = (MethodSignature) point.getSignature();
        Method method = methodSignature.getMethod();
        //获取方法注解
        Annotation[] annotationList = method.getAnnotations();
        //参数注解
        Annotation[][] argAnnotations = method.getParameterAnnotations();
        //参数名称
        String[] argNames = methodSignature.getParameterNames();
        Validator validator =  Validation.buildDefaultValidatorFactory().getValidator();
        for(int i = 0;i

参考博客:

https://blog.csdn.net/DuShiWoDeCuo/article/details/79080237

https://my.oschina.net/itblog/blog/211693

http://exceptioneye.iteye.com/blog/1305040

 

你可能感兴趣的:(SpringMVC)