Filterはページ内のinclude方式の要求をブロックし,その要求のURLを取得する.


最近、プロジェクトにキャッシュフレームワークを作成し、プラグインで追加する必要があります.プロファイルを使用して、ページをキャッシュするURLを指定する必要があります.
 
そこで遮断器Filterを作りたいと思った.
 
このFilterは、まずすべてのリクエストをブロックしてからリクエストのURLを取得し、構成中のキャッシュが必要なURLと比較し、キャッシュが必要な場合はキャッシュ処理に入り、キャッシュが必要でない場合は次のFitlerに直接移行することができる.
 
具体的なキャッシュ処理は、オープンソースフレームワークOScacheを採用している.
 
案は比較的簡単です.テストでは、一般的なFitlerはブラウザのアドレスバーからのリクエストをブロックするしかないことがわかりました.ページの読み込み方法の要求ページは、ブロックできません.
 
関連資料の表示http://www.ibm.com/developerworks/java/library/j-tomcat2/結論を出す:
 
サーブレット2.3では,Fitlerはinclude,forward,error方式からの要求をブロックできない.
Sellvet 2.4では、上記の3つのリクエストをブロックできるようにFilterの機能が強化されています.ただし、プロファイルに構成を追加する必要があります.
 
   
   
   
   
  1. <filter> 
  2.     <filter-name>Cachefilter-name> 
  3.     <filter-class>prx.cache.filter.CacheFilterfilter-class> 
  4.     <init-param> 
  5.          
  6.         <param-name>refreshPeriodparam-name> 
  7.         <param-value>120param-value> 
  8.     init-param> 
  9. filter> 
  10.  
  11. <filter-mapping> 
  12.     <filter-name>Cachefilter-name> 
  13.     <url-pattern>/*url-pattern> 
  14. filter-mapping> 

この方式ではincludeリクエストをブロックできません.
次のように変更します.
   
   
   
   
  1. <filter> 
  2.     <filter-name>Cachefilter-name> 
  3.     <filter-class>prx.cache.filter.CacheFilterfilter-class> 
  4.     <init-param> 
  5.          
  6.         <param-name>refreshPeriodparam-name> 
  7.         <param-value>120param-value> 
  8.     init-param> 
  9. filter> 
  10.  
  11. <filter-mapping> 
  12.     <filter-name>Cachefilter-name> 
  13.     <url-pattern>/index.jspurl-pattern> 
  14.     <dispatcher>requestdispatcher> 
  15.      
  16.     <dispatcher>includedispatcher> 
  17. filter-mapping> 

コンフィギュレーション・ファイルで、コンフィギュレーションを追加します.
request Filterは、一致するrequest方式のリクエストのみをブロックします.デフォルトです.
include Filterは、一致するincldue方式のリクエストのみをブロックできます.
forward Filterは、一致するforward方式のリクエストのみをブロックできます.
error Filterは、一致するerror方式のリクエストのみをブロックできます.
 
dispatcherは、様々なニーズを組み合わせるために複数を構成することができる.
 
たとえば、上記の構成では、Fitlerはrequestおよびinclude方式のリクエストをブロックできます.
 
 
以上の構成により、Filterがincludeにブロックしたリクエストになります.(もちろんtomcatはservlet 2.4をサポートする必要があります)
 
これで問題を解決した.
 
 
その後のテストでは、Filterはincldueの要求をブロックしたが、FilterではそのincldueのURLを取得できないことが分かった.
 
プロジェクトのキャッシュスキームが必要であるため,URL要求を取得し,キャッシュが必要か否かを判断する.したがって、そのincludeリクエストのURLを取得する必要があります.
 
   
   
   
   
  1. public void doFilter(ServletRequest request, ServletResponse response, 
  2.             FilterChain chain) throws IOException, ServletException { 
  3.          
  4.         HttpServletRequest httpRequest = (HttpServletRequest)request; 
  5.          
  6.         // url , :/PrxWebCache/index.jsp 
  7.         String url = httpRequest.getRequestURI(); 
  8.         System.out.println(url); 
  9.          
  10.         int cacheGrade = CacheUtils.isNeedCacheUrl(url); 
  11.         if(cacheGrade != 0) {   // url 
  12.             String key = CacheUtils.createKeyByUrl(httpRequest); 
  13.             boolean isInCache = CacheUtils.isInCache(httpRequest, key, cacheGrade); 
  14.             if(isInCache) { 
  15.                 try { 
  16.                     String content = (String)CacheUtils.getFromCache(httpRequest, key, cacheGrade, refreshPeriod); 
  17.                     System.out.println(" "); 
  18.                     response.getWriter().print(content);     
  19.                 } catch (NeedsRefreshException e) { // ,  
  20.                     System.out.println(" "); 
  21.                     cacheAndResponseContent(httpRequest, response, chain, key, cacheGrade); 
  22.                 } 
  23.             } else { 
  24.                 // , ,  
  25.                 cacheAndResponseContent(httpRequest, response, chain, key, cacheGrade); 
  26.             } 
  27.         } else { 
  28.             chain.doFilter(request, response); 
  29.         } 
  30.     } 

FilterではhttpRequest.getRequestURI(); 取り出したURL:
1.requestリクエストの場合、取得したURLは正しい.
2.include要求の場合、取得したURLは、そのinclude要素を含む元ページのURLである
 
例えばmain.jspページに
Fitlerがinclude要求をブロックすると、httpRequest.getRequestURI(); 得られたのはmainです.私が必要とするindexではなくjspです.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?type 1=request¶m 1=test 1でindex.jspページに
アクセス/index.jsp?type 1=request¶m 1=test 1の場合、上記の方法でincludeリクエスト/mainをブロックする.jsp?type2=include¶m2=test2
Filterの中のこの要求のすべてのパラメータを取得する時、/index.jspのパラメータ(type 1=request¶m 1=test 1)も読みだします
   
   
   
   
  1. /** 
  2.      *  URL , :url=/index.jsp?type=1&searchWord=java, type=1&searchWord=java 
  3.      * @param request 
  4.      */ 
  5.     private static String getSortedQueryString(HttpServletRequest request) { 
  6.         Map paramMap = request.getParameterMap(); 
  7.  
  8.         if (paramMap.isEmpty()) { 
  9.             return null
  10.         } 
  11.  
  12.         Set paramSet = new TreeMap(paramMap).entrySet(); 
  13.  
  14.         StringBuffer buf = new StringBuffer(); 
  15.  
  16.         boolean first = true
  17.  
  18.         for (Iterator it = paramSet.iterator(); it.hasNext();) { 
  19.             Map.Entry entry = (Map.Entry) it.next(); 
  20.             String[] values = (String[]) entry.getValue(); 
  21.  
  22.             for (int i = 0; i 
  23.                 String key = (String) entry.getKey(); 
  24.  
  25.                 if ((key.length() != 10) || !"jsessionid".equals(key)) { 
  26.                     if (first) { 
  27.                         first = false
  28.                     } else { 
  29.                         buf.append('&'); 
  30.                     } 
  31.  
  32.                     buf.append(key).append('=').append(values[i]); 
  33.                 } 
  34.             } 
  35.         } 
  36.  
  37.         // We get a 0 length buffer if the only parameter was a jsessionid 
  38.         if (buf.length() == 0) { 
  39.             return null
  40.         } else { 
  41.             return buf.toString(); 
  42.         } 
  43.     } 

このメソッドが返す結果は:/main.jsp?type2=include¶m2=test2&type1=request¶m1=test1
これで含む、indexが取得する.jspのパラメータ.
私は今include要求のパラメータ、すなわち/mainだけを取得したいと思っています.jsp?type 2=include¶m 2=test 2のパラメータ部分type 2=include¶m 2=test 2
でもrequest.getParameter()メソッドは,どのパラメータがinclude要求のパラメータであるか判断できない.
以上のヒントを得て、他のAttributeNameがincludeリクエストのパラメータだけを取得できるのではないかと思いました.
テストを通して、やはりこのAttributeName:“javax.servlet.include.query_string”が発見されました.
このパラメータ文字列は、一言で取得できます.
   
   
   
   
  1. (String)request.getAttribute("javax.servlet.include.query_string"); 

この結果は、type 2=include¶m 2=test 2がinclude要求のみに必要なパラメータである.