项目基本配置参考文章SpringBoot入门一,使用myEclipse新建一个SpringBoot项目,使用myEclipse新建一个SpringBoot项目即可,此示例springboot升级为2.2.1版本。
1. pom.xml添加AOP支持
如果已经引用了spring-boot-starter-web,就不要需要引用spring-boot-starter-validation了,但Springboot2.3以后的版本则需要单独引用,本例就不再引用
<!-- 引入validation支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
2. 创建接口
分组使用,不分组的话,不需要创建接口,可直接跳过此步
import javax.validation.GroupSequence;
public class ToolInterface {
// 新增使用(配合spring的@Validated功能分组使用)
public interface insert{}
// 更新使用(配合spring的@Validated功能分组使用)
public interface update{}
// 属性必须有这两个分组的才验证(配合spring的@Validated功能分组使用)
@GroupSequence({insert.class, update.class})
public interface all{};
}
3. 创建实体类
groups 指定分组,可属于多个组
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import com.qfx.modules.common.util.ToolInterface;
public class UserVo {
@Min(groups = {ToolInterface.update.class}, value = 1, message = "ID不能小于1")
private int id;
@NotBlank(groups = {ToolInterface.update.class, ToolInterface.insert.class}, message = "用户名不能为空")
private String name;
@NotBlank(groups = {ToolInterface.update.class, ToolInterface.insert.class}, message = "密码不能为空")
@Size(groups = {ToolInterface.update.class, ToolInterface.insert.class}, min = 6, max = 12, message = "密码长度不能小于6,大于12")
private String password;
@Min(value = 1, message = "年龄必须大于1岁")
@Max(value = 200, message = "年龄必须小于200岁")
private int age;
private String remark;
// get、set方法略过...,如果使用Lombok则不需要写get、set方法了,原因你懂的...
}
4. 创建验证信息格式化工具类ToolValidated.java
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import com.qfx.modules.common.vo.MessageBean;
public class ToolValidated {
private static final Logger LOG = LoggerFactory.getLogger(ToolValidated.class);
// 实际使用建议将编码信息放置在一个单独的文件中统一管理
/**
* 操作成功
*/
public static int SUCCESS = 200;
/**
* 参数无效
*/
public static int PARAM_INVALID = 1001;
// =================== Spring validated (建议使用) ===================
/**
* <h5>功能:验证参数信息是否有效</h5>
*
* @param bindingResult
* @return
*/
public static MessageBean myValidate(BindingResult bindingResult) {
MessageBean messageBean = new MessageBean();
if(bindingResult.hasErrors()) {
// 设置验证结果状态码
messageBean.setCode(PARAM_INVALID);
// 获取错误字段信息集合
List<FieldError> fieldErrorList = bindingResult.getFieldErrors();
// 使用TreeSet是为了让输出的内容有序输出(默认验证的顺序是随机的)
Set<String> errorInfoSet = new TreeSet<String>();
for (FieldError fieldError : fieldErrorList) {
// 遍历错误字段信息
errorInfoSet.add(fieldError.getDefaultMessage());
LOG.debug("[{}.{}]{}", fieldError.getObjectName() , fieldError.getField(), fieldError.getDefaultMessage());
}
StringBuffer sbf = new StringBuffer();
for (String errorInfo : errorInfoSet) {
sbf.append(errorInfo);
sbf.append(",");
}
messageBean.setMessage(sbf.substring(0, sbf.length() - 1));
}
return messageBean;
}
}
5. 参数验证
5.1 手动验证
5.1.1 创建测试类TestCtl.java
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson.JSONObject;
import com.qfx.modules.common.util.ToolInterface;
import com.qfx.modules.common.util.ToolValidated;
import com.qfx.modules.common.vo.MessageBean;
import com.qfx.modules.demo.vo.UserVo;
/**
* <h5>描述:实体类参数校验示例</h5>
* 本类示例仅适用于实体类参数校验,方法参数校验请参照TestExtCtl.java中的validatedFive方法
*/
@RestController
@RequestMapping("test")
public class TestCtl {
/**
* <h5>功能:只验证未UserVo中设置group的属性</h5>
* 只验证不需要分组的参数,这里只验证userVo.age
* @param userVo
* @param bindingResult
* @return
*/
@RequestMapping("validatedOne")
public String validatedOne(@Validated() UserVo userVo, BindingResult bindingResult) {
// 验证参数信息是否有效
MessageBean messageBean = ToolValidated.myValidate(bindingResult);
if (ToolValidated.SUCCESS == messageBean.getCode()) {
messageBean.setMessage("哈哈哈,通过验证了");
}
return JSONObject.toJSONString(messageBean);
}
/**
* <h5>功能:只验证UserVo中group为"ToolValidated.insert.class"的属性</h5>
* 验证组为"insert.class"的参数,这里验证userVo.name、验证userVo.password
* @param userVo
* @param bindingResult
* @return
*/
@RequestMapping("validatedTwo")
public String validatedTwo(@Validated(ToolInterface.insert.class) UserVo userVo, BindingResult bindingResult) {
// 验证参数信息是否有效
MessageBean messageBean = ToolValidated.myValidate(bindingResult);
if (ToolValidated.SUCCESS == messageBean.getCode()) {
messageBean.setMessage("哈哈哈,通过验证了");
}
return JSONObject.toJSONString(messageBean);
}
/**
* <h5>功能:只验证UserVo中group为"ToolValidated.update.class"的属性</h5>
* 验证组为"update.class"的参数,这里验证userVo.id、userVo.name、验证userVo.password
* @param userVo
* @param bindingResult
* @return
*/
@RequestMapping("validatedThree")
public String validatedThree(@Validated(ToolInterface.update.class) UserVo userVo, BindingResult bindingResult) {
// 验证参数信息是否有效
MessageBean messageBean = ToolValidated.myValidate(bindingResult);
if (ToolValidated.SUCCESS == messageBean.getCode()) {
messageBean.setMessage("哈哈哈,通过验证了");
}
return JSONObject.toJSONString(messageBean);
}
/**
* <h5>功能:只验证UserVo中同时满足多个group的属性</h5>
* 验证组为"all.class"的参数,all接口包含insert.class和 update.class,
* 因此需要验证同时属于insert.class和 update.class的参数,
* 这里只验证userVo.name、验证userVo.password
* @param userVo
* @param bindingResult
* @return
*/
@RequestMapping("validatedFour")
public String validatedFour(@Validated(ToolInterface.all.class) UserVo userVo, BindingResult bindingResult) {
// 验证参数信息是否有效
MessageBean messageBean = ToolValidated.myValidate(bindingResult);
if (ToolValidated.SUCCESS == messageBean.getCode()) {
messageBean.setMessage("哈哈哈,通过验证了");
}
return JSONObject.toJSONString(messageBean);
}
}
5.1.2 测试
5.2 自动验证
5.2.1 创建一个全局自动处理类ParamVerifyException.java
import java.util.Set;
import java.util.TreeSet;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import com.alibaba.fastjson.JSONObject;
import com.qfx.modules.common.util.ToolValidated;
import com.qfx.modules.common.vo.MessageBean;
/**
* <h5>描述:全局参数验证异常处理</h5>
* 设定执行顺序,只要比全局异常处理类靠前就行,否则会报500或者404错误信息
* 这里的全局异常处理类是MyExceptionHandler.java
*/
@RestControllerAdvice
@Order(Ordered.LOWEST_PRECEDENCE - 1)
public class ParamVerifyException {
private static final Logger LOG = LoggerFactory.getLogger(ParamVerifyException.class);
/**
* <h5>功能:处理普通参数校验失败的异常</h5>
*
* @param ex ConstraintViolationException
* @return
*/
@ExceptionHandler(value = ConstraintViolationException.class)
public String ConstraintViolationException(ConstraintViolationException ex) {
MessageBean messageBean = new MessageBean();
// 使用TreeSet是为了让输出的内容有序输出(默认验证的顺序是随机的)
Set<String> errorInfoSet = new TreeSet<String>();
Set<ConstraintViolation<?>> violations = ex.getConstraintViolations();
if (!violations.isEmpty()) {
// 设置验证结果状态码
messageBean.setCode(ToolValidated.PARAM_INVALID);
for (ConstraintViolation<?> item : violations) {
System.out.println(item.getPropertyPath());
// 遍历错误字段信息
errorInfoSet.add(item.getMessage());
LOG.debug("[{}]{}", item.getPropertyPath(), item.getMessage());
}
StringBuffer sbf = new StringBuffer();
for (String errorInfo : errorInfoSet) {
sbf.append(errorInfo);
sbf.append(",");
}
messageBean.setMessage(sbf.substring(0, sbf.length() - 1));
}
return JSONObject.toJSONString(messageBean);
}
/**
* <h5>功能: 处理实体类参数校验失败的异常</h5>
*
* @param ex BindException
* @return
*/
@ExceptionHandler(value = BindException.class)
public String BindException(BindException bindingResult) {
// 验证参数信息是否有效
MessageBean messageBean = ToolValidated.myValidate(bindingResult);
return JSONObject.toJSONString(messageBean);
}
}
5.2.2 创建测试类TestExtCtl.java
这里没有指定验证信息处理类,全部由ParamVerifyException.java自动拦截处理
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson.JSONObject;
import com.qfx.modules.common.util.ToolInterface;
import com.qfx.modules.common.vo.MessageBean;
import com.qfx.modules.demo.vo.UserVo;
/**
* <h5>描述:实体类参数与普通参数校验示例</h5>
* 采用全局异常处理的方式来进行参数校验
*/
@RestController
@RequestMapping("testExt")
@Validated // @Validated只能作用在类上面
public class TestExtCtl {
/**
* <h5>功能:只验证未UserVo中设置group的属性</h5>
*
* @param userVo
* @return
*/
@RequestMapping("validatedOne")
public String validatedOne(@Validated() UserVo userVo) {
MessageBean messageBean = new MessageBean("哈哈哈,通过验证了");
return JSONObject.toJSONString(messageBean);
}
/**
* <h5>功能:只验证UserVo中group为"insert.class"的属性</h5>
*
* @param userVo
* @return
*/
@RequestMapping("validatedTwo")
public String validatedTwo(@Validated(ToolInterface.insert.class) UserVo userVo) {
MessageBean messageBean = new MessageBean("哈哈哈,通过验证了");
return JSONObject.toJSONString(messageBean);
}
/**
* <h5>功能:只验证UserVo中group为"update.class"的属性</h5>
*
* @param userVo
* @return
*/
@RequestMapping("validatedThree")
public String validatedThree(@Validated(ToolInterface.update.class) UserVo userVo) {
MessageBean messageBean = new MessageBean("哈哈哈,通过验证了");
return JSONObject.toJSONString(messageBean);
}
/**
* <h5>功能:只验证UserVo中同时满足多个group的属性(一般不使用这个)</h5>
* all.class中同时包含了insert.class和update.class
* @param userVo
* @return
*/
@RequestMapping("validatedFour")
public String validatedFour(@Validated(ToolInterface.all.class) UserVo userVo) {
MessageBean messageBean = new MessageBean("哈哈哈,通过验证了");
return JSONObject.toJSONString(messageBean);
}
/**
* <h5>功能:直接参数校验</h5>
* 验证框架里面大部分都不需要我们显示设置message,每个注解框架都给了一个默认提示语,大多数提示还都比较友好
* 不建议对原始类型数据如int进行参数校验(支持不好,会报异常),建议绑定实体参数校验,如上面几个方法的校验方式
* @param name
* @param bindingResult
* @return
*/
@RequestMapping("validatedFive")
public String validatedFive(
@NotBlank(message = "姓名不能为空") String name,
@Min(value = 10, message = "年龄必须大于10岁") Integer age
) {
MessageBean messageBean = new MessageBean("哈哈哈,通过验证了");
return JSONObject.toJSONString(messageBean);
}
}
5.2.3 测试
6. MessageBean消息处理类
import java.util.Date;
/**
* @功能描述: JSON模型 用户后台向前台返回的JSON对象
*/
public class MessageBean {
private int code = 200; // 返回编码
private String message = ""; // 提示信息
private Object data = null; // 其他信息
private Long time = new Date().getTime();
public MessageBean() {
super();
}
public MessageBean(String message) {
super();
this.message = message;
}
public MessageBean(Object data) {
super();
this.data = data;
}
public MessageBean(int code, String message) {
super();
this.code = code;
this.message = message;
}
public MessageBean(String message, Object data) {
super();
this.message = message;
this.data = data;
}
public MessageBean(int code, String message, Object data) {
super();
this.code = code;
this.message = message;
this.data = data;
}
// get、set方法略过...,如果使用Lombok则不需要写get、set方法了,原因你懂的...
}
7、源码
移步码云下载