SpringBoot--JSR303验证传入参数

来源:互联网 发布:搜狗小说书架数据恢复 编辑:程序博客网 时间:2024/06/05 03:35

程序工具类:

package com.liutao.utilitys;import org.springframework.http.HttpStatus;import org.springframework.validation.BindingResult;import org.springframework.validation.ObjectError;import javax.servlet.http.HttpServletResponse;import java.util.List;/** * 参数验证工具类 * * @author LIUTAO * @version 2017/5/19 * @see * @since */public class ValidateUtility {    /**     * 判断是否有验证错误信息     * @param result     * @return     */    public static String judgeValidate(BindingResult result, HttpServletResponse response) {        if(result.hasErrors()){            List<ObjectError> list = result.getAllErrors();            StringBuilder stringBuilder = new StringBuilder();            for(ObjectError  error:list){                stringBuilder.append("\n"+error.getDefaultMessage());            }            response.setStatus(HttpStatus.BAD_REQUEST.value());            return stringBuilder.toString();        }        return "ok";    }}


一、常用的校验注解
(1)常用标签
@Null  被注释的元素必须为null
@NotNull  被注释的元素不能为null
@AssertTrue  被注释的元素必须为true
@AssertFalse  被注释的元素必须为false
@Min(value)  被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value)  被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value)  被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value)  被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max,min)  被注释的元素的大小必须在指定的范围内。
@Digits(integer,fraction)  被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past  被注释的元素必须是一个过去的日期
@Future  被注释的元素必须是一个将来的日期
@Pattern(value) 被注释的元素必须符合指定的正则表达式。
@Email 被注释的元素必须是电子邮件地址
@Length 被注释的字符串的大小必须在指定的范围内
@NotEmpty  被注释的字符串必须非空
@Range  被注释的元素必须在合适的范围内
(2)示例

