参考博客: SpringMVC参数校验,包括JavaBean和基本类型的校验
一、spingmvc引入Hibernate Validator校验框架,参考地址:http://blog.csdn.net/menghuanzhiming/article/details/78059876
二、校验JavaBean
1、javaben的实体类注解校验:
package edu.hrbeu.platform.modeling.pojo;
import java.io.Serializable;
import javax.validation.constraints.Pattern;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotEmpty;
public class User implements Serializable{
private Integer userId;
@NotEmpty
@Pattern(regexp="^[A-Za-z\u4e00-\u9fa5]{2,10}$", message="登录名:2-10位以内中文或英文或数字")
private String username;
@NotEmpty
@Pattern(regexp="^[A-Za-z\u4e00-\u9fa5]{2,10}$", message="用户名:2-10位以内中文或英文或数字")
private String alias;
@NotEmpty
@Pattern(regexp="^(?=.*[a-z])(?=.*[A-Z])[a-zA-Z\\d]{6,18}$", message="密码:6-18位以内数字和字母,至少各一个大小写字母")
private String password;
@NotEmpty
@Email
private String email;
@NotEmpty
@Pattern(regexp="^1[0-9]{10}$", message="手机号:11位以内中国大陆手机号")
private String phone;
}
2、javaben定义了注解校验等标签后,结合在Controller里使用@Valid和BindingResult即可完成参数的校验。
譬如registerUser方法里,只需要加上@Valid标签即可完成校验。如果校验不通过,那么错误信息就会封装到BindingResult对象了,可以通过bindingResult的相关方法获取详细的错误信息并返回给用户。
如果不加BindingResult则会抛出异常。
此时即可完成表单类,或者用户注册之类的类似请求的参数校验了,可以选择获取bindingResult信息后直接return给用户。如果这样的需要校验的地方比较多,每个都单独处理比较麻烦,可以通过aop统一处理返回,后面会讲到。
校验的标签可参考:http://blog.csdn.net/catoop/article/details/51278675
相关文章:http://412887952-qq-com.iteye.com/blog/2312356
/**
*
* @Title: RegisterUser
* @Description: TODO(用户注册)
* @return Map<String,Object> 返回类型
* @return
*/
@RequestMapping("registerUser")
@ResponseBody
@Operationlog(desc="用户注册")
public Map<String, Object> registerUser(
@Valid
User user,
BindingResult bindingResult
) {
while(bindingResult.hasErrors()) {
System.out.println("没有通过校验");
return null;
}
return null;
}
二、校验基本类型
在很多场景下,我们不需要校验一个javaBean,更多的是校验单个的int,String等。但是直接写上去,是不起作用的,校验框架并没有去校验,我们需要做的就是让它生效。
参考如下:https://diamondfsd.com/article/78fa12cd-b530-4a90-b438-13d5a0c4e26c
这里写链接内容
1、controller层添加注解校验:
controller层方法代码如下,既有javabean的校验也有简单参数的校验:
/**
*
* @Title: RegisterUser
* @Description: TODO(用户注册)
* @return Map<String,Object> 返回类型
* @param user
* @param confirmPassword
* @param vercode
* @param request
* @return
*/
@RequestMapping("registerUser")
@ResponseBody
@Operationlog(desc="用户注册")
public Map<String, Object> registerUser(
@Valid
User user,
BindingResult bindingResult,
@NotEmpty
String confirmPassword,
@NotEmpty
String vercode) {
return null;
}
2、配置aop统一管理javabean的校验信息BindingResult以及使简单参数的注解校验生效:
(1)springmvc的controller配置aop注意事项:
参考连接:http://blog.csdn.net/menghuanzhiming/article/details/78780612
如果仍然无法使用aop请检查jar包是否冲突;
(2)配置文件:spring-aspect.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
<!-- 开启asepctj注解扫描 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
<!-- AOP的XML的aspectj配置 -->
<bean id="requestParamValidAspect" class="edu.hrbeu.platform.modeling.common.aspect.RequestParamValidAspect"/>
</beans>
springmvc配置文件引入spring-aspect.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
...
省略
...
<import resource="spring-aspect.xml"/>
</beans>
切面类RequestParamValidAspect :
package edu.hrbeu.platform.modeling.common.aspect;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.ElementKind;
import javax.validation.Validation;
import javax.validation.ValidatorFactory;
import javax.validation.executable.ExecutableValidator;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.hibernate.validator.internal.engine.path.NodeImpl;
import org.hibernate.validator.internal.engine.path.PathImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import edu.hrbeu.platform.modeling.exception.ParamValidException;
import edu.hrbeu.platform.modeling.pojo.SimpleFiledError;
/**
*
* @ClassName: RequestParamValidAspect
* @Description: TODO(controller参数校验aspectj)
* @author chenliming
* @date 2017年12月12日 上午10:27:36
*
*/
@Aspect
public class RequestParamValidAspect {
private final ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
private final ExecutableValidator validator = factory.getValidator().forExecutables();
Logger log = LoggerFactory.getLogger(getClass());
@Pointcut("execution(public java.util.Map edu.hrbeu.platform.modeling.*.controller.*.*(..))")
public void controllerAround() {
}
ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
/**
*
* @Title: around
* @Description: TODO(环绕增强,校验controller参数)
* @return Object 返回类型
* @param pjp
* @return
* @throws Throwable
*/
@Around("controllerAround()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("aspect参数校验start.....");
try {
// 取参数,如果没参数,那肯定不校验了
Object[] args = pjp.getArgs();
if (args.length == 0) {
return pjp.proceed();
}
List<SimpleFiledError> simpleFiledErrors = new ArrayList<>();
/************************** 校验封装好的javabean **********************/
// 寻找带BindingResult参数的方法,然后判断是否有error,如果有则是校验不通过
for (Object arg : args) {
if (arg instanceof BeanPropertyBindingResult) {
// 有校验
BeanPropertyBindingResult result = (BeanPropertyBindingResult) arg;
if (result.hasErrors()) {
List<ObjectError> list = result.getAllErrors();
for (ObjectError error : list) {
// System.out.println(
// error.getCode() + "---" + error.getArguments() + "--" + error.getDefaultMessage());
String name = null;
if(error instanceof FieldError) {
//字段名称
name = ((FieldError)error).getField();
} else {
//对象名称
name = error.getObjectName();
}
SimpleFiledError simpleFiledError = new SimpleFiledError();
simpleFiledError.setName(name);
simpleFiledError.setMessage(error.getDefaultMessage());
simpleFiledErrors.add(simpleFiledError);
}
}
}
}
/************************** 校验普通参数 *************************/
// 获得切入目标对象
Object target = pjp.getThis();
// 获得切入的方法
Method method = ((MethodSignature) pjp.getSignature()).getMethod();
// 执行校验,获得校验结果
Set<ConstraintViolation<Object>> validResult = validMethodParams(target, method, args);
// 如果有校验不通过的
if (!validResult.isEmpty()) {
String[] parameterNames = parameterNameDiscoverer.getParameterNames(method); // 获得方法的参数名称
for (ConstraintViolation<Object> constraintViolation : validResult) {
PathImpl pathImpl = (PathImpl) constraintViolation.getPropertyPath(); // 获得校验的参数路径信息
NodeImpl leafNode = pathImpl.getLeafNode();
//判断是否是参数类型(如果是bean的属性无法获取index,抛出异常)
if(leafNode.getKind() == ElementKind.PARAMETER) {
int paramIndex = leafNode.getParameterIndex(); // 获得校验的参数位置
String paramName = parameterNames[paramIndex]; // 获得校验的参数名称
// //参数名称
// System.out.println(paramName);
// // 校验信息
// System.out.println(constraintViolation.getMessage());
SimpleFiledError simpleFiledError = new SimpleFiledError();
simpleFiledError.setName(paramName);
simpleFiledError.setMessage(constraintViolation.getMessage());
simpleFiledErrors.add(simpleFiledError);
}
}
}
if(!simpleFiledErrors.isEmpty()) {
Map map = new HashMap();
map.put("success", false);//是否成功
map.put("message", "参数校验不成功");//文本消息
map.put("filedErrors", simpleFiledErrors);
return map;
}
return pjp.proceed();
} catch (Throwable e) {
e.printStackTrace();
throw e;
}
}
public void before(JoinPoint point) throws ParamValidException {
// 获得切入目标对象
Object target = point.getThis();
// 获得切入方法参数
Object[] args = point.getArgs();
// 获得切入的方法
Method method = ((MethodSignature) point.getSignature()).getMethod();
// 执行校验,获得校验结果
Set<ConstraintViolation<Object>> validResult = validMethodParams(target, method, args);
if (!validResult.isEmpty()) {
String[] parameterNames = parameterNameDiscoverer.getParameterNames(method); // 获得方法的参数名称
List<SimpleFiledError> errors = new ArrayList<>();
for (ConstraintViolation<Object> constraintViolation : validResult) {
PathImpl pathImpl = (PathImpl) constraintViolation.getPropertyPath(); // 获得校验的参数路径信息
int paramIndex = pathImpl.getLeafNode().getParameterIndex(); // 获得校验的参数位置
String paramName = parameterNames[paramIndex]; // 获得校验的参数名称
SimpleFiledError error = new SimpleFiledError(); // 将需要的信息包装成简单的对象,方便后面处理
error.setName(paramName); // 参数名称(校验错误的参数名称)
error.setMessage(constraintViolation.getMessage()); // 校验的错误信息
errors.add(error);
System.out.println(paramName);
// 校验信息
System.out.println(constraintViolation.getMessage());
}
throw new ParamValidException(errors); // 我个人的处理方式,抛出异常,交给上层处理
}
}
private <T> Set<ConstraintViolation<T>> validMethodParams(T obj, Method method, Object[] params) {
return validator.validateParameters(obj, method, params);
}
}
切面类中的环绕增强将校验错误汇总并返回;
参数异常处理类ParamValidException:
package edu.hrbeu.platform.modeling.exception;
import java.util.List;
import edu.hrbeu.platform.modeling.pojo.SimpleFiledError;
public class ParamValidException extends Exception{
private static final long serialVersionUID = 1L;
private List<SimpleFiledError> fieldErrors;
public ParamValidException(List<SimpleFiledError> fieldErrors) {
this.fieldErrors = fieldErrors;
}
}
自定义校验错误实体类SimpleFiledError :
package edu.hrbeu.platform.modeling.pojo;
public class SimpleFiledError {
private String name;
private String message;
public SimpleFiledError() {
super();
// TODO Auto-generated constructor stub
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}