设计模式的应用-模版方法解决多种角色的登陆过滤

在报名系统中,登陆的有两类用户,后台管理员和报名参与者,而他们都有些操做必须登陆才能执行,传统的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

那么这个问题可否用策略模式解决了????不能设计

相关文章
相关标签/搜索