在报名系统中,登陆的有两类用户,后台管理员和报名参与者,而他们都有些操做必须登陆才能执行,传统的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"; } }
<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
那么这个问题可否用策略模式解决了????不能设计