SSH集成框架下真正實現(xiàn)SpringAOP攔截功能

字號:

問題的提出:
    在Struts1框架下,有三種類型的Action控制器,分別是MappingDispatchAction、DispatchAction和Action,他們是依次繼承,最終執(zhí)行的execute方法。但MappingDispatchAction、DispatchAction的子類中沒有execute方法,只有參數(shù)指定的具體方法,而這些方法是被MappingDispatchAction、DispatchAction本類的execute方法調(diào)用執(zhí)行,特別注意的是它是通過反射機制來做的(大家可以看看DispatchAction類的源代碼),所以這些被反射調(diào)用的方法是不能被Spring AOP攔截的,因此也就無法利用切面編程實現(xiàn)權(quán)限控制了。
    解決方法:
    巴巴運動網(wǎng)通過覆蓋DelegatingRequestProcessor控制器的processActionPerform方法,是一種理想的解決方案,但嚴(yán)格來說并不是AOP切面編程方法。因此筆者僅從學(xué)習(xí)AOP切面編程的角度來提出本文章,對于實用性筆者極力推薦巴巴運動網(wǎng)的方案。
    本方法解決思想:
    1.覆蓋execute方法,再模仿DispatchAction反射調(diào)用具體的方法;
    2.實現(xiàn)Spring AOP攔截點,開始攔截配置描述的范圍內(nèi)的程序;
    3.在切入點程序中再次實現(xiàn)反射機制,獲取執(zhí)行方法上的權(quán)限配置信息;
    4.根據(jù)權(quán)限信息決定放行還是返回。
    最終既可以攔截到execute方法,也可以得到具體方法中的權(quán)限注解配置信息。以本BBS系統(tǒng)為例:
    第一步:凡繼承于DispatchAction的類都覆蓋execute方法:
    @Override
    public ActionForward execute(ActionMapping mapping, ActionForm form,
    HttpServletRequest request, HttpServletResponse response) throws Exception {
    return super.execute(mapping, form, request, response);
    }
    //假如這個action中有一個具體的方法:
    @Privilege(userType=PrivilegeType.Admin,message="需管理員權(quán)限!")
    public ActionForward addUI(ActionMapping mapping, ActionForm form,
    HttpServletRequest request, HttpServletResponse response) throws Exception {
    CategoryForm categoryForm = (CategoryForm)form;
    categoryForm.setTitle("新增分類");
    return mapping.findForward("addUI");
    }
    第二步:做自己的權(quán)限配置:
    看上面addUI方法上的注解應(yīng)該可以理解這些配置
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface Privilege {
    String message() default "您沒有權(quán)限執(zhí)行該操作,請登錄后重試!";
    PrivilegeType userType();
    }
    配置中有個字字段是枚舉,源碼如下:
    public enum PrivilegeType {
    LoginUser{
    public String getName(){
    return "所有登錄用戶";
    }
    public int getValue(){
    return 1;
    }
    },
    LoginUserSelf{
    public String getName(){
    return "登錄用戶自己";
    }
    public int getValue(){
    return 2;
    }
    },
    Moderator{
    public String getName(){
    return "版主";
    }
    public int getValue(){
    return 3;
    }
    },
    Admin{
    public String getName(){
    return "管理員";
    }
    public int getValue(){
    return 4;
    }
    };
    public abstract String getName();
    public abstract int getValue();
    }