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. SQL字符串分割转列,Sql列转字符串

    declare @strVar varchar(2000)declare @ResultVar varchar(2000)set @ResultVar='[薄饼],[点心],[海鲜],[酒吧],[楼面 ...

  2. C#之工厂

    工厂在我看来分为三种分别都是简单工厂,工厂方法,和抽象工厂,这三种都是将使用和创建分开的一种模式 接下来我来介绍一下我理解的简单工厂模式: 在平时我们需要使用生产对象的一个类当我们需要new 一个对象 ...

  3. infopath 2007 升级到2013 栏目字段重复生成问题

    1. 把Expense Statement.xsn的xsn扩展名改成zip.然后解压后会看到有一个mnifest.xsf. 2. 在vs 2013 中打开它. 3. Search for the fi ...

  4. 重装SQL前,一定要把SQL2005、SQL2008之类的彻底删除干净

    0.预备 如果你曾删除过VS2010或者VS2008之类的,同理也要照此方法删除 1.步骤,顺序无妨 卸载程序:控制面板---查找SQL..NET   删除干净 停掉SQL的所有服务:  计算机--管 ...

  5. TestNG参数化之@Parameters传参

    通过TestNG实现参数话常用两种方式,一种是借助 @Parameters读取testng.xml中参数,一种是使用@DataProvider注解传参. 此次主要讲解XML传参,语法:在java类中定 ...

  6. PHP set_error_handler()函数的使用

    我们写程序,难免会有问题(是经常会遇到问题 ),而PHP遇到错误时,就会给出出错脚本的位置.行数和原因.有很多人说,这并没有什么大不了.确实,在调试程序阶段,这确实是没啥的,而且我认为给出错误路径是必 ...

  7. StringBudiler源码简单解析

    StringBudiler源码 继承关系树 底层实现 默认容量() 特别的添加方法(append) 1.继承关系树 继承自AbstractStringBuilder与StringBuffer同族 2. ...

  8. Get 和 Post 方法的选择和URL的设计

    原文链接:http://yifei.me/note/540 HTTP 中常用的方法有 GET/POST/PUT/DELETE 等,在设计API或者表单的时候我们需要选择合适的方法.一般有两种方案: 只 ...

  9. SpringMvc HttpMessageConverter之@ResponseBody

    我们先看HttpMessageConverter的示意图,从图片可以看出它是多么的重要.在一条必经之路截道了的感觉. 先上我的测试例子: jsp页面: <%@ page language=&qu ...

  10. 主机:Think Pad(6475EC7) 64位的Win7上面装CentOS,说VT模式没有被启动,但BIOS里面已经启用了VT-X

    我的主机是ThindPad,型号是6475EC7,就是比较老的型号. 启动vmware出现 二进制转换与此平台长模式不兼容.......: 首先:进入BOIS查看VT是否已经开启(不同型号电脑VT选项 ...