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

SpringMVC参数校验,包括JavaBean和基本类型的校验(转载)

2017-12-12 11:30 621 查看
参考博客: 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;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: