使用AOP拦截controller层方法时,通过监控方法上的注解(@Annotation)达到业务上的隔离或验证

作者: admin 分类: 应用技巧 发布时间: 2018-08-13 12:17  阅读: 270 views

我认为这是一种更简单\方便的设计思路,可以有很多的适用场景。

用到了Spring框架的特性,所以先将相关特性的开关打开

开启注解:

切面代理:

1. 先创建两个注解  NeedLogin验证登录   SignFree验签处理

 

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Controller层的方法注解,表示该方法需要用户登录验证
*/
@Target(value = ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface NeedLogin {
    //空
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Controller层的方法注解,表示该方法不需要数字签名
*/
@Target(value = ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface SignFree {
    //空
}

 

2. 定义AOP切面类

import org.apache.commons.lang3.StringUtils;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@Aspect
@Component
@Order(5)
public class AspectAdvice {
    private static final Logger logger = LoggerFactory.getLogger(AspectAdvice.class);
    private static final Logger warnLogger = LoggerFactory.getLogger("warning");

    /**
    * 拦截项目中包名为xxx.controller.*的相关前端控制器
    */
    @Around(value = "execution(* com.xxx.xx.x.controller..*.*(..))")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        try {
            //禁止爬虫
            //禁止IP
            //检查业务
            //上面是开始业务的前置检验
            //下面是业务检验
            Method method = ((MethodSignature) pjp.getSignature()).getMethod();

            // 检查auth
            if (method.getAnnotation(NeedLogin.class) != null) {
                if (!checkAuth(response, request)) {
                    // 测试环境打印日志
                    recordLog(request, response, pjp.getArgs(), paramMap,
                        start, null, !commonConfig.isOnline());

                    return response;
                }
            } else if (method.getAnnotation(SignFree.class) == null) {
                // 检查sign
                if (!checkSign(response, request)) {
                    recordLog(request, response, pjp.getArgs(), paramMap,
                        start, null, false);

                    return response;
                }
            }

            if (method.getAnnotation(CheckPartnerSign.class) != null) {
                checkPartnerSign(pjp);
            }

            Object result = pjp.proceed();
            recordLog(request, result, pjp.getArgs(), paramMap, start, null,
                false);

            return result;
        } catch (ServiceException e) {
            response.setCode(e.getCode());
            response.setMessage(e.getMessage());
            recordLog(request, response, pjp.getArgs(), paramMap, start, e,
                false);

            return response;
        } finally {
            //业务处理
        }
    }
}

 

通过注解判断当前方法是否需要验证、登录等操作

 

3. Controller层的使用

根据业务需要增加不同的注解

 

@RequestMapping(value = "/isshow", method = RequestMethod.GET)
@ResponseBody
@NeedLogin //是否需要登录
@SignFree //是否需要验签
public BaseResponse checkCondition() {
CommonResponse() response = new CommonResponse();
......
return response;
}

 

我之前的处理方式简便性就不如这个。

如登录验证

之前是在controller层中的每个方法内部,代码段开始处做个方法的调用boolean bool = XxxService.checkLogin(XXX);

虽然说两种方式在代码上差不了多少。但是设计思路的优越性上,我更喜欢注解方式。写代码时间越久,越觉得它好. 哈哈哈


   原创文章,转载请标明本文链接: 使用AOP拦截controller层方法时,通过监控方法上的注解(@Annotation)达到业务上的隔离或验证

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

发表评论

电子邮件地址不会被公开。 必填项已用*标注

更多阅读