在使用spring的aop拦截技术的时候,我们在调用ProceedingJoinPoint的proceed()方法
的时候,在执行struts2的方法的时候,struts2的堆栈里面的数据会丢失,如何解决??比方说我们在用struts2来做登陆的时候用户名和密码,只要我们用spring拦截在执行该方法的时候
在堆栈里面的username和password就会为空

解决方案 »

  1.   

    public class SystemPrivilegeIntercepter {
    private void anyMethod() {}//声明一个切入点
    public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
    //if() {//判断用户是否有权限
    System.out.println("进入方法");
    Object result = pjp.proceed();
    System.out.println("执行的方法:" + pjp.getSignature().getName());
    Method method = pjp.getTarget().getClass().getMethod(pjp.getSignature().getName());

    Permission permission = method.getAnnotation(Permission.class);
    if(permission!=null) {
    System.out.println("---"+permission.model());
    System.out.println("---"+permission.privilegeValue());
    }
    /**
     * 在这里我们就可以利用上面的参数来判断权限
     */
    System.out.println("退出方法");
    //}
    return  result;
    }

    /**
     * 校验用户是否具有执行当前方法的权限
     */
    private boolean validate(Method method) {
    if(method!=null && method.isAnnotationPresent(Permission.class)){
    Permission permission = method.getAnnotation(Permission.class);
    /* 得到当前方法的系统权限 */
    SystemPrivilege privilege = new SystemPrivilege(new SystemPrivilegePK(permission.model(),permission.privilegeValue()));
    /* 得到用户拥有的所有权限 */
    Employee employee = (Employee)ActionContext.getContext().getSession().get("employee");
    for(PrivilegeGroup p : employee.getGroups()) {
    if(p.getPrivileges().contains(privilege))return true;
    }
    return false;
    }
    return true;
    }
    }
      

  2.   

    struts2中属性必须是对象点属性,这这狭隘可以得到
      

  3.   

    request、response、session、servletContext这些对象只能由web容器(tomcat)来实例化,因为它们里面含有上下文信息。Struts2非常变态,它在单线程内将容器提供的这些对象封装了,做成自己的action上下文,然后让程序接受这种潜规则(如强奸一样)。在Spring的AOP时它脱离了线程(ThreadLocal),使自己变一个赤裸裸的类。不知我理解有没有对。这时候解决问题的焦点,就是如何获取session对象,能拿到session就自然可以拿employee对象和用户权限信息(在ThreadLocal中能不能取得action上下文?没有试过。)那么谈谈我在Spring AOP拦截WEB层,是如何获取WEB容器(Tomcat)提供的对象。我原来用Struts1.x,Action中的方法都有四个参数,分别是actionform,actionmapping,request,response。这就好办了,可以在切入点方法参数ProceedingJoinPoint对象的getArgs()方法获取被拦截的方法的参数,返回的是数组,可见request就在第三个,那么:
    HttpServletRequest request = (HttpServletRequest)pjp.getArgs()[2];
    HttpSession session = request.getSession();
    拦截Struts1.x时,我是这样取得session的。后来我一直用Spring @MVC,这个WEB框架很牛的,灵活得难以想象,它可以让程序员给Action中的方法的参数随意定制,例如:
    public String logon(HttpServletRequest request, String userName, String password){
    //Todo
    }
    logon()方法中的参数可以随意制定,我这里定制了三个,那么request对象Spring MVC会自动填充(实例化),剩下的userName和password可以在url参数中或form表单中传过来。后来我想,方法签名中匹配一个HttpServletRequest参数,Spring就能自动实体化,那么在切入点方法中也加一个HttpServletRequest参数恺不是也能实体化?幸运的是我猜中了。即:
    public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {}方法参数中加入HttpServletRequest参数:
    public Object doBasicProfiling(ProceedingJoinPoint pjp, HttpServletRequest request) throws Throwable {
        HttpSession session = request.getSession();
    }
    其实request实例能不能被Spring实例化成功,取得决拦截配置,我的这个配置是:
    @Around("pointcut() && isPrivlegeCheck() && args(*,request,..)")//环绕通知
    这个request对象仍然是借助于被拦截的方法中的request参数对象。
    Struts2我很少用它了(用惯了Spring就很难再接受那种侵入式编程框架),但应该也可以寻求解决方案,按照上面的思路提供一个比较笨拙的办法:在Action中设置一个HttpServletRequest属性,在被拦截的方法中为该属性赋值,写个简单的代码://Action for Struts2
    public class UserAction implements Action {    //被拦截的方法
         @拦截配置
        public String execute(){
           //Todo
        }    //获得J2EE标准的request对象
        public HttpServletRequest getRequest(){
           return ServletActionContext.getRequest();
        }
    }//Aop point
    public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable { 
        Object result = pjp.proceed();//先让被拦截的方法运行
        UserAction action = (UserAction)pjp.getThis();//不是知道是不是这个方法,返回代理对象 
         HttpServletRequest request = action.getRequest();
        //取得empolyee对象,分析权限,
         if(validate(xxx)){
           return result;
        }else{
           request.setAttribute("message","您无权进入...");
           return message;
        }
    }
      

  4.   

    问题已解决,可用在一个struts2包中定义一个拦截器,使用拦截器来的代理可以得到拦截的方法名,然后再通过方法名得到这个反射的方法,得到这个方法后就可以得到这个方法的相关信息了,这样就可以了做权限控制了