1. 程式人生 > >spring boot AOP

spring boot AOP

在spring boot中,簡單幾步,使用spring AOP實現一個攔截器:

1、引入依賴:
  1. <dependency>
  2.     <groupId>org.springframework.boot</groupId>
  3.     <artifactId>spring-boot-starter-aop</artifactId>
  4. </dependency>

2、建立攔截器類(在該類中,定義了攔截規則:攔截com.xjj.web.controller包下面的所有類中,有@RequestMapping註解的方法。):
  1. /** 
  2.  * 攔截器:記錄使用者操作日誌,檢查使用者是否登入……
     
  3.  * @author XuJijun 
  4.  */
  5. @Aspect
  6. @Component
  7. publicclass ControllerInterceptor {  
  8.     privatestaticfinal Logger logger = LoggerFactory.getLogger(ControllerInterceptor.class);  
  9.     @Value("${spring.profiles}")  
  10.     private String env;  
  11.     /** 
  12.      * 定義攔截規則:攔截com.xjj.web.controller包下面的所有類中,有@RequestMapping註解的方法。
     
  13.      */
  14.     @Pointcut("execution(* com.xjj.web.controller..*(..)) and @annotation(org.springframework.web.bind.annotation.RequestMapping)")  
  15.     publicvoid controllerMethodPointcut(){}  
  16.     /** 
  17.      * 攔截器具體實現 
  18.      * @param pjp 
  19.      * @return JsonResult(被攔截方法的執行結果,或需要登入的錯誤提示。) 
  20.      */
  21.     @Around
    ("controllerMethodPointcut()"//指定攔截器規則;也可以直接把“execution(* com.xjj.........)”寫進這裡
  22.     public Object Interceptor(ProceedingJoinPoint pjp){  
  23.         long beginTime = System.currentTimeMillis();  
  24.         MethodSignature signature = (MethodSignature) pjp.getSignature();  
  25.         Method method = signature.getMethod(); //獲取被攔截的方法
  26.         String methodName = method.getName(); //獲取被攔截的方法名
  27.         Set<Object> allParams = new LinkedHashSet<>(); //儲存所有請求引數,用於輸出到日誌中
  28.         logger.info("請求開始,方法:{}", methodName);  
  29.         Object result = null;  
  30.         Object[] args = pjp.getArgs();  
  31.         for(Object arg : args){  
  32.             //logger.debug("arg: {}", arg);
  33.             if (arg instanceof Map<?, ?>) {  
  34.                 //提取方法中的MAP引數,用於記錄進日誌中
  35.                 @SuppressWarnings("unchecked")  
  36.                 Map<String, Object> map = (Map<String, Object>) arg;  
  37.                 allParams.add(map);  
  38.             }elseif(arg instanceof HttpServletRequest){  
  39.                 HttpServletRequest request = (HttpServletRequest) arg;  
  40.                 if(isLoginRequired(method)){  
  41.                     if(!isLogin(request)){  
  42.                         result = new JsonResult(ResultCode.NOT_LOGIN, "該操作需要登入!去登入嗎?\n\n(不知道登入賬號?請聯絡老許。)"null);  
  43.                     }  
  44.                 }  
  45.                 //獲取query string 或 posted form data引數
  46.                 Map<String, String[]> paramMap = request.getParameterMap();  
  47.                 if(paramMap!=null && paramMap.size()>0){  
  48.                     allParams.add(paramMap);  
  49.                 }  
  50.             }elseif(arg instanceof HttpServletResponse){  
  51.                 //do nothing...
  52.             }else{  
  53.                 //allParams.add(arg);
  54.             }  
  55.         }  
  56.         try {  
  57.             if(result == null){  
  58.                 // 一切正常的情況下,繼續執行被攔截的方法
  59.                 result = pjp.proceed();  
  60.             }  
  61.         } catch (Throwable e) {  
  62.             logger.info("exception: ", e);  
  63.             result = new JsonResult(ResultCode.EXCEPTION, "發生異常:"+e.getMessage());  
  64.         }  
  65.         if(result instanceof JsonResult){  
  66.             long costMs = System.currentTimeMillis() - beginTime;  
  67.             logger.info("{}請求結束,耗時:{}ms", methodName, costMs);  
  68.         }  
  69.         return result;  
  70.     }  
  71.     /** 
  72.      * 判斷一個方法是否需要登入 
  73.      * @param method 
  74.      * @return 
  75.      */
  76.     privateboolean isLoginRequired(Method method){  
  77.         if(!env.equals("prod")){ //只有生產環境才需要登入
  78.             returnfalse;  
  79.         }  
  80.         boolean result = true;  
  81.         if(method.isAnnotationPresent(Permission.class)){  
  82.             result = method.getAnnotation(Permission.class).loginReqired();  
  83.         }  
  84.         return result;  
  85.     }  
  86.     //判斷是否已經登入
  87.     privateboolean isLogin(HttpServletRequest request) {  
  88.         returntrue;  
  89.         /*String token = XWebUtils.getCookieByName(request, WebConstants.CookieName.AdminToken); 
  90.         if("1".equals(redisOperator.get(RedisConstants.Prefix.ADMIN_TOKEN+token))){ 
  91.             return true; 
  92.         }else { 
  93.             return false; 
  94.         }*/
  95.     }  
  96. }  

3、測試

瀏覽器中輸入:http://localhost:8082/api/admin/login

測試結果:

  1. 2016-07-26 11:58:12,057:INFO http-nio-8082-exec-1 (ControllerInterceptor.java:58) - 請求開始,方法:login  
  2. 2016-07-26 11:58:12,061:INFO http-nio-8082-exec-1 (ControllerInterceptor.java:103) - login請求結束,耗時:8ms  

證明攔截器已經生效。