設計模式的應用-模版方法解決多種角色的登陸過濾

在報名系統中,登陸的有兩類用戶,後臺管理員和報名參與者,而他們都有些操做必須登陸才能執行,傳統的Java Web應用中使用過濾器對指定的路徑進行過濾。web

管理員登陸攔截器

下面攔截管理員,定義登陸過濾器AuthorLoginFilter設計模式

/**
 * 管理員的登陸過濾器
 */
public class ManagerLoginFilter implements Filter {

    /** 白名單:從web.xml中讀取配置 */
    protected Set<String> whiteList = new HashSet<>();
    
    /**
     * 過濾動做
     */
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
            throws IOException, ServletException {

        //1. 獲得應用的uri
        if(!whiteList.contains(uri)) {
            //2. 不在白名單的路徑(須要過濾的)
            //3. 獲取session中的值?
            if( author == null) {
                //4. 未登陸或登陸超時,設置提示信息,重定向到指定路徑?
                return;
            }
        }
        chain.doFilter(req, resp);
    }
    ....
}

web.xml中使用過濾器:session

<filter>
    <description>管理員登陸過濾</description>
    <filter-name>managerLoginFilter</filter-name>
    <filter-class>web.filter.ManagerLoginFilter</filter-class>
    <init-param>
        <!-- 登陸頁面和登陸動做 -->
        <param-name>whiteList</param-name>
        <param-value>
            /manage/login.do;/manage/;
        </param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>managerLoginFilter</filter-name>
    <url-pattern>/manage/*</url-pattern>
</filter-mapping>

發現問題,重構

如今定義UserLoginFilter過濾,攔截活動參與者須要登陸才能執行的URL。因而COPY上面的代碼,改改!!!app

doFilter(...) {
    ...
    // 修改第3步中得到session中的key值: session.getAttribute("CURRENT_USER");
    // 修改第4步中的重定向URL
}

But問題來了????,有沒有發覺代碼和處理流程驚人的類似,除了上面須要修改的地方。ide

定義抽象方法

因而我使用模版方法重構, 定義一個抽象公共的父過濾器LogFilter:this

/**
 * 抽象的登陸過濾器
 * 利用模版設計模式,實現封裝
 * @author 
 *
 */
public abstract class LoginFilter implements Filter {

    protected Set<String> whiteList = new HashSet<>();

    /**
     * 對應第3步:獲取不一樣類型的登陸對象
     * @param session
     * @return
     */
    protected abstract Object getLoginObject(HttpSession session);
    
    /**
     * 對應第4步:得到重定向路徑
     * @param request
     * @return
     */
    protected abstract String getRedirectPath(HttpServletRequest request);
    
    
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        HttpSession session = request.getSession();
        
        // 第1步:獲得出去應用名的uri
        String uri = request.getRequestURI();
        String contextPath = request.getContextPath();
        if(uri.startsWith( contextPath )) {
            uri = uri.replaceFirst(contextPath,"");
        }
        
        // 第2步:攔截不在白名單中,且未登陸的請求
        if(!whiteList.contains(uri)) {
            // 第3步:鉤子方法,利用多態特效,調用具體實現的方法
            Object targetObject= getLoginObject(session);
            if(targetObject == null) {
                session.setAttribute("message", "登陸超時,從新登陸");
                // 第4步:鉤子方法,利用多態特性,調用具體的方法實現
                response.sendRedirect( getRedirectPath(request));
                return;
            }
        }
        
        chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException {
        String configWhiteData = config.getInitParameter("whiteList");
        // 有配置參數
        if( !StringUtil.isBlank(configWhiteData) ) {
            String[] whites = configWhiteData.split(";"); 
            for (String white : whites) {
                this.whiteList.add(white.trim());
            }
        }
    }

}

具體的過濾器實現

/**
 * 管理員登陸過濾器
 * @author 
 *
 */
public class ManagerLoginFilter extends LoginFilter{

    @Override
    protected Object getLoginObject(HttpSession session) {
        return session.getAttribute("CURRENT_MANAGER");
    }

    @Override
    protected String getRedirectPath(HttpServletRequest request) {
        return request.getContextPath() + "/manage/login.do";
    }

}
/**
 * 參與者(用戶)登陸過濾器
 * @author 
 *
 */
public class UserLoginFilter extends LoginFilter{

    @Override
    protected Object getLoginObject(HttpSession session) {
        return session.getAttribute("CURRENT_USER");
    }

    @Override
    protected String getRedirectPath(HttpServletRequest request) {
        return request.getContextPath() + "/index.do";
    }

}

web.xml配置文件

<filter>
    <description>管理員登陸過濾</description>
    <filter-name>managerLoginFilter</filter-name>
    <filter-class>web.filter.ManagerLoginFilter</filter-class>
    <init-param>
        <param-name>whiteList</param-name>
        <param-value>
            /manage/login.do;/manage/;
        </param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>managerLoginFilter</filter-name>
    <url-pattern>/manage/*</url-pattern>
</filter-mapping>

<filter>
    <description>參與者登陸過濾</description>
    <filter-name>userLoginFilter</filter-name>
    <filter-class>web.filter.UserLoginFilter</filter-class>
    <init-param>
        <param-name>whiteList</param-name>
        <param-value></param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>userLoginFilter</filter-name>
    <url-pattern>/user/*</url-pattern>
</filter-mapping>

總結

對於某一類問題,具備相同的解決步驟,可是每一步具體的實現可能不一致,可能這個時候就能夠使用模版方法。url

那麼這個問題可否用策略模式解決了????不能設計

相關文章
相關標籤/搜索