package com.liutao.model;import org.hibernate.validator.constraints.Length;import org.hibernate.validator.constraints.NotEmpty;/** * 用户数据模板 * * @author LIUTAO * @version 2017/3/29 * @see * @since */public class User {    @NotEmpty(message = "姓名不能为空")    private String name;    private Integer age;    @NotEmpty(message = "密码不能为空")    @Length(min = 6,max = 20,message = "密码长度应该大于6位小于20位")    private String password;    public User() {    }    public User(String name, Integer age, String password) {        this.name = name;        this.age = age;        this.password = password;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Integer getAge() {        return age;    }    public void setAge(Integer age) {        this.age = age;    }    public String getPassword() {        return password;    }    public void setPassword(String password) {        this.password = password;    }    @Override    public String toString() {        return "User{" +                "name='" + name + '\'' +                ", age=" + age +                ", password='" + password + '\'' +                '}';    }}

package com.liutao.controller;import com.liutao.model.User;import com.liutao.utilitys.ValidateUtility;import com.wordnik.swagger.annotations.Api;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.validation.BindingResult;import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletResponse;import javax.validation.Valid;/** * 用户控制层 * * @author LIUTAO * @version 2017/3/29 * @see */@RestController@Api(value = "test")@RequestMapping("/liutao/v1")public class UserController {    private Logger logger = LoggerFactory.getLogger(UserController.class);    @PostMapping(value = "/user")    public    @ResponseBody    String postUser(@Valid @RequestBody User user, BindingResult result, HttpServletResponse response) {        return ValidateUtility.judgeValidate(result,response);    }}
以上运行程序进行相应的测试就可以看到返回对应的错误信息。

二、自定义验证标签
针对某些需求,现有的标签无法满足我们的需要的时候,就需要我们定义自己的标签。实例如下:
(1)定义标签

package com.liutao.annotation;import javax.validation.Constraint;import javax.validation.Payload;import java.lang.annotation.*;import static java.lang.annotation.ElementType.*;import static java.lang.annotation.RetentionPolicy.RUNTIME;/** * 演示自定义参数校验注解 * 校验list集合中是否有null元素 * * @author LIUTAO * @version 2017/5/19 * @see */@Target({ANNOTATION_TYPE, METHOD, ElementType.FIELD})@Retention(RUNTIME)@Documented@Constraint(validatedBy = ListNotHasNullValidatorImpl.class)//此处指定了注解的实现类为ListNotHasNullValidatorImplpublic @interface ListNotHasNull {    /**     * 添加value属性,可以作为校验时的条件,若不需要,可去掉此处定义     */    int value() default 0;    String message() default "List集合中不能含有null元素";    Class<?>[] groups() default {};    Class<? extends Payload>[] payload() default {};    /**     * 定义List,为了让Bean的一个属性上可以添加多套规则     */    @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})    @Retention(RUNTIME)    @Documented    @interface List {        ListNotHasNull[] value();    }}
(2)标签验证实现类

package com.liutao.annotation;import org.springframework.stereotype.Service;import javax.validation.ConstraintValidator;import javax.validation.ConstraintValidatorContext;import java.util.List;/** * 演示实现ListNotHasNull校验注解的实现类 * * @author LIUTAO * @version 2017/5/19 * @see */@Servicepublic class ListNotHasNullValidatorImpl implements ConstraintValidator<ListNotHasNull, List> {    private int value;    @Override    public void initialize(ListNotHasNull constraintAnnotation) {        //传入value 值,可以在校验中使用        this.value = constraintAnnotation.value();    }    public boolean isValid(List list, ConstraintValidatorContext constraintValidatorContext) {        for (Object object : list) {            if (object == null) {                //如果List集合中含有Null元素,校验失败                return false;            }        }        return true;    }}
(3)所需的数据模型

package com.liutao.model;/** * 员工数据模型 * * @author LIUTAO * @version 2017/5/19 * @see */public class Employee {    private String name;    private String age;    private String cellPhone;    public Employee() {    }    public Employee(String name, String age, String cellPhone) {        this.name = name;        this.age = age;        this.cellPhone = cellPhone;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getAge() {        return age;    }    public void setAge(String age) {        this.age = age;    }    public String getCellPhone() {        return cellPhone;    }    public void setCellPhone(String cellPhone) {        this.cellPhone = cellPhone;    }    @Override    public String toString() {        return "Employee{" +                "name='" + name + '\'' +                ", age='" + age + '\'' +                ", cellPhone='" + cellPhone + '\'' +                '}';    }}

package com.liutao.model;import com.liutao.annotation.ListNotHasNull;import org.hibernate.validator.constraints.Length;import org.hibernate.validator.constraints.NotEmpty;import javax.validation.Valid;import java.util.List;/** * 公司数据模型 * * @author LIUTAO * @version 2017/5/19 * @see * @since */public class Company {    @NotEmpty(message = "公司名字不能为空")    private String name;    @Length(min = 2,max = 20,message = "地址信息必须在2到20个字符之间")    private String address;    @NotEmpty(message = "员工信息不能为空")    @ListNotHasNull    @Valid    private List<Employee> employees;    public Company() {    }    public Company(String name, String address, List<Employee> employees) {        this.name = name;        this.address = address;        this.employees = employees;    }    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 List<Employee> getEmployees() {        return employees;    }    public void setEmployees(List<Employee> employees) {        this.employees = employees;    }    @Override    public String toString() {        return "Company{" +                "name='" + name + '\'' +                ", address='" + address + '\'' +                ", employees=" + employees +                '}';    }}
从上面的Company我们可以看见已经使用了自定义的@ListNotHasNull标签
(4)测试Controller

package com.liutao.controller;import com.liutao.model.Company;import com.liutao.utilitys.ValidateUtility;import com.wordnik.swagger.annotations.Api;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.validation.BindingResult;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletResponse;import javax.validation.Valid;/** * 公司Controller * * @author LIUTAO * @version 2017/5/19 * @see */@RestController@Api(value = "test company")@RequestMapping("/liutao/v1")public class CompanyController {    private Logger logger = LoggerFactory.getLogger(UserController.class);    @PostMapping(value = "/company")    public String postCompany(@Valid @RequestBody Company company, BindingResult result,HttpServletResponse response){        return ValidateUtility.judgeValidate(result,response);    }}
上面的程序进行相应的测试后就可以看见相应的错误信息。
三、分组验证
当我们针对同一个model的校验不一样的时候该怎么办?比如针对同一个model的添加和修改的时候?这个时候我们就需要采用分组验证。
(1)定义分别代表修改和添加校验规则的接口

package com.liutao.validateInterface;/** * person模型新增时的参数校验规则 * * @author LIUTAO * @version 2017/5/19 * @see * @since */public interface PersonAddView {}

package com.liutao.validateInterface;/** * person模型修改时的参数校验规则 * * @author LIUTAO * @version 2017/5/19 * @see * @since */public interface PersonUpdateView {}
(2)在数据模型上添加相应的校验规则

package com.liutao.model;import com.liutao.validateInterface.PersonAddView;import com.liutao.validateInterface.PersonUpdateView;import org.hibernate.validator.constraints.Length;import javax.validation.constraints.Max;import javax.validation.constraints.Min;import javax.validation.constraints.NotNull;/** * person数据模型 * * @author LIUTAO * @version 2017/5/19 * @see */public class Person {    private Long id;    /**     * 针对验证标签里面添加groups说明仅仅在特定的验证规则里面起作用,如果不加,那么就在默认的验证规则里面起作用。     */    @NotNull(groups = {PersonAddView.class},message = "添加的姓名不能为空")    @Length(min = 2,max = 10,groups = {PersonUpdateView.class},message = "修改时的姓名必须在2到10个字符之间")    private String name;    @NotNull(groups = {PersonAddView.class}, message = "添加用户时地址不能为空")    private String address;    @Min(value = 18, groups = {PersonAddView.class}, message = "年龄不能低于18岁")    @Max(value = 30, groups = {PersonUpdateView.class}, message = "年龄不能超过30岁")    private Integer age;    public Person() {    }    public Person(Long id, String name, String address, Integer age) {        this.id = id;        this.name = name;        this.address = address;        this.age = age;    }    public Long getId() {        return id;    }    public void setId(Long id) {        this.id = id;    }    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 Integer getAge() {        return age;    }    public void setAge(Integer age) {        this.age = age;    }    @Override    public String toString() {        return "Person{" +                "id=" + id +                ", name='" + name + '\'' +                ", address='" + address + '\'' +                ", age=" + age +                '}';    }}
(3)给参数添加校验

package com.liutao.controller;import com.liutao.model.Person;import com.liutao.utilitys.ValidateUtility;import com.liutao.validateInterface.PersonAddView;import com.liutao.validateInterface.PersonUpdateView;import com.wordnik.swagger.annotations.Api;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.validation.BindingResult;import org.springframework.validation.annotation.Validated;import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpServletResponse;import javax.validation.groups.Default;/** * 人员Controller * * @author LIUTAO * @version 2017/5/19 * @see * @since */@RestController@Api(value = "test person")@RequestMapping("/liutao/v1")public class PersonController {    private Logger logger = LoggerFactory.getLogger(PersonController.class);    /**     * 处@Validated(PersonAddView.class) 表示使用PersonAndView这套校验规则,若使用@Valid 则表示使用默认校验规则,     * 若两个规则同时加上去,则只有第一套起作用     *     * @param person     */    @PostMapping(value = "/person")    public String addPerson(@RequestBody @Validated({PersonAddView.class, Default.class}) Person person, BindingResult result,HttpServletResponse response) {        logger.debug("enter post person");        logger.debug("the information of person :"+ person);        return ValidateUtility.judgeValidate(result,response);    }    /**     * 修改Person对象     * 此处启用PersonModifyView 这个验证规则     * @param person     */    @PutMapping(value = "/person")    public String modifyPerson(@RequestBody @Validated(value = {PersonUpdateView.class}) Person person, BindingResult result,HttpServletResponse response) {        logger.debug("enter put person");        logger.debug("the information of person :"+ person);        return ValidateUtility.judgeValidate(result,response);    }}
根据上面的程序进行测试就可以得到相应的测试结果。
四、Controller方法中的非对象参数验证
如果我们传入的参数没必要进行封装成对象,那么这个时候对参数的校验就得使用参数验证了。

(1)添加参数验证配置类

package com.liutao.config;import org.springframework.context.annotation.Bean;import org.springframework.http.HttpStatus;import org.springframework.stereotype.Component;import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.bind.annotation.ResponseStatus;import javax.validation.ValidationException;/** * 参数验证配置类 * * @author LIUTAO * @version 2017/5/18 * @see */@ControllerAdvice@Componentpublic class GlobalExceptionHandler {    @Bean    public MethodValidationPostProcessor methodValidationPostProcessor() {        return new MethodValidationPostProcessor();    }    @ExceptionHandler    @ResponseBody    @ResponseStatus(HttpStatus.BAD_REQUEST)    public String handle(ValidationException exception) {        return "传入参数不符合要求";    }}

(2)在Controller上添加参数验证

package com.liutao.controller;import com.wordnik.swagger.annotations.Api;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.http.HttpStatus;import org.springframework.validation.annotation.Validated;import org.springframework.web.bind.annotation.*;import javax.validation.constraints.Min;/** * 员工Controller * * @author LIUTAO * @version 2017/5/19 * @see * @since */@RestController@Api(value = "test employee")@RequestMapping("/liutao/v1")@Validatedpublic class EmployeeController {    private Logger logger = LoggerFactory.getLogger(EmployeeController.class);    @GetMapping("/employee")    @ResponseStatus(HttpStatus.OK)    public @ResponseBody    String check(@RequestParam @Min(value = 10,message = "名字长度必须大于10") int age) {        logger.debug("enter employee get");        return "ok";    }}
以上的程序就可以进行相应的测试得到测试结果。

源代码请参考gitHub地址:SpringBoot__validatot






原创粉丝点击