Aop 面向切面编程,在java 中普遍使用动态代理和反射实现。具体的请百度。spring aop有多种方式。本次使用的是注解方式,(建议使用注解方式)。
第一步自定义了2个注解
@Target(value={ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Verify {}
public @interface FieldVerify {
boolean required() default true;
/***
* 数据类型primary 基本数据
* creator mingqiang_zhou
* createdate 2016-6-16
* modifyor
* @return
*/
String type() default "primary";
}
第二步、建立AOP实现类,和spring IOC 配合使用
@Aspect
public class FunctionRightAop {
private static Logger logger = Logger.getLogger(FunctionRightAop.class);
@Around("@annotation(com.xxx.xxx.FunctionRight)")
public Object process(ProceedingJoinPoint joinPoint) throws Throwable{
Object[] args = joinPoint.getArgs();
Method method = ((MethodSignature)joinPoint.getSignature()).getMethod();Class<?>[] ptypes = method.getParameterTypes();
User loginUser = null;
int len = ptypes.length;
for(int i = 0;i< len;i++){
if(ptypes[i].isAssignableFrom(User.class)){
loginUser = (User)args[i];
break;
}
}
String chktype = method.getAnnotation(FunctionRight.class).value();
boolean addAble = true;........
Opportunity opportunity = null;
if(RightConstant.ACT_ADD.equals(chktype)){
//检查添加权限
}else{
//需要数据进行验证权限。。。。
addAble = checkAll(。。。chktype);
}
if(!addAble){
throw new AuthException(AppCodeEnum.no_right.getCode(),AppCodeEnum.no_right.getMsg());
}else if(!RightConstant.ACT_ADD.equals(chktype)){
//设置获取的对象,节省再次请求数据库
args[len-1] = new Opportunity[]{opportunity};
}
Object returnValue = joinPoint.proceed(args);
return returnValue;
}
可以看到如果在权限验证中使用了,要获取的数据,可以直接将数据当做参数传递到被调用方法中,当然在被调用方法需要定义好参数。
第三步、 在Aop代理中根据注解不能内容进行参数验证。
private boolean procee(Object obj){
if(obj == null){
return false;
}else if(obj instanceof String&&StringUtils.isBlank((String)obj)){
return false;
}else if(obj instanceof List){
List<?> objs = (List<?>)obj;
if(objs==null||objs.isEmpty()){
return false;
}
}else if(obj instanceof Map<?, ?>){
Map<?, ?> map = (Map<?, ?>)obj;
if(map==null||map.isEmpty()){
return false;
}
}else{
Class<?> pclass = obj.getClass();
if(pclass.getAnnotation(Verify.class)!=null){
Field[] fields = pclass.getDeclaredFields();
if(fields!=null){
for(Field field : fields){
if(field.getAnnotation(FieldVerify.class)!=null){
field.setAccessible(true);
try {
Object propertyObj = field.get(obj);
boolean re = procee(propertyObj);
if(!re){
return re;
}
} catch (IllegalArgumentException e) {
logger.error(e.getMessage(),e);
return false;
} catch (IllegalAccessException e) {
logger.error(e.getMessage(),e);
return false;
}
}
}
}
}
}
return true;
}
这个解析是十分简单的验证十分有数据,没有对数据的具体内容进行解析验证判断,同学们有需要可以自己添加。
上面的代码权限验证和参数验证混合在一起了,大概的流程都是产不多的。在第二步中我把权限验证需要用到的数据当做参数传递到真正的业务方法中,这样的好处是节省了在查询数据库的花费,但是与切面与业务分离的思想有违背的。大家根据具体情况使用吧。