JSR-303校验的基本用法可以参考这篇文章:
http://www.cnblogs.com/yangzhilong/p/3724967.html
这里讲一下自定义校验注解的用法;
1.定义一个注解
@Target({ElementType.FIELD, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Constraint(validatedBy = ValidNumChecker.class)@Documentedpublic @interface ValidNum { String message() default "the num is invalid"; Class [] groups() default {}; Class [] payload() default {};}
说明:重点在于 :
@Constraint(validatedBy = ValidNumChecker.class)
ValidNumChecker这个类是实际校验的方法;
2.编写实际校验的类
package com.river.jsr.annotation;import javax.validation.ConstraintValidator;import javax.validation.ConstraintValidatorContext;/** * Created by Administrator on 2017/10/19. */public class ValidNumChecker implements ConstraintValidator{ private ValidNum validNum; @Override public void initialize(ValidNum validNum) { this.validNum = validNum; } @Override public boolean isValid(Integer value, ConstraintValidatorContext constraintValidatorContext) { if (value < 0 || value > 100) { return false; } constraintValidatorContext.disableDefaultConstraintViolation(); constraintValidatorContext.buildConstraintViolationWithTemplate(this.validNum.message()).addConstraintViolation(); return true; }}
说明:
这个类ValidNumChecker要实现接口
public interface ConstraintValidator { //A为自定义注解ValidNum,T为校验数据的类型; void initialize(A var1); //初始化方法, boolean isValid(T var1, ConstraintValidatorContext var2); //验证的逻辑,返回false则验证不通过}
3.实体类中应用
package com.river.jsr.entity;import com.river.jsr.annotation.ValidNum;import lombok.Getter;import lombok.NoArgsConstructor;import lombok.Setter;/** * Created by Administrator on 2017/10/18. */@NoArgsConstructorpublic class Person { @Getter @Setter @ValidNum(message = "id 超出范围") //在这里实践 private Integer id; @Getter @Setter private Integer age; @Getter @Setter private Integer hight; @Getter @Setter private Integer weight; }
4.Controller接收参数并验证;
package com.river.jsr.controller;import com.alibaba.fastjson.JSON;import com.river.jsr.entity.Person;import org.springframework.validation.BindingResult;import org.springframework.validation.ObjectError;import org.springframework.web.bind.annotation.*;import javax.validation.Valid;import java.util.Iterator;import java.util.List;/** * Created by Administrator on 2017/10/18. */@RestControllerpublic class PersonController { @RequestMapping(value = "jsr", method = RequestMethod.POST) @ResponseBody public String jsrValid(@Valid Person person, BindingResult result) { ListallErrors = result.getAllErrors(); if (allErrors != null && !allErrors.isEmpty()) { Iterator errorIterator = allErrors.iterator(); while (errorIterator.hasNext()) { ObjectError error = errorIterator.next(); return error.getDefaultMessage(); } } return person.toString(); }}
说明:BindingResult result为接收错误信息的对象,若没有,则校验不通过直接抛出异常,通过这个对象可以拿到异常信息;
5.页面部分
6.验证:
当输入参数均为10时,页面返回Person{id=10, age=1, hight=1, weight=1}
当id输入值为1000时,校验不通过,页面得到:id 超出范围
说明:提示信息"id 超出范围"可以在Person的字段加上自定义注解后自定义message属性,也可以使用默认模板在
org\hibernate\hibernate-validator\5.3.5.Final\hibernate-validator-5.3.5.Final.jar!\org\hibernate\validator\ValidationMessages_zh_CN.properties该路径下;
也可以将此文件copy到resource目录下自定义模板;
7.自定义模板
修改自定义注解的message的default,
当default为字符串是被认为是默认提示消息;
当为{"key"}时,被认为引入了模板,在模板中
key = \u9700\u8981\u662F\u4E00\u4E2A\u5408\u6CD5\u7684URL
通过key找到模板中的消息;
8.Validator直接注入
controller里面的校验这样写其实很麻烦,要是有很多很不方便;
我们可以改用这样的方式:
package com.river.jsr.controller;import com.river.jsr.entity.Person;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.validation.BindingResult;import org.springframework.validation.ObjectError;import org.springframework.web.bind.annotation.*;import javax.validation.ConstraintViolation;import javax.validation.Valid;import javax.validation.Validator;import java.util.Iterator;import java.util.List;import java.util.Set;/** * Created by Administrator on 2017/10/18. */@RestControllerpublic class PersonController { @Autowired private Validator validator; @RequestMapping(value = "jsr", method = RequestMethod.POST) @ResponseBody public String jsrValid(Person person) { Set> validate = validator.validate(person); if (validate !=null &&! validate.isEmpty()){ Iterator > iterator = validate.iterator(); return iterator.next().getMessage(); } return person.toString(); }}
结果不发生变化;
其中调用校验的方法
Set> validate = validator.validate(person); if (validate !=null &&! validate.isEmpty()){ Iterator > iterator = validate.iterator(); return iterator.next().getMessage(); }
我们可以提出来单独一个方法,每次进入后首先调用校验方法;
9.AOP
这里应该很多人都想到了,进一步的我们可以写成一个aop,前置通知去做这一步的校验,切点打在要加入校验的方法上或者所有有该对象接收的方法上;
好了,就讲到这里吧,有些细节可以参考下面的链接;
这篇文章:http://clongjava.iteye.com/blog/1317649