1. 程式人生 > >SpringAOP的自定義註解實踐

SpringAOP的自定義註解實踐

list tsar vat limits exec frame tom component fin

springaop屬於spring的重要屬性,在java中有相當廣泛的用途,大家一般都接觸過aop實現事務的管理,在xml裏配好聲明式事務,然後直接在service上直接加上相應註解即可,

今天我們來實現下SpringAOP的自定義註解,用來在前置通知中做下權限校驗,有利於我們代碼的解藕,提高復用性,增加代碼B格;

話不多說,上代碼,首先定義一個自定義註解

技術分享圖片

這裏的參數我們並沒有在使用,先隨意定義個type,以後想使用時可以再賦值

再來看切面

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;


import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.jiubao.common.core.cache.redis.JedisUtil;


import com.jiubao.common.core.exception.MyException;
import com.jiubao.livenet.cache.JiuBaoCache;
import com.jiubao.livenet.constant.ServiceConstants;
import com.jiubao.livenet.enums.Limitsenum;
import com.jiubao.livenet.service.CustomerService;

/**
* 註解切面
* @author Administrator
*
*/
@Aspect
@Component
public class AuthorityAspect {

private static final Logger logger = LoggerFactory.getLogger(AuthorityAspect.class);

@Resource
private CustomerService customerService;

//Controller層切點
@Pointcut("execution (* com.jiubao.livenet.controller.*.*(..))")
public void controllerAspect() {}



/**
* 前置通知
* 只攔截帶有Authority註解的controller方法
* @param joinPoint 切點
* @return
*/

//@org.springframework.stereotype.Controller *) 表示攔截controller方法 @annotation(Authority) 表示只攔截帶此註解的方法


@Before("within(@org.springframework.stereotype.Controller *) && @annotation(Authority)")
public void doBefore(JoinPoint joinPoint) throws MyException {
  logger.info("==========執行商戶權限controller前置通知===============");
  Object[] args = joinPoint.getArgs();
  HttpServletRequest request=null;
  for (int i = 0; i < args.length; i++) {
    Object object = args[i];
    if(object instanceof HttpServletRequest) {
    request=(HttpServletRequest) args[i];
    break;
   }
}
  Map<String, Object> paramMap = new HashMap<String, Object>();
  if(request ==null) {
    return;
  }

  String url = request.getRequestURI().toString(); //請求的url

  /**
  * 權限控制
  */
JedisUtil jedis = JiuBaoCache.getJedisUtil();
String userId = jedis.getUserId(request);
paramMap.put("uid", userId); //登錄人UID
boolean isAccess=false;
List<Map<String, String>> userAuthlist= customerService.getUserAuth(paramMap); //查詢登錄人的商戶角色列表
for (int i = 0; i < userAuthlist.size(); i++) {
if(userAuthlist.get(i).get("role")!=null) {
String[] limitsArray = Limitsenum.limitsArray(Integer.valueOf(userAuthlist.get(i).get("role"))); //使用枚舉得到此角色對應的URL數組
for (int a = 0; a < limitsArray.length; a++) {
if(url.contains(limitsArray[a])) { //判斷是否有,如果有則跳出
isAccess=true;
break;
}
}
if(isAccess) {
break;
}
}
}

  if (!isAccess){
   throw new MyException(-1,ServiceConstants.NO_ACCESS); //無權限訪問,如果沒有權限直接扔出個自定義異常,在那裏會用response返回給前端提示
}
}

  //全部攔截,這樣的before就是全局攔截,會攔截所有方法
  @Before("controllerAspect()")
  public void doBefore2(JoinPoint joinPoint) {
    System.out.println("==========執行全部攔截controller前置通知===============");
  }

}

再看看調用過程

直接加在controller裏想要限制的方法上即可

技術分享圖片

上面就是全部邏輯了,還有after和Around註解在此省略,這裏要開始測試了,我幾次都測不通,發現根本無效,而且

我配置文件裏也有 <aop:aspectj-autoproxy proxy-target-class="true" />,不知道怎麽回事,後來才發現

如果你的配置文件是這樣的:

技術分享圖片

你除了在spring-mybaits.xml裏要有這個外,還需要在spring-mvc.xml裏有,好吧,都要加上才有效,而且別忘了頭部的聲明哦

順便鄙視一下springmvc,配置文件就是麻煩

在此就完成了所有代碼了,親測是有效的

需提醒是的,當一個切面裏有多個同樣的註解時,會按鏈式分先後執行,比如上面第1個before,所有配了@Authority的方法會執行,接著執行第2個before,

而沒有配@Authority的方法會直接執行第2個before,第1個由於不滿足條件不會執行,這樣方便我們在一個切面裏寫多種靈活的邏輯.

springaop由於配置靈活,復用性強,無性能損耗,在封裝代碼上很好用,比攔截器更方法,推薦使用

再推薦幾個這方面比較好的文章:

1.https://www.cnblogs.com/jianjianyang/p/4910851.html

2.https://www.cnblogs.com/sjlian/p/7325602.html

3.https://www.cnblogs.com/mouseIT/p/5033746.html

SpringAOP的自定義註解實踐