JSR校验

 

JSR-303校验的基本用法可以参考这篇文章:

     http://www.cnblogs.com/yangzhilong/p/3724967.html

 

这里讲一下自定义校验注解的用法;

1.定义一个注解

@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ValidNumChecker.class)
@Documented
public @interface ValidNum {

    String message() default "the num is invalid";

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

    Class<? extends Payload>[] 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<ValidNum, Integer> {

    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 extends Annotation, T> {  //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.
 */
@NoArgsConstructor
public 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.
 */
@RestController
public class PersonController {

    @RequestMapping(value = "jsr", method = RequestMethod.POST)
    @ResponseBody
    public String jsrValid(@Valid Person person, BindingResult result) {
        
        List<ObjectError> allErrors = result.getAllErrors();
        if (allErrors != null && !allErrors.isEmpty()) {
            Iterator<ObjectError> errorIterator = allErrors.iterator();
            while (errorIterator.hasNext()) {
                ObjectError error = errorIterator.next();
                return error.getDefaultMessage();
            }
        }
        return person.toString();
    }

}

说明:BindingResult result为接收错误信息的对象,若没有,则校验不通过直接抛出异常,通过这个对象可以拿到异常信息;

5.页面部分

<form action="/river/jsr" onsubmit="" method="post" enctype="application/x-www-form-urlencoded">
    id" <input name="id">
    age  <input name="age">
    hight <input name="hight">
    weight  <input name="weight">
    <input type="submit" value="123">
</form>

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.
 */
@RestController
public class PersonController {
    @Autowired
    private Validator validator;

    @RequestMapping(value = "jsr", method = RequestMethod.POST)
    @ResponseBody
    public String jsrValid(Person person) {
        Set<ConstraintViolation<Person>> validate = validator.validate(person);
        if (validate !=null &&! validate.isEmpty()){
            Iterator<ConstraintViolation<Person>> iterator = validate.iterator();
            return iterator.next().getMessage();
        }
        return person.toString();
    }

}

结果不发生变化;

其中调用校验的方法

Set<ConstraintViolation<Person>> validate = validator.validate(person);
        if (validate !=null &&! validate.isEmpty()){
            Iterator<ConstraintViolation<Person>> iterator = validate.iterator();
            return iterator.next().getMessage();
        }

我们可以提出来单独一个方法,每次进入后首先调用校验方法;

9.AOP

这里应该很多人都想到了,进一步的我们可以写成一个aop,前置通知去做这一步的校验,切点打在要加入校验的方法上或者所有有该对象接收的方法上;

 

好了,就讲到这里吧,有些细节可以参考下面的链接;

这篇文章:http://clongjava.iteye.com/blog/1317649

转载于:https://my.oschina.net/JackieRiver/blog/1553639

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值