您的位置:首页 > 编程语言 > Java开发

SpringBoot--JSR303验证传入参数

2017-05-19 11:20 295 查看
程序工具类:

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)//此处指定了注解的实现类为ListNotHasNullValidatorImpl
public @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
*/
@Service
public 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
@Component
public 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")
@Validated
public 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: