1. 配置 applicationContext

在 Spring 中支持 AOP 的配置非常的简单,只需要在 Spring 配置文件 applicationContext.xml 中添加:

<aop:aspectj-autoproxy/>

同时在 applicationContext.xml 的 schema 中配置:

清单 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="
  http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/cache
  http://www.springframework.org/schema/cache/spring-cache.xsd
  http://www.springframework.org/schema/tx
  http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
  http://www.springframework.org/schema/aop
  http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">

在配置时,我们需要将引用的 jar 包放置在 WEB-INF/lib 目录下面:

需要的 jar 包有

配置这些之后 Spring AOP 就可以开始工作了。

2. 定义 Annotation

首先,我们定义一个常量来表示用户是否登录:

清单 2
1
2
3
4
5
6
package com.example.myenum;        
    public enum ISLOGIN {
        YES,
        LOGOUT,
        NO
    }

这里也可以选择不使用 enum,UserAccessAnnotation 中的 isLogin() 方法也可以返回整数或 String 类型,返回类型并没有限制。常量定义之后,我们再定义 Annotation,在 UserAccessAnnotation 中定义 isLogin(),表示用户是否已经登录:

清单 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.example.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
import com.example.myenum.ISLOGIN;
 
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface UserAccessAnnotation {
         /**
         * User has been login or not.
         *
         */
        ISLOGIN isLogin();
    }

定义好之后,这个 Annoatation 将可以被放置在需要验证用户是否登录的方法前面,就像下面这样:

清单 4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.example.aspect;
public class OrderAction extends BaseAction{
    ……
     @UserAccessAnnotation(>isLogin=ISLOGIN.YES)
     public String Order(){
         try{
            Boolean result = orderService.order(Quote quote);
            if(result) return SUCCESS;
         }catch(Exception e) {
            logger.debug(e);
            this.addActionError(getText("user_no_permission_error"));
         }
         return INPUT;
    }
    ……
 }

在这里我们使用 UserAccessAnnotation 来表示需要在 Order 方法执行之前判断用户是否已经登录,如果没有登录,在 struts2 中,通过下面定义的 Exception 的捕获机制,将页面转到登录页面。

3. 在 applicationContext.xml 中定义 Aspect

清单 5
1
2
3
<bean id="permission" class="com.example.aspect.PermissionAspect" scope="prototype">
     <property name="authService" ref="AuthService" />
</bean>

我们要在 Spring 中定义 PermissionAspect。在 Struts+Spring 架构中可以把 Aspect 看作是一个 Action,只不过 Aspect 是其他 Action 的前提条件或者结束动作。Aspect 定义中的 Service 属性和 Action 中的 Service 属性没有任何区别。这里我们用 AuthService 类来实现判断用户是否已经登录的逻辑。

4. 定义 PointCut

清单 6
1
2
3
4
5
6
7
8
9
10
@Aspect
public class SystemArchitecture {
  /**
   * A Join Point is defined in the action layer where the method needs
   * a permission check.
   */
   @Pointcut("@annotation(com.example.annotation.UserAccessAnnotation)")
   public void userAccess() {}
    
}

PointCut 即切入点,就是定义方法执行的点,before、after 或者 around。 一般情况下,我们把 PointCut 全部集中定义在 SystemArchitecture 类中,以方便修改和管理。

当实现 Aspect 时可以很方便的使用我们在 SystemArchitecture 中定义的 PointCut。

5. 实现 Aspect

清单 7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.example.aspect;
 
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
 
import com.example.annotation.UserAccessAnnotation;
import com.example.base.action.BaseAction;
import com.example.myenum.USERTYPE;
import com.example.service.AuthService;
 
@Aspect
public class PermissionAspect extends BaseAction{
 ……
 AuthService authService = null;
 
@Before(value="com.example.aspect.SystemArchitecture.userAccess()&&"+
"@annotation(userAccessAnnotation)",argNames="userAccessAnnotation")
 
public void checkPermission(UserAccessAnnotation userAccessAnnotation)
throws Exception{
    IsLogin isLogin = userAccessAnnotation.isLogin ();
 
    if(!authService.userLogin(user).equals(isLogin.toString())){
        throw new NoPermissionException(getText("user_no_permission_error"));
    }
}
    ……
}

在 checkPermission 方法前,我们首先定义 PointCut:

1
2
@Before(value="com.example.aspect.SystemArchitecture.userAccess()&&"+
"@annotation(userAccessAnnotation)",argNames="userAccessAnnotation").

argNames="userAccessAnnotation" 的意思是把 Annotation 当做参数传递进来,并判断用户登录状态是否与 Annotation 中的定义一致。如果不一致,就要抛出 NoPermissionException,通知系统该用户没有权限。

基于 Annotation 的 Spring AOP 权限验证方法的实现的更多相关文章

  1. 基于 Annotation 拦截的 Spring AOP 权限验证方法

    基于 Annotation 拦截的 Spring AOP 权限验证方法 转自:http://www.ibm.com/developerworks/cn/java/j-lo-springaopfilte ...

  2. Spring学习笔记之四----基于Annotation的Spring AOP编程

    你能使用@Aspect annotation将某个Java类标注为Aspect,这个Aspect类里的所有公有方法都可以成为一个Advice,Spring提供了5个Annotation去将某个方法标注 ...

  3. 基于注解的Spring AOP的配置和使用

    摘要: 基于注解的Spring AOP的配置和使用 AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面编程.可以通过预编译方式和运行期动态代理实现在不 ...

  4. 基于注解的Spring AOP示例

    基于注解的Spring AOP示例 目录 在XML配置文件中开启 @AspectJ 支持 声明切面及切入点 声明通知 测试 结语 在XML配置文件中开启 @AspectJ 支持 要使用Spring的A ...

  5. 基于注解的Spring AOP的配置和使用--转载

    AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面编程.可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术. ...

  6. 基于@AspectJ配置Spring AOP之一--转

    原文地址:http://tech.it168.com/j/2007-08-30/200708302209432.shtml 概述 在低版本Spring中定义一个切面是比较麻烦的,需要实现特定的接口,并 ...

  7. Spring学习总结(17)——Spring AOP权限管理

    每个项目都会有权限管理系统 无论你是一个简单的企业站,还是一个复杂到爆的平台级项目,都会涉及到用户登录.权限管理这些必不可少的业务逻辑.有人说,企业站需要什么权限管理阿?那行吧,你那可能叫静态页面,就 ...

  8. Asp.net Mvc4 基于Authorize实现的模块权限验证方式

    在MVC中,我们可以通过在action或者controller上设置Authorize[Role="xxx"] 的方式来设置用户对action的访问权限.显然,这样并不能满足我们的 ...

  9. Spring AOP项目应用——方法入参校验 & 日志横切

    转载:https://blog.csdn.net/Daybreak1209/article/details/80591566 应用一:方法入参校验 由于系统多个方法入参均对外封装了统一的Dto,其中D ...

随机推荐

  1. Java多线程编程:Callable、Future和FutureTask浅析(多线程编程之四)

    java多线程-概念&创建启动&中断&守护线程&优先级&线程状态(多线程编程之一)java多线程同步以及线程间通信详解&消费者生产者模式&死锁& ...

  2. SparkSQL大数据实战:揭开Join的神秘面纱

    本文来自 网易云社区 . Join操作是数据库和大数据计算中的高级特性,大多数场景都需要进行复杂的Join操作,本文从原理层面介绍了SparkSQL支持的常见Join算法及其适用场景. Join背景介 ...

  3. Python脱产8期 Day15 2019/4/30

    一 生成器send方法 1.send的工作原理# 1.send发生信息给当前停止的yield# 2.再去调用__next__()方法,生成器接着往下指向,返回下一个yield值并停止 2.例: per ...

  4. java学习笔记—EL表达式(38)

    EL表达式 EL即Expression Language,主要的任务是帮助开发者简化获取域属性. 但是一般情况下需要使用EL和JSTL结合使用. 语法: ${ // 隐含对象|直接写域中的属性 }  ...

  5. 【OCP题库-12c】最新CUUG OCP 071考试题库(72题)

    72.View the exhibit for the structure of the STUDENTand FACULTYtables. STUDENT Name Null? Type ----- ...

  6. 【12c OCP】CUUG OCP认证071考试原题解析(33)

    33.choose the best answer View the Exhibit and examine the structure of the ORDER_ITEMS table. Exami ...

  7. codeforces 1093 题解

    12.18 update:补充了 $ F $ 题的题解 A 题: 题目保证一定有解,就可以考虑用 $ 2 $ 和 $ 3 $ 来凑出这个数 $ n $ 如果 $ n $ 是偶数,我们用 $ n / 2 ...

  8. git简易入门(github)

    本文讲解下git的使用,包括使用git上传项目工程到github,以及错误解决. 1.安装git 使用apt-get安 sudo apt-get update sudo apt-get install ...

  9. 这是一次 docker 入门实践

    前言 其实接触 docker 也有一段时间了,但是一直没有做下总结,现在网上关于 docker 的介绍也有很多了,本着好记性不如烂笔头的原则,还是自己再记录一波吧. 实现目标 安装 docker ce ...

  10. c# 操作excle

    添加引用  Microsoft.Office.Interop.Excel; 添加命名空间 using Excel = Microsoft.Office.Interop.Excel; //创建接口变量- ...