springboot使用AOP实现验证
先写注释类ValidateGroup
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ValidateGroup {
public ValidateFiled[] fileds() ;
}
注释类ValidateFiled
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ValidateFiled {
/**
* 参数索引位置
*/
int index() default -1 ;
/**
* 如果参数是基本数据类型或String ,就不用指定该参数,如果参数是对象,要验证对象里面某个属性,就用该参数指定属性名
*/
String filedName() default "" ;
/**
* 正则验证
*/
String regStr() default "";
/**
* 是否能为空 , 为true表示不能为空 , false表示能够为空
*/
boolean notNull() default false;
/**
* 是否能为空 , 为true表示不能为空 , false表示能够为空
*/
int maxLen() default -1 ;
/**
* 最小长度 , 用户验证字符串
*/
int minLen() default -1 ;
/**
*最大值 ,用于验证数字类型数据
*/
int maxVal() default -1 ;
/**
*最小值 ,用于验证数值类型数据
*/
int minVal() default -1 ;
int size() default -1 ;
boolean images() default false;
}
验证类ValidateAspectHandel
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import com.chqcontrol.annotation.ValidateFiled;
import com.chqcontrol.annotation.ValidateGroup;
import com.chqcontrol.exception.ValidException;
import com.common.other.APIErrorCode;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
/**
* 验证注解处理类
* @author zhoufeng
*/
@Component
@Aspect
public class ValidateAspectHandel {
/**
* 使用AOP对使用了ValidateGroup的方法进行代理校验
* @throws Throwable
*/
@SuppressWarnings({ "finally", "rawtypes" })
@Around("@annotation(com.chqcontrol.annotation.ValidateGroup)")
//@Before(("execution(* com.chqcontrol.service.*.*(..)) && @annotation(validateGroup)"))
public Object validateAround(ProceedingJoinPoint joinPoint) throws Throwable {
boolean flag = false ;
ValidateGroup an = null;
Object[] args = null ;
Method method = null;
Object target = null ;
String methodName = null;
methodName = joinPoint.getSignature().getName();
target = joinPoint.getTarget();
method = getMethodByClassAndName(target.getClass(), methodName); //得到拦截的方法
args = joinPoint.getArgs(); //方法的参数
an = (ValidateGroup)getAnnotationByMethod(method ,ValidateGroup.class );
flag = validateFiled(an.fileds() , args);
if(flag){
System.out.println("验证通过");
return joinPoint.proceed();
}else{ //这里使用了Spring MVC ,所有返回值应该为Strng或ModelAndView ,如果是用Struts2,直接返回一个String的resutl就行了
System.out.println("验证未通过");
Class returnType = method.getReturnType(); //得到方法返回值类型
if(returnType == String.class){ //如果返回值为Stirng
return "/error.jsp"; //返回错误页面
}else if(returnType == ModelAndView.class){
return new ModelAndView("/error.jsp");//返回错误页面
}else{ //当使用Ajax的时候 可能会出现这种情况
throw new ValidException(APIErrorCode.JSON_ERROR);
}
}
}
public boolean validateFiledOne(String filedName,Object[] args,ValidateFiled validateFiled) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException{
Object arg = null;
if("".equals(filedName) ){
arg = args[validateFiled.index()];
}else{
arg = getFieldByObjectAndFileName(args[validateFiled.index()] ,
filedName);
}
if(validateFiled.notNull()){ //判断参数是否为空
if(StringUtils.isEmpty(arg))
return false;
}else{ //如果该参数能够为空,并且当参数为空时,就不用判断后面的了 ,直接返回true
if(arg == null )
return true;
}
if(validateFiled.maxLen() > 0){ //判断字符串最大长度
if(((String)arg).length() > validateFiled.maxLen())
return false;
}
if(validateFiled.minLen() > 0){ //判断字符串最小长度
if(((String)arg).length() < validateFiled.minLen())
return false;
}
if(validateFiled.maxVal() != -1){ //判断数值最大值
if( (Integer)arg > validateFiled.maxVal())
return false;
}
if(validateFiled.minVal() != -1){ //判断数值最小值
if((Integer)arg < validateFiled.minVal())
return false;
}
if(validateFiled.size() != -1){ //判断数值最小值
if(((String)arg).length() != validateFiled.size())
return false;
}
if(!"".equals(validateFiled.regStr())){ //判断正则
if(arg instanceof String){
if(!((String)arg).matches(validateFiled.regStr()))
return false;
}else{
return false;
}
}
if(validateFiled.images()){ //判断正则
if(arg == null || ((MultipartFile[])arg).length == 0){
return false;
}
}
return true;
}
/**
* 验证参数是否合法
*/
public boolean validateFiled(ValidateFiled[] valiedatefiles , Object[] args) throws SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException{
for (ValidateFiled validateFiled : valiedatefiles) {
String fileName = validateFiled.filedName();
String[] fileNames = fileName.split(",");
for(String f : fileNames) {
boolean flag = validateFiledOne(f, args,validateFiled);
if(!flag){
return false;
}
}
}
return true;
}
/**
* 根据对象和属性名得到 属性
*/
public Object getFieldByObjectAndFileName(Object targetObj , String fileName) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException{
String tmp[] = fileName.split("\\.");
Object arg = targetObj ;
for (int i = 0; i < tmp.length; i++) {
Method methdo = arg.getClass().
getMethod(getGetterNameByFiledName(tmp[i]));
arg = methdo.invoke(arg);
}
return arg ;
}
/**
* 根据属性名 得到该属性的getter方法名
*/
public String getGetterNameByFiledName(String fieldName){
return "get" + fieldName.substring(0 ,1).toUpperCase() + fieldName.substring(1) ;
}
/**
* 根据目标方法和注解类型 得到该目标方法的指定注解
*/
public Annotation getAnnotationByMethod(Method method , Class annoClass){
Annotation all[] = method.getAnnotations();
for (Annotation annotation : all) {
if (annotation.annotationType() == annoClass) {
return annotation;
}
}
return null;
}
/**
* 根据类和方法名得到方法
*/
public Method getMethodByClassAndName(Class c , String methodName){
Method[] methods = c.getDeclaredMethods();
for (Method method : methods) {
if(method.getName().equals(methodName)){
return method ;
}
}
return null;
}
}
最后在service方法中加入注解使用
@ValidateGroup(fileds = {
//index=0 表示下面方法的第一个参数,也就是person nutNull=true 表示不能为空
// @ValidateFiled(index = 0, notNull = true, filedName = "account,name,post"),
// @ValidateFiled(index = 0, notNull = true, filedName = "phone", regStr = phone_pattern),
// @ValidateFiled(index = 0, notNull = true, filedName = "ezPhone", size = 6)
})