为动态栏目生成独立的地址

因工作原因,要实现一个动态的栏目,使用独立的地址访问。例如对于项目xxx使用http://localhost:8080/xxx/aaa可访问栏目aaa。

“海词”网站(http://dict.cn/)实现了“地址栏一步查词”,具有类似的功能。

 

提出了两种方案:

1、建立固定结构目录aaa,可使用要求的地址访问。当建立新栏目时,程序拷贝aaa目录,修改目录名实现。

2、使用过滤器,拦截浏览器对http://localhost:8080/xxx/aaa的访问,并转发某个固定的Servlet,将aaa作为参数传给转发的Servlet中。

 

使用解决方案1,当程序变更时,需要更改每一个目录下的程序,所以优先尝试方案2。

 

首先建立一个Servlet,为了简单模拟动态页面,只是读取一个参数,并打印到页面中

public class HostTestServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		String msg = request.getParameter("id");
		PrintWriter out = response.getWriter();
		out.print(msg);
		out.flush();
		out.close();
	}
}

对于过滤器来说,要拦截所有请求并进行地址分析,只有满足条件的才进行转发,这里的条件就是存在的栏目名

下面编写一个类,检测某个字符串是否为栏目名

public class HostTable {
	
	private static String[] hosts = new String[]{
			"hello",
			"123"
	};

	public static boolean isHost(String str) {
		for (String s : hosts) {
			if (str.equals(s)) {
				return true;
			}
		}
		return false;
	}
}

下面实现一个过滤器,具体过程见注释

public class HostFilter implements Filter {
	
	public void init(FilterConfig filterConfig) throws ServletException {}

	public void destroy() {}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain filterchain) throws IOException, ServletException {
		
		HttpServletRequest httpreq = (HttpServletRequest) request;
		HttpServletResponse httpres = (HttpServletResponse) response;
		// 获取当前项目的appName
		String appName = httpreq.getContextPath();
		// 获取请求的URL
		StringBuffer requestUrl = httpreq.getRequestURL();
		System.out.println("过滤器,请求的地址:" + requestUrl);
		// 获取参数
		int pos = requestUrl.lastIndexOf(appName + "/");
		if (pos >= requestUrl.length() || pos < 0) {
			httpres.sendRedirect("/index.jsp");
			return;
		} else {
			String parmar = requestUrl.substring(pos+appName.length()+1, requestUrl.length());
			// 检测参数是否是允许的访问地址
			if (HostTable.isHost(parmar)) {
				String url = "servlet/HostTestServlet?id="+parmar;
				System.out.println("过滤器,转到的地址:" + url);////////////
				// 页面转向,浏览器地址栏能看到新的URL地址
				//httpres.sendRedirect(url);
				// 页面转发,地址栏看不到新地址
				request.getRequestDispatcher(url).forward(request,response);
				return;
			} else {
				System.out.println("参数parmar不在允许访问的地址列表中");////////////
				filterchain.doFilter(httpreq,httpres);
			}
		}
	}
}

将Servlet和Filter注册到web.xml文件

在web.xml文件的<web-app></web-app>之间加入以下内容

        <filter>
		<filter-name>HostFilter</filter-name>
		<filter-class>lmsk.sy.hostFilter.HostFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>HostFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	 
	<servlet>
		<servlet-name>HostTestServlet</servlet-name>
		<servlet-class>lmsk.sy.hostFilter.HostTestServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>HostTestServlet</servlet-name>
		<url-pattern>/servlet/HostTestServlet</url-pattern>
	</servlet-mapping>

 

测试

发布到Tomcat,

在浏览器访问http://localhost:8080/HostTest/hello,页面上输出了hello

在浏览器访问http://localhost:8080/HostTest/123,页面输出了123

同时,控制台输出了调试信息

过滤器,请求的地址:http://localhost:8080/HostTest/hello
过滤器,转到的地址:servlet/HostTestServlet?id=hello
过滤器,请求的地址:http://localhost:8080/HostTest/123
过滤器,转到的地址:servlet/HostTestServlet?id=123

尝试访问某个未注册的值,出现404错误,同时控制台输出

过滤器,请求的地址:http://localhost:8080/HostTest/aaa
参数parmar不在允许访问的地址列表中

也可以修改过滤器代码,使出现该错误时,转到一个自定义的页面上。

通过重写HostTable.isHost(),让它根据数据库内容检测,可以实现栏目的动态地址访问。

 

补充:

1、应用到Struts2中时,发现不能正常转发.action请求。

原因是默认情况下,struts2的核心过滤器会过滤request请求,不会过滤forward请求。

解决方法是在web.xml文件配置核心过滤器的参数

        <!-- 配置核心拦截器 -->
	<filter>
		<filter-name>struts2</filter-name>
		<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>struts2</filter-name>
		<url-pattern>/*</url-pattern>
		<dispatcher>REQUEST</dispatcher>
		<dispatcher>FORWARD</dispatcher>
	</filter-mapping>

加入了<dispatcher>REQUEST</dispatcher>和<dispatcher>FORWARD</dispatcher>。

参考资料:http://hi.baidu.com/dimm456852/blog/item/7d66c3c7e2d5ffa78326ac46.html/cmtid/dbb11ed017721a0e3af3cfb9,感谢!

posted @ 2012-02-01 17:32  石莹  阅读(908)  评论(0编辑  收藏  举报