- 浏览: 461943 次
- 性别:
- 来自: 长沙
文章分类
- 全部博客 (132)
- Java (17)
- Eclipse (2)
- Struts2 (6)
- SWT (9)
- Java Web Start (2)
- Heritrix (4)
- Nutch (1)
- Internet (2)
- J2me (2)
- Windows (4)
- Swing (8)
- JavaScript (11)
- Hibernate (1)
- Spring (6)
- Mysql (9)
- Oracle (10)
- Linux (6)
- RESTful (3)
- XML (1)
- Flex (4)
- EL (1)
- Apache (4)
- VC (3)
- OpenSourceLicence (1)
- Tomcat (4)
- Tiles2 (1)
- nosql (6)
- else (4)
- Nginx (2)
最新评论
-
mzlogin:
然而并没有讲 hash 函数
深入理解HashMap(及hash函数的真正巧妙之处) -
czp11210:
hi,你这篇文章很好。有两个细节跟你确认下:1.你使用的amo ...
Mysql 基于 Amoeba 的 水平和垂直 分片 -
Mybeautiful:
It seems the amoeba doesn't sup ...
Mysql 基于 Amoeba 的 水平和垂直 分片 -
xs.cctv:
言简意赅。。。。。。
深入理解HashMap(及hash函数的真正巧妙之处) -
mnhkahn:
h & (length-1)这个其实还是一个模运算,只 ...
深入理解HashMap(及hash函数的真正巧妙之处)
最近需要在项目中做一个缓存框架,通过插件方式加入,要求可以通过配置文件,指定需要缓存页面的URL。
于是就想到做一个拦截器Filter。
该Filter可以首先拦截所有的请求,然后取得请求的URL,与配置中的需要缓存的URL对比,如果需要缓存,则进入缓存处理,如果不需要缓存,则直接到下一个Fitler。
具体的缓存处理,采用开源框架OScache。
方案还是比较简单的。 测试中发现,一般的Fitler只能拦截到从浏览器地址栏中过来的请求。 而页面的采用<jsp:include>方式载入的请求页面,则不能拦截到。
查看相关资料http://www.ibm.com/developerworks/java/library/j-tomcat2/ 后,得出结论:
在Servlet2.3中,Fitler是不能拦截include, forward, error 方式发来的请求的。
在Serlvet2.4中,则增强了Filter的功能,使之可以拦截到上面说的三个请求。 不过需要在配置文件中增加一个配置。
具体如下:
<filter> <filter-name>Cache</filter-name> <filter-class>prx.cache.filter.CacheFilter</filter-class> <init-param> <!-- 过期时间设置,默认为60秒 --> <param-name>refreshPeriod</param-name> <param-value>120</param-value> </init-param> </filter> <filter-mapping> <filter-name>Cache</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
该方式,不能拦截到 include 请求。
修改如下:
<filter> <filter-name>Cache</filter-name> <filter-class>prx.cache.filter.CacheFilter</filter-class> <init-param> <!-- 过期时间设置,默认为60秒 --> <param-name>refreshPeriod</param-name> <param-value>120</param-value> </init-param> </filter> <filter-mapping> <filter-name>Cache</filter-name> <url-pattern>/index.jsp</url-pattern> <dispatcher>request</dispatcher> <!-- 使得页面中通过 include 方式嵌入的匹配页面也可以通过该Filter --> <dispatcher>include</dispatcher> </filter-mapping>
在配置文件,增加 <dispatcher></dispatcher>配置:
<dispatcher>request
</dispatcher> Filter 只能拦截 匹配的 request 方式的请求,为默认值
。
<dispatcher>include
</dispatcher> Filter 只能拦截 匹配的 incldue 方式的请求
<dispatcher>forward
</dispatcher> Filter 只能拦截 匹配的 forward 方式的请求
<dispatcher>error </dispatcher> Filter 只能拦截 匹配的 error 方式的请求
dispatcher可以配置多个,用来组合各种需求。
例如:上面的配置,Fitler可以拦截 request和include 方式的请求。
通过以上的配置,就可以是Filter拦截到 include 的请求了。(当然,tomcat需要支持 servlet2.4)
到此解决了问题一。
在后来的测试又发现,虽然Filter是拦截了 incldue 的请求,但是在 Fitler 中,却无法取得该 incldue 的URL
由于项目的缓存方案是需要,取得URL请求,然后再判断是否需要缓存。 所以必须取得该 include 请求的URL。
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest)request; //取的url相对地址,例如:/PrxWebCache/index.jsp String url = httpRequest.getRequestURI(); System.out.println(url); int cacheGrade = CacheUtils.isNeedCacheUrl(url); if(cacheGrade != 0) { //是否是需要缓存的url String key = CacheUtils.createKeyByUrl(httpRequest); boolean isInCache = CacheUtils.isInCache(httpRequest, key, cacheGrade); if(isInCache) { try { String content = (String)CacheUtils.getFromCache(httpRequest, key, cacheGrade, refreshPeriod); System.out.println("缓存"); response.getWriter().print(content); } catch (NeedsRefreshException e) { //过期,需要刷新 System.out.println("刷新"); cacheAndResponseContent(httpRequest, response, chain, key, cacheGrade); } } else { //拦截响应数据,先加入缓存,再响应给客户端 cacheAndResponseContent(httpRequest, response, chain, key, cacheGrade); } } else { chain.doFilter(request, response); } }
在Filter中,通过 httpRequest.getRequestURI(); 取出的 URL:
1. 当是 request 请求时,取得的 URL 是正确的。
2. 当是 include 请求时, 取得的 URL 是 包含该 include 元素的原页面的 URL
比如: 在 main.jsp 页面中 有个 <jsp:include page="index.jsp?type=test"/>
当Fitler拦截到 该 include请求时, httpRequest.getRequestURI(); 得出的是 main.jsp 而不是我需要的 index.jsp
但是 通过 httpRequest.getParameter("type"); 却可以得到 传入的参数 "test"。
到网上搜个半天,都没有相关答案。
最后在 OScache 源码中发现了一个方法。
httpRequest.getAttribute("javax.servlet.include.request_uri")
通过该方法,可以直接取出 include 请求的 URL 值。
至于,这个 "javax.servlet.include.request_uri" 参数怎么设置进来的,还没仔细研究。 时间紧张,先用着,以后再研究吧。
又发现一个问题:
在Filter中拦截到incldue方式的请求后,在取得传入的所有参数的时候,会把request 的请求参数也读出来。
比如:请求页面 /index.jsp?type1=request¶m1=test1 然后再 index.jsp页面中有一个 <jsp:include page="/main.jsp?type2=include¶m2=test2"/>
当访问 /index.jsp?type1=request¶m1=test1 时,使用上面的方法拦截到 include请求 /main.jsp?type2=include¶m2=test2
Filter中的 在取得该请求的所有参数的时候,会将 /index.jsp的参数(type1=request¶m1=test1)也读出来
/** * 返回请求的URL的参数部分,例如:url=/index.jsp?type=1&searchWord=java,则返回type=1&searchWord=java * @param request */ @SuppressWarnings("unchecked") private static String getSortedQueryString(HttpServletRequest request) { Map paramMap = request.getParameterMap(); if (paramMap.isEmpty()) { return null; } Set paramSet = new TreeMap(paramMap).entrySet(); StringBuffer buf = new StringBuffer(); boolean first = true; for (Iterator it = paramSet.iterator(); it.hasNext();) { Map.Entry entry = (Map.Entry) it.next(); String[] values = (String[]) entry.getValue(); for (int i = 0; i < values.length; i++) { String key = (String) entry.getKey(); if ((key.length() != 10) || !"jsessionid".equals(key)) { if (first) { first = false; } else { buf.append('&'); } buf.append(key).append('=').append(values[i]); } } } // We get a 0 length buffer if the only parameter was a jsessionid if (buf.length() == 0) { return null; } else { return buf.toString(); } }
该方法返回的结果为: /main.jsp?type2=include¶m2=test2&type1=request¶m1=test1
这样就取得了包含,index.jsp的参数。
我现在想要只想要取得 include请求的参数,即 /main.jsp?type2=include¶m2=test2 的参数部分type2=include¶m2=test2
但是通过 request.getParameter()方法,是无法判断出哪个参数才是 include 请求的参数。
经过上面的启发,于是又想到了,是不是有别的AttributeName 可以仅取到 include 请求的参数呢?
通过测试,果然发现的确有该AttributeName:"javax.servlet.include.query_string "
只要通过一句话便可以得到该 参数字符串:
(String)request.getAttribute("javax.servlet.include.query_string");
该结果即为:type2=include¶m2=test2 正是需要的仅为 include 请求的参数。
发表评论
-
【转载】ServletContextListener使用详解
2011-05-12 14:58 4222在 Servlet API 中有一个 Ser ... -
【转载】Java来获取访问者真实的IP地址(避免反向代理的影响)
2010-12-09 09:08 4127在JSP里,获取客户端的IP地址的方法是:request ... -
(转)应用OSCache提升J2EE系统运行性能
2010-11-08 15:09 880肖菁,软件工程师,IBM developerWorks/Bea ... -
深入Java核心 Java内存分配原理精讲
2010-09-10 10:05 1261原文地址:http://developer ... -
防止刷新/后退引起的重复提交问题的Java Token代码,非Struts
2010-09-03 11:42 1699贴子转自http://hi.baidu.com/bobylou ... -
<context-param>与<init-param>的区别与作用
2010-09-03 10:17 3228<context-param>的作用:web.xm ... -
深入Java虚拟机:JVM中的Stack和Heap
2010-04-01 10:44 1096在JVM中,内存分为两个 ... -
利用HttpSessionListener实现网站在线人数统计功能
2010-02-03 14:30 2748在网站中经常需要进行在线人数的统计。过去的一般做法是结合登录和 ... -
深入理解HashMap(及hash函数的真正巧妙之处)
2009-12-08 10:31 17099原文地址:http://www.iteye.com/topic ... -
一键安装双击运行——Java安装程序制作
2009-08-25 15:35 2126标 题: 一键安装双击运行——Java安装程序制作 作 者: ... -
Java实现RSS
2009-08-25 11:20 2016RSS是一个标准的XML文件,Rss阅读器可以读取这个XM ... -
关于EL表达式语言的简单总结
2009-06-22 09:31 1109一、EL简介 1. 语法结构 ${e ... -
Java虚拟机(JVM)中的内存设置详解
2009-06-05 09:37 1283在一些规模稍大的应用中,Java虚拟机(JVM)的内 ... -
JAR 文件揭密
2009-05-31 10:32 1050大多数 Java 程序员都熟悉对 JAR 文件的基本操作。但是 ... -
利用DES加密算法保护Java源代码
2009-04-11 09:59 1726摘 要:本文首先分析了Java源代码需要加密的原因,简要介绍了 ... -
一刻钟精通正则表达式
2008-10-30 15:14 1106maXiaoKe 原创 想 ...
评论