struts2的CRUD中的权限控制初探(转)

 
        在信息管理系统中,涉及到最多的就是对信息(数据)的增删改查,当然在真是的系统中,对于这些操作要控制在严格的权限中,在前面的文章中,我们已经使用 struts2+hibernate+spring实现了简单的crud操作,现在我们就来研究下如何给这些相关操作增加权限控制。
      当然最简单的实现就是在每个Action的CRUD方法中首先判断登陆用户的权限,如果没有此方法操作的权限就可以抛出一个说明原因的异常,这样在一个庞大的系统中,这样类似权限检查的代码就会在众多Action中蔓延,这将会使得业务逻辑代码变得晦涩,对系统以后的维护变得困难,严重违反了单一职责原则。
      相反,我们可以将一个权限控制剥离到一个代理中,这样Action几乎不需要改动就可以达到权限控制的目的。以下是详细实现。
     1.基本的实现步骤:使用一个动态代理类(Proxy),通过拦截一个对象(我们实现crud操作的一个抽象类AbstractCRUDAction)的行为("load", "store","remove")并添加我 们需要的功能(权限控制)来完成。Java中的java.lang.reflect.Proxy类和 java.lang.reflect.InvocationHandler接口为我们实现动态代理类提供了一个方案.
     2.实现InvocationHandler接口的invoke()方法,所有代理对象的调用都会发送到invoke方法,所以只要在调用前后实现自己的控制即可,这里我们在调用代理方法之前进行权限控制,伪代码如下:
 //在调用核心功能之前作一些动作
……
//调用核心功能
m.invoke(obj, args);
//在调用核心功能以后做一些动作
……
本例的代码如下:
package com.waimai.experiment;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.List;

import com.opensymphony.xwork2.ActionSupport;
import com.waimai.web.AbstractCRUDAction;

/**
 * 描述:
 * 
 * 
@author Stone yang 创建日期:2007-5-20
 * 
@version pattern Study 技术支持: <a
 *          href="
http://blog.csdn.net/yq76034150">http://blog.csdn.net/yq76034150</a>
 
*/

public class ActionProxy implements InvocationHandler {
       //需要权限控制的方法列表
    
private List<String> methods;

    
private Object target;

    
/**
     * 描述:构造函数
     * 
     * 
@param methods
     * 
@param target
     * 
@author Stone yang 创建时间:2007-5-20
     
*/

    
public ActionProxy(Object target, String... methodNames) {
        
this.methods = Arrays.asList(methodNames);
        
this.target = target;
    }


    
public static Object getInstance() {
        ActionProxy actionProxy 
= new ActionProxy(new AbstractCRUDAction(), "load","store","remove");
        
return Proxy.newProxyInstance(AbstractCRUDAction.class.getClassLoader(),
                
new Class[] {AbstractCRUDAction.class}, actionProxy);
    }


    
/**
     * 描述:
     * 
     * 
@author Stone yang
     * 
@see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
     *      java.lang.reflect.Method, java.lang.Object[])
     
*/

    
public Object invoke(Object proxy, Method method, Object[] args)
            
throws Throwable {
        
// TODO 自动生成方法存根
        this.doBegin();
        
return method.invoke(target, args);
    }


    
/**
     * 
     * 描述:
     * 
     * 
@author Stone yang 创建时间:2007-5-20
     
*/

    
private void doBegin() {
        
// TODO 自动生成方法存根
        
//权限检查代码
    }


}


3.调用代理类实现系统功能,代码大致如此:
package com.waimai.experiment;

import com.waimai.web.CaiTypeAction;

/**
 * 描述:
 * 
@author Stone yang  创建日期:2007-5-20 
 * 
@version pattern Study
 * 技术支持: <a href="
http://blog.csdn.net/yq76034150">http://blog.csdn.net/yq76034150</a>
 
*/

public class ProxyInvokeMock {

    
/**
     * 描述:
     * 
@param args
     * 
@author Stone yang
     * 创建时间:2007-5-20 
     
*/

    
public static void main(String[] args) {
        
// TODO 自动生成方法存根
        CaiTypeAction actionProxy = (CaiTypeAction)ActionProxy.getInstance();
        
//调用需要进行权限控制的方法
        actionProxy.load();
//        actionProxy.store();
//        actionProxy.remove();
    }


}

     这样我们的权限控制目的就在引入动态代理后优雅的实现了,在上面的代码大家可能已经留意到,权限控制是在实际操作之前完成的,也有很多操作需要在 invoke之后完成,比如用户在完成一笔交易以后,积分要相应增加....那么我们就要在动态代理类的invoke后加入doAfter()之类的代码。是不是感觉到些什么,对,AOP,就是AOP思想的起源。
      最后回到我们需要解决的问题上,由于我们是对struts2的Action进行动态代理,在整个struts的整个框架中,我们并不显式调用 action,这可怎么办呢?呵呵,不用着急,在aop风靡的今天,struts不会落后的,struts2整合了webwork,最重要的一个特性就是拦截器(拦截器)。在Webwork的中文文档的解释为——拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个 action执行的前后执行的代码,也可以在一个action执行前阻止其执行。同时也是提供了一种可以提取action中可重用的部分的方式。谈到拦截器,还有一个词大家应该知道——拦截器链(Interceptor Chain,在Struts 2中称为拦截器栈Interceptor Stack)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。既然如此,我们看看struts2中拦截器调用的时序图:

yeah,和我们之前的动态代理的原理一样,那么我们就使用拦截器来完成我们这样的需求,下篇文章我们将解决这些问题。
posted @ 2008-01-28 09:14    阅读(1644)  评论(2编辑  收藏  举报