Spring AOP基於配置文件的面向方法的切面
Spring AOP根據執行的時間點可以分為around、before和after幾種方式。
around為方法前后均執行before為方法前執行after為方法后執行
這里只對around的方式進行介紹。本文只是摘錄相應的思路,許多輔助類和方法不一一給出。因此下述方法並不能正常運行。
定義忽略權限檢查注解類
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnorePermission {
}
定義需要權限檢查的類及方法
@RestController
@RequestMapping(value = "/api/test")
public class TestController extends BaseController {
@RequestMapping(value="", method= RequestMethod.POST)
public ResponseEntity postTest(@RequestParam(name = "accessToken") String accessToken) {
ResponseEntity responseEntity = new ResponseEntity();
return responseEntity;
}
@RequestMapping(value = "/delete", method = RequestMethod.POST)
public ResponseEntity deleteTest(@RequestParam(name = "accessToken") String accessToken) {
ResponseEntity responseEntity = new ResponseEntity();
return responseEntity;
}
/**
* 帶了IgnorePermission注解,不進行權限檢查。
*/
@IgnorePermission
@RequestMapping(value = "/list", method = RequestMethod.GET)
public ResponseEntity getTestList(@RequestParam(name = "accessToken") String accessToken) {
ResponseEntity responseEntity = new ResponseEntity();
return responseEntity;
}
}
定義切面aop類
public class PermissionAspect {
private Logger logger = LoggerFactory.getLogger(PermissionAspect.class);
private static final String DEFAULT_TOKEN_NAME = "accessToken";
private TokenManager tokenManager;
private String tokenName;
private boolean processing = true;
@Autowired
private BasicService BasicService;
public void setTokenManager(TokenManager tokenManager) {
this.tokenManager = tokenManager;
}
public void setTokenName(String tokenName) {
if (StringUtils.isEmpty(tokenName)) {
tokenName = DEFAULT_TOKEN_NAME;
}
this.tokenName = tokenName;
}
//ProceedingJoinPoint只有around的方式才可用
//JoinPoint則around、before和after均可用
public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
processing = true;
ResponseEntity responseEntity = new ResponseEntity();
// 從切點上獲取目標方法
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
// 若目標方法忽略權限檢查,則直接調用目標方法
if (method.isAnnotationPresent(IgnorePermission.class)) {
return joinPoint.proceed();
}
// 檢查 該用戶是否已經開通
// System.out.println("******************* PermissionAspect start ************************");
logger.info("******************* PermissionAspect start ************************");
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
// 從 request header 中獲取當前 token
String token = StringUtils.isBlank(request.getHeader(tokenName)) ? request.getParameter("accessToken") : request.getHeader(tokenName);
String userId = tokenManager.getUserId(token);
TestBasic TestBasic = BasicService.findByUserId(userId);
try {
if (null == TestBasic) {
String message = String.format("Test basic userId [%s] is not exist.", userId);
responseEntity.failure(ResponseConstant.CODE_000, "尚未申請開通功能。");
processing = false;
throw new Exception(message);
}
if (TestConstant.Test_BASIC_IS_PASS_PASSED != TestBasic.getIsPass()) {
String message = String.format("Test basic userId [%s] has no permission.", userId);
String tips = "不具備權限功能。";
if (TestConstant.Test_BASIC_IS_PASS_PROCESSING == TestBasic.getIsPass()) {
tips = "權限正在審核中。";
} else if (TestConstant.Test_BASIC_IS_PASS_DENY == TestBasic.getIsPass()) {
tips = "不具備權限。";
}
responseEntity.failure(ResponseConstant.CODE_000, tips);
processing = false;
throw new Exception(message);
}
} catch (Exception e) {
throw new Exception(e);
} finally {
// System.out.println("******************* PermissionAspect end ************************");
logger.info("******************* PermissionAspect end ************************");
if (processing) {
return joinPoint.proceed();//如果具備權限則執行相應的方法
} else {
return responseEntity;//如果不具備權限返回相應的json數據
}
}
}
}
配置文件的配置
開啟切面支持
springMvc-context.xml中開啟如下配置
<!-- 開啟aspectj切面支持 -->
<aop:aspectj-autoproxy proxy-target-class="true" />
定義 bean
applicationContext.xml中添加如下配置
<!--Test權限檢查-->
<bean id="permissionAspect" class="com.test.api.test.PermissionAspect">
<property name="tokenManager" ref="tokenManager" />
<property name="tokenName" value="accessToken" />
</bean>
AOP配置
applicationContext.xml中添加如下配置
<aop:config>
<!--其他切面配置-->
... ...
<!--問題權限切面檢查-->
<aop:aspect ref="permissionAspect" order="2">
<aop:around method="execute" pointcut="execution( * com.test.api.test.controller.TestController.*(..) )"/>
</aop:aspect>
</aop:config>
- 注:上述代碼只是實現思路的摘錄,代碼不能直接運行。
