1。サーブレットフィルター
1.1フィルターとは何ですか
フィルターは、サーバーまたはJSPページに関連付けられているサーバー上で実行されるプログラムです。フィルターは1つ以上のサーブレットまたはJSPページに接続され、これらのリソースに入力するリクエスト情報を確認できます。この後、フィルターは次のように選択できます。
resourtion通常の方法でリソースを呼び出します(つまり、サーブレットまたはJSPページを呼び出します)。
codified変更された要求情報を使用して、リソースを呼び出します。
リソースをコールしますが、クライアントに応答を送信する前に変更します。
リソース呼び出しをブロックし、代わりに別のリソースに移動するか、特定のステータスコードを返したり、交換出力を生成したりします。
1.2サーブレットフィルターの基本原理
サーブレットがフィルターとして使用されると、顧客リクエストを処理できます。処理が完了すると、処理のために次のフィルターに引き渡され、クライアントの要求がターゲットに送信されるまでフィルターチェーンで1つずつ処理されます。たとえば、Webサイトには「変更された登録情報」を提出するWebページがあります。ユーザーが変更された情報に記入して送信した後、サーバーは処理時に2つのタスクを実行する必要があります。クライアントのセッションが有効かどうかを判断します。提出されたデータを均一にエンコードします。これらの2つのタスクは、2つのフィルターで構成されるフィルターチェーンで処理できます。フィルタープロセスが成功すると、送信されたデータが最終ターゲットに送信されます。フィルタープロセスが失敗した場合、ビューは指定されたエラーページに配布されます。
2。サーブレットフィルター開発手順
サーブレットフィルターを開発するための手順は次のとおりです。
filterフィルターインターフェイスを実装するサーブレットクラスを作成します。
web.xmlのconfigureフィルター。
フィルターを開発するには、フィルターインターフェイスを実装する必要があります。フィルターインターフェイスは、次の方法を定義します。
destory()は、このフィルターを初期化するためにWebコンテナによって呼び出されます。
②init(filterconfig filterconfig)は、このフィルターを初期化するためにWebコンテナによって呼び出されます。
dofilter(サーブレクエストリクエスト、サーブレスポンス応答、フィルターチェーンチェーン)特定のフィルタリング処理コード。
3。フィルターフレームワークの例
SimpleFilter1.java
パッケージcom.zj.sample; import java.io.ioexception; import javax.servlet.filter; import javax.servlet.filterchain; Import javax.servlet.filterconfig; Import javax.servlet.servletexception;パブリッククラスSimpleFilter1はフィルター{@suppresswarnings( "unused")private filterconfig filterconfig; public void init(filterconfig config)servletexception {this.filterconfig = config; } public void dofilter(servletRequest request、servletResponse応答、フィルターチェーンチェーン){try {system.out.println( "in SimpleFilter1:リクエストのフィルタリング..."); Chain.dofilter(request、response); //処理を次のフィルターSystem.out .println( "SimpleFilter1内:応答のフィルタリング..."); } catch(ioexception ioe){ioe.printstacktrace(); } catch(servletexception se){se.printstacktrace(); }} public void Destroy(){this.filterconfig = null; }}
SimpleFilter2.java
パッケージcom.zj.sample; import java.io.ioexception; import javax.servlet.filter; import javax.servlet.filterchain; Import javax.servlet.filterconfig; Import javax.servlet.servletexception;パブリッククラスSimpleFilter2はフィルター{@suppresswarnings( "unused")private filterconfig filterconfig; public void init(filterconfig config)servletexception {this.filterconfig = config; } public void dofilter(servletRequest request、servletResponse応答、フィルターチェーンチェーン){try {system.out.println( "in SimpleFilter2内:リクエストのフィルタリング..."); Chain.dofilter(リクエスト、応答); //次のフィルターSystem.out.println( "SimpleFilter2内:応答のフィルタリング..."); } catch(ioexception ioe){ioe.printstacktrace(); } catch(servletexception se){se.printstacktrace(); }} public void Destroy(){this.filterconfig = null; }}
web.xml
<filter> <filter-name> filter1 </filter-name> <filter-class> com.zj.sample.simplefilter1 </filter-class> </filter> <filter-name> filter1 </filter-name> <url-pattern>/*</url-pattern> //フィルター> <フィルター> <フィルター> <フィルター> <フィルター> <フィルター> <フィルター> <フィルター> <フィルター> <フィルター> <filter-class> com.zj.sample.simplefilter2 </filter-class> </filter> <filter-mapping> <filter-name> filter2 </filter-name> <url-pattern>/*</url-pattern> //すべての訪問のフィルター</filter-mapping>
結果を出力するためにWebコンテナ内の任意のページを開きます。
SimpleFilter1内:リクエストのフィルタリング... SimpleFilter2内:リクエストのフィルタリング... SimpleFilter2内:応答のフィルタリング... SimpleFilter1内:応答のフィルタリング...
4。レポートフィルター
関連するサーブレットまたはJSPページを呼び出すことにより、標準出力にメッセージを印刷するシンプルなフィルターを試してみましょう。この関数を実装するために、フィルタリング動作はDoFilterメソッドで実行されます。このフィルターに関連付けられたサーブレットまたはJSPページが呼び出されるたびに、DoFilterメソッドは、要求されたホストとコールのURLをリストする印刷物を生成します。 GetRequesturlメソッドはServletRequestの代わりにhttpservletrequestにあるため、servletRequestオブジェクトはhttpservletrequestタイプとして構築されます。第3章でsimplefilter1.javaを変更しましょう。
SimpleFilter1.java
パッケージcom.zj.sample; import java.io.ioexception; import java.util.date; import javax.servlet.filter; import javax.servlet.filterchain; import javax.servlet.filterconfig;インポートjavax.servlet.servletexception; javax.servlet.servletResponse; import javax.servlet.http.httpservletrequest;パブリッククラスSimpleFilter1はフィルター{@suppresswarnings( "unused")private filterconfig filterconfig; public void init(filterconfig config)servletexception {this.filterconfig = config; } public void dofilter(servletRequest request、servletResponse応答、フィルターチェーンチェーン){try {system.out.println( "in SimpleFilter1:リクエストのフィルタリング..."); httpservletrequest req =(httpservletrequest)request; system.out.println(req.getRemoteHost() + "Access" + req.getRequesturl() + "on" + new date() + "。"); Chain.dofilter(リクエスト、応答); System.out.println( "SimpleFilter1内:応答のフィルタリング..."); } catch(ioexception ioe){ioe.printstacktrace(); } catch(servletexception se){se.printstacktrace(); }} public void Destroy(){this.filterconfig = null; }}
同じ第3章では、Web.xmlの設定は変更されていません。
テスト:
[url] http:// localhost:8080/test4jsp/login.jsp [/url]を入力します
結果:
simplefilter1内:リクエストのフィルタリング... 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:1は[url] http:// localhost:8080/test4jsp/login.jsp [/url] sun 04 17:01:37 csmplyfilfilfilftter2:filting filting filting filting filting filting filting [/url]にアクセスしようとしました。応答... SimpleFilter1内:応答のフィルタリング...
5。アクセス時のフィルター(サーブレットを使用してフィルターのパラメーターを初期化)
以下は、initを使用して通常のアクセス時間範囲を設定して、この期間にないアクセスを記録します。第3章でsimplefilter2.javaを変更しましょう。
SimpleFilter2.java。
パッケージcom.zj.sample; import java.io.ioexception; import java.text.dateformat; Import java.util.calendar; import java.util.gregoriancalendar; Import javax.servlet.filter; Import Javax.servlet.filterchain; javax.servlet.servletcontext; Import javax.servlet.servletexception; Import javax.servlet.servletrequest; Import javax.servlet.servletResponse; Import javax.servlet.http.httpservletrequest;パブリッククラスSimpleFilter2はフィルター{@suppresswarnings( "Unsused")private filterconfig configを実装します。 private servletcontextコンテキスト。プライベートINT開始時刻、終了時刻。プライベートデートフォーマットフォーマッタ。 public void init(filterconfig config)servletexception {this.config = config; context = config.getServletContext(); formatter = dateformat.getDateTimeInstance(dateformat.medium、dateformat.medium); try {starttime = integer.parseint(config.getInitParameter( "starttime")); // web.xml endtime = integer.parseint(config.getInitparameter( "endtime")); // web.xml} catch(numberformatexception nfe){// nulfored or nul // starttime = 22; // 10:00 pm終了時間= 6; // 6:00 am}} public void dofilter(servletRequest request、servletResponse応答、フィルターチェーンチェーン){try {system.out.println( "in SimpleFilter2:リクエストのフィルタリング..."); httpservletrequest req =(httpservletrequest)request; GregorianCalendar Calendar = new GregorianCalendar(); int currentTime = Calendar.get(Calendar.hour_of_day); if(isunusualtime(cuntrytime、starttime、endtime))){context.log( "warning:" + req.getRemotehost() + "Access" + req.getRequesturl() + "on" + formatter.format(calendar.getTime()); //ログファイルは<Catalina_home> /logs.1日あたりのログの下にあります。 } Chain.dofilter(request、response); System.out .println( "SimpleFilter2内:応答のフィルタリング..."); } catch(ioexception ioe){ioe.printstacktrace(); } catch(servletexception se){se.printstacktrace(); }} public void destroy(){} //は、異常なアクセス時間としてマークされている開始と終了時間の間の現在の時間ですか? Private Boolean isunusualtime(int Currenttime、int starttime、int endtime){//開始時間が終了時間よりも短い場合(つまり、//同じ日に2回です)、//現在の時間は、//開始時間と終了時間の間に珍しいと見なされます。 if(starttime <endtime){return((currenttime> = starttime)&&(currenttime <endtime)); } //開始時間が//終了時間(つまり、開始時間が1日、//終了時間が翌日にある)以上の場合、//終了時間と開始時間の間にない場合、現在の//時間は異常と見なされます。 else {return(!isunusualtime(currenttime、endtime、starttime)); }}}
web.xmlの設定は変更されていません。
Tomcatログ処理については、さらに紹介します。 config.getServletContext()。log( "log message")は、<catalina_home>/logsフォルダーにログ情報を書き込みます。ファイル名はlocalhost_log.2007-03-04.txtである必要があります(1つは日付ごとに1日に生成され、翌日には見られます)。このようなログファイルを取得するには、次のようにする必要があります。
<logger classname = "org.apache.catalina.logger.filelogger" prefix = "catalina_log。" suffix = "。txt" timestamp = "true"/>
6.サイトフィルターは禁止されています
フィルターが異常な例外を検出したときに後続のフィルタリングプロセスを中断したい場合は、次のことを行うことができます。
public void dofilter(servletrequest request、servletresponse応答、フィルターチェーンチェーン)Servletexception、ioexception {httpservletrequest req =(httpservletrequest)request; httpservletResponse res =(httpservletResponse)応答; if(isunusualcondition(req)){res.sendredirect( "http://www.somesite.com"); } else {chain.dofilter(req、res); }}次の例は、禁止されているサイトフィルターです。一部のサイトにWebサイトにアクセスしたくない場合は、Web.xmlのパラマリューにサイトをリストし、上記の原則を適用して通常のフィルタリングからジャンプして禁止ページを提供できます。
bannedaccessfilter.java
パッケージcom.zj.sample; import java.io.ioexception; import java.io.printwriter; import java.net.malformedurlexceptiontection; import java.net.url; import java.util.hashset; import java.util.stringtokenizer; Import javax.fillet.filter. javax.servlet.filterconfig; Import javax.servlet.servletexception; Import javax.servlet.servletrequest; Import javax.servlet.servletResponse; Import javax.servlet.http.httpservletrequest; Public Class BannedAccessFilterはフィルターを実装しています{private hashset <string> bannedSiteTable; /***リクエストが旗のサイトから来るか、旗のあるサイトでここに紹介されている場合、アクセスを拒否します。 */ public void dofilter(servletRequest request、servletResponse応答、フィルターチェーンチェーン)ServleTexception、ioException {system.out.println( "BannedAccessFilter:リクエストのフィルタリング..."); httpservletrequest req =(httpservletrequest)request; string requestinghost = req.getRemoteHost(); string referringhost = getReferringHost(req.getheader( "参照"));文字列bannedsite = null; Boolean isbanned = false; if(BannedSiteTable.Contains(RequestIngHost)){BannedSite = RequestIngHost; isbanned = true; } else if(bannedsitetable.contains(referringhost)){bannedsite = referringhost; isbanned = true; } if(isbanned){showwarning(response、bannedsite); } else {Chain.dofilter(request、response); } system.out.println( "Bannedaccessfilter内:応答のフィルタリング..."); } /***初期化パラメーターに基づいて旗のテーブルを作成します。*サーブレットAPIのバージョン2.3は、* Java 2プラットフォームの使用を義務付けていることを忘れないでください。したがって、不器用なハッシュテーブル*(各キーに値がある)ではなく、ハッシュセット(特定のキーが存在するかどうかを決定する)を使用することは安全です。 string bannedsites = config.getInitParameter( "bannedsites"); //デフォルトのトークンセット:ホワイトスペース。 stringtokenizer tok = new StringTokenizer(BannedSites); while(tok.hasmoretokens()){string bannedsite = tok.nexttoken(); BannedSiteTable.Add(BannedSite); system.out.println( "banned" + bannedsite); }} public void destroy(){} private string getReferringHost(String Refererringurlstring){try {url referringurl = new Url(refererringurlstring); return(referingurl.gethost()); } catch(malformedurlexception mue){//奇跡またはnull return(null); }} //ユーザーに返される交換応答//ここでバナーサイトから紹介されている人。 private void showarning(servletresponse応答、string bannedsite)servletexception、ioexception {respons.setcontenttype( "text/html"); printwriter out = response.getWriter(); string doctype = "< out.println(doctype + "<html>/n" + "<head> <title>アクセス禁止</title> </head>/n" + "<body bgcolor =/" white/">/n" + "<h1>アクセス禁止</h1>/n" + " "</body> </html>"); }}
web.xml
<filter> <filter-name> bannedaccessfilter </filter-name> <filter-class> com.zj.sample.sample.bannedaccessfilter </filter-class> <init-param> <param-name> bannedsites </param-name> <param-value> [url] www.comtingite.com [/url] [/url] [url] www.moreervlets.com [/url] 127.0.0.1//we test this </param-value> </init-param> </filter> <filter-mapping> <filter-name> bannedaccessfilter </filter-name> <url-pattern>/*</url-pertherth> </filter-mapping>
テスト:
[url] http:// localhost:8080/test4jsp/[/url]
結果:
7.フィルターを交換します
7.1応答を変更します
フィルターは、リソースへのアクセスをブロックしたり、アクティブ化されたりしないようにすることができます。しかし、フィルターがリソースによって生成された応答を変更したい場合。何をするか?リソースによって生成された応答にアクセスする方法はないようです。 DoFilter(ServleTResponse)の2番目のパラメーターは、クライアントに新しい出力を送信する方法を提供しますが、サーブレットまたはJSPページの出力にアクセスする方法をフィルターに提供しません。なぜこれが起こっているのですか?なぜなら、DoFilterメソッドが初めて呼び出されたときにサーブレットまたはJSPページは実行されていないからです。 FilterChainオブジェクトのDoFilterメソッドが呼び出されると、応答を変更するには遅すぎるようです。つまり、データはクライアントに送信されました。
ただし、方法があります。つまり、フィルターチェーンオブジェクトに渡されたドフィルターメソッドの応答オブジェクトを変更します。通常、サーブレットまたはJSPページで生成されたすべての出力バージョンのキャッシュを作成します。サーブレットAPIバージョン2.3は、これに便利なリソース、つまりHTTPSERVLETRESPONSEWRAPPERクラスを提供します。このクラスの使用には、次の5つのステップが含まれます。
1)応答ラッパーを作成します。 javax.servlet.http.httpservletResponseWrapperを拡張します。
2)出力をキャッシュするプリントライターを提供します。 GetWriterメソッドをオーバーロードし、送信されるすべてを保存するPrintWriterを返し、結果を後でアクセスできるフィールドに保存します。
3)このラッパーをDofilterに渡します。 HTTPSERVLETRESPONSEWRAPPERがHTTPSERVLETRESPONSEを実装するため、この呼び出しは合法です。
4)出力を抽出して変更します。フィルターチェーンのDoFilterメソッドを呼び出した後、元のリソースの出力は、ステップ2で提供されるメカニズムを使用して取得できます。アプリケーションに適している限り、変更または交換できます。
5)変更された出力をクライアントに送信します。元のリソースはクライアントに出力を送信しなくなったため(これらの出力は既に応答ラッパーに保存されています)、これらの出力を送信する必要があります。これにより、フィルターは、元の応答オブジェクトからPrintWriterまたは出力ストリームを取得し、変更された出力をストリームに渡す必要があります。
7.2再利用可能な応答ラッパー
次の例は、フィルターがリソースの出力を変更したいほとんどのアプリケーションで使用できるラッパーを示しています。 CharArrayWrapperクラスは、GetWriterメソッドを過負荷にして、大規模な文字配列内のすべてを蓄積するPrintWriterを返します。開発者は、ToCharArray(Original Char [])またはToString(char []から派生した文字列)を使用して、この結果を得ることができます。
Chararraywrapper.java
パッケージcom.zj.sample; import java.io.chararraywriter; import java.io.printwriter; import javax.servlet.http.httpservletresponse; Import javax.servlet.http.httpservletresponsewrapper; /** *クライアントが通常 *出力し、1つの大きな文字配列に保存するすべてのものを取得する応答ラッパー。 */public class chararraywrapperはhttpservletresponsewrapper {private chararraywriter charwriterを拡張します。 /***ラッパーを初期化します。 * <p> *最初に、このコンストラクターは親コンストラクターを呼び出します。その呼び出し *は残酷であるため、応答が保存されるため、Setheader、 *Setstatus、AddCookieなどが正常に機能します。 * <p> *次に、このコンストラクターは、応答を蓄積するために使用されるチャラレイライターを作成します。 */ public Chararraywrapper(httpservletResponse応答){super(response); charwriter = new ChararrayWriter(); } /***サーブレットまたはJSPページが作家に尋ねるとき、彼らに本当のものを与えないでください。代わりに、キャラクター配列*に書き込むバージョンを提供します。 *フィルターは、配列の内容を*クライアントに送信する必要があります(おそらく変更後)。 */ public PrintWriter getWriter(){return(new Printwriter(charwriter)); } /***バッファー全体の文字列表現を取得します。 * <p> *この方法を同じ *ラッパーで複数回呼び出すように<b> <b> </b>ではないことを確認してください。 ChararrayWriterのAPIは、それが以前の値を「覚えている」ことを保証するものではないため、通話は毎回新しい文字列になる可能性があります。 */ public String toString(){return(charwriter.toString()); } /**基礎となる文字配列を取得します。 */ public char [] tochararray(){return(charwriter.tochararray()); }}
7.3フィルターを交換します
前のセクションで示されているChararrayWrapperの一般的なアプリケーションは次のとおりです。複数のターゲット文字列のフィルターを代替文字列に変更します。
7.3.1一般的な交換フィルター
交換filter.javaは、チャララリーワッパーに応答をラップするフィルターを提供し、ラッパーをフィルターチェーンオブジェクトのドフィルターメソッドに渡し、すべてのリソースの出力を与えるストリングタイプの値を抽出し、ターゲット文字列のすべての発生を置換文字列に置き換え、修正された結果をクライアントに送信します。
このフィルターについて注意すべきことは2つあります。まず、それは抽象的なクラスです。それを使用するには、getTargetStringとgetReplacementStringメソッドの実装を提供するサブクラスを作成する必要があります。この治療の例は、次のサブセクションに記載されています。第二に、実際の文字列置換には、より小さなユーティリティクラス(filterutils.javaを参照)を使用します。弦と弦楽装置で低レベルで退屈な方法を使用する代わりに、新しい正規表現パッケージを使用できます。
交換filter.java
パッケージcom.zj.sample; import java.io.ioexception; import java.io.printwriter; import javax.servlet.filter; import javax.servlet.filterchain; import javax.servlet.filterconfig; Import javax.servlet.servletexception; javax.servlet.servletResponse; Import javax.servlet.http.httpservletResponse; /***特定の文字列のすべての発生を交換するフィルター*の置換。 *これは抽象的なクラスです。<i> </i> </i> </i> getTargetString*をオーバーライドし、サブクラスのgetReplacementStringメソッドを使用する必要があります。これらの仕様の2番目は、ターゲット文字列の各発生を置き換えるべき文字列*です。 */public abstract class filterfilter filter {private filterconfig config; public void dofilter(servletrequest request、servletresponse応答、フィルターチェーンチェーン)Servletexception、ioexception {chararraywrapper responsewrapper = new ChararrayWrapper((httpservletResponse)Response); //リソースを呼び出し、ラッパーに出力を蓄積します。 Chain.dofilter(request、responsewrapper); //出力全体を1つの大きな文字列に変えます。 string restornstestring = responsewrapper.toString(); //出力で、ターゲット文字列のすべての発生を交換//文字列に置き換えます。 responseString = filterutils.replace(responseString、getTargetString()、getReplacementString()); //コンテンツレングスヘッダーを更新します。 UpdateHeaders(Response、Respontestring); printwriter out = response.getWriter(); out.write(responsestring); } /***サブクラスが必要な場合に備えて、filterconfigオブジェクトを保存します。 */ public void init(filterconfig config)servletexception {this.config = config; } protected filterconfig getFilterConfig(){return(config); } public void Destroy(){} /***交換が必要な文字列。*このメソッドをサブクラスにオーバーライドします。 */ public Abstract String getTargetString(); /***ターゲットを置き換える文字列。このメソッドを *サブクラスでオーバーライドします。 */ public Abstract String getReplacementString(); /***応答ヘッダーを更新します。このシンプルなバージョンは、文字ごとに1バイトを使用する*文字セットを使用していると仮定して、コンテンツ長ヘッダーを設定するだけです。 */ public void updateheaders(servletresponse response、string responseString){respons.setContentLength(responseString.length()); }}
filterutils.java
パッケージcom.zj.sample; /***文字列を返す応答ラッパーを支援するための小さなユーティリティ。 * /public class filterutils { /***メインストリングのオリジナルのすべての発生を交換して変更します。 */ public static stringの交換(String MainString、String Orig、String facterment){string result = ""; int oldindex = 0; int index = 0; int riglength = orig.length(); while((index = mainstring.indexof(orig、oldindex))!= -1){result = result + mainstring.substring(oldindex、index) +置換; OldIndex = index + ovirengent; } result = result + mainstring.substring(oldindex); return(result); }} 7.3.2文字置換フィルターを実装します。 BaiduがGoogle(ただの仮説)を取得したと仮定します。すべてのページにGoogleという単語を含むすべてのテキストは、Baiduに置き換える必要があります!交換するのは、この関数を実装するために、上記のreplacefilter.javaを継承します。交換するcom.zj.sample; public class latesItEnameFilter extends falterfilter {public string getTargetString(){return( "google.com.cn"); } public string getReplacementString(){return( "baidu.com"); }}
web.xml
<filter> <filter-name>交換</filter-name> <filter-class> com.zj.sample.ReplacesItenAmeFilter </filter-class> </filter> <filter-mapping> <filter-name>交換</filter-name> <url-pattern>/login.jsp </url-pertern> </filter-mapping>
テスト結果:
フィルタリングする前
フィルタリング後
8。圧縮フィルター
圧縮コンテンツを処理し、コンテンツエンコード応答ヘッダー値としてGZIPを使用して圧縮ファイルを自動的に解除し、元のドキュメントと同じように結果を処理できる最新のブラウザがいくつかあります。このような圧縮コンテンツを送信すると、サーバー上のドキュメントを圧縮してクライアントのドキュメントを元に戻すのにかかる時間がかかるため、ファイルをダウンロードするのにかかる時間と比較して、時間を節約できます。プログラムLongservlet.javaは、長く重複したプレーンテキスト出力を備えたサーブレットを提供します。圧縮用の成熟したサーブレットです。 GZIPを使用すると、出力を1/300に圧縮できます!
ブラウザがこの圧縮機能をサポートすると、圧縮フィルターは第7章で導入されたChararrayWrapperを使用してコンテンツを圧縮できます。このタスクを完了するには、次のコンテンツが必要です。
1)フィルターインターフェイスを実装するクラス。このクラスはCompressionFilterという名前です。 initメソッドは、サブクラスがサーブレット環境またはフィルター名にアクセスする必要がある場合に備えて、フィールドにフィールドオブジェクトをフィールドに保存します。脱毛方法の本体は空です。
2)ラップされた応答オブジェクト。 DoFilterメソッドは、ServletResponseオブジェクトをChararrayWrapperに包み、このラッパーをフィルターチェーンオブジェクトのDoFilterメソッドに渡します。この呼び出しが完了すると、他のすべてのフィルターと最終リソースが実行され、出力はラッパー内にあります。このようにして、元のDoFilterは、すべてのリソースの出力を表す文字の配列を抽出します。クライアントが圧縮をサポートしていると述べている場合(つまり、GZIPを受け入れエンコードヘッダーの値として使用)、フィルターはgzipoutputStreamをBytearrayoutputStreamに追加し、このストリームに文字配列をコピーし、コンテンツエンコード応答ヘッダーをGZIPに設定します。クライアントがGZIPをサポートしていない場合は、変更されていない文字配列をByTearRayOutputStreamにコピーします。最後に、DoFilterは、元の応答に関連付けられた文字配列全体(おそらく圧縮)を出力ストリームに書き込むことにより、結果をクライアントに送信します。
3)LongServletを登録します。
CompressionFilter.java
パッケージcom.zj.sample; import java.io.io.bytearrayoutputStream; Import java.io.ioexception; Import java.io.outputStream; Import java.OutputStreamWriter; Import java.util.zip.gzipoutputStream; Import javax.servlet.filter; inervax.servlet.fillet.servlet.servlet.servlet.servlet.servlet.servlet. javax.servlet.filterconfig; Import javax.servlet.servletexception; Import javax.servlet.servletrequest; Import javax.servlet.servletResponse; Import javax.servlet.servlet.http.httpservletrequest; /** * GZIPで出力を圧縮するフィルター(ブラウザが * GZIPをサポートすると仮定)。 */public class CompressionFilterはフィルター{private filterconfig config; /***ブラウザがGZIPをサポートしていない場合は、正常にリソースを呼び出します。ブラウザ * <i>がGZIPをサポートする場合、コンテンツエンコード応答ヘッダーを設定し、すべての出力を収集するラップされた応答でリソースを呼び出します。 *出力を抽出し、GZIPT BYTEアレイに書き込みます。最後に、その配列をクライアントの出力ストリームに書き込みます。 */ public void dofilter(servletRequest request、servletResponse応答、フィルターチェーンチェーン)ServleTexception、ioexception {httpservletrequest req =(httpservletrequest)リクエスト。 httpservletResponse res =(httpservletResponse)応答; if(!isgzipsupported(req)){//正常にリソースを呼び出します。 Chain.dofilter(req、res); } else {//ブラウザにgzipdデータを送信しています。 res.setheader( "Content-Encoding"、 "gzip"); //リソースを呼び出し、ラッパーに出力を蓄積します。 CharArrayWrapper ResponseWrapper = new ChararrayWrapper(res); Chain.dofilter(Req、ResponseWrapper); //出力を表す文字配列を取得します。 char [] responsechars = responsewrapper.tochararray(); //データを圧縮し、それをバイト配列に入れるライターを作成します。 bytearrayoutputStream byTestream = new bytearrayoutputStream(); gzipoutputStream zipout = new gzipoutputStream(byTestream); outputStreamWriter tempout = new outputStreamWriter(zipout); //元の出力を圧縮し、バイト配列に入れます。 Tempout.Write(ResponseChars); // GZIPストリームは明示的に閉じている必要があります。 tempout.close(); //コンテンツレングスヘッダーを更新します。 res.setContentLength(bytestream.size()); //圧縮結果をクライアントに送信します。 outputStream realout = res.getOutputStream(); bytestream.writeto(realout); }} /***サブクラスが必要な場合にfilterconfigオブジェクトを保存します。 */ public void init(filterconfig config)servletexception {this.config = config; } protected filterconfig getFilterConfig(){return(config); } public void destroy(){} private boolean isgzipsupported(httpservletrequest req){string browserencodings = req.getheader( "accept-encoding"); return((browserencodings!= null)&&(browserencodings.indexof( "gzip")!= -1)); }} longservlet.javapackage com.zj.sample; import java.io.ioexception; import java.io.printwriter; import javax.servlet.servletexception; import javax.servlet.http.httpservlet; Import javax.servlet.http.httptservletreqest; javax.servlet.http.httpservletResponse; /*** long </b>出力を備えたサーブレット。第9章の圧縮 *フィルターの効果のテストに使用。 printwriter out = response.getWriter(); string doctype = "<文字列タイトル= "long page"; out.println(doctype + "<html>/n" + " +" <head> <title> " +" </title> </head>/n " +" <body bgcolor =/"#fdf5e6/">/n " +" <h1 align =/"center/"> " +" + "</h1>/n"); string line = "blah、blah、blah、blah、blah。" + "yadda、yadda、yadda、yadda"; for(int i = 0; i <10000; i ++){out.println(line); } out.println( "</body> </html>"); }}
web.xml
<filter> <filter-name> compressionfilter </filter-name> <filter-class> com.zj.sample.compressionFilter </filter-class> </filter> <filter-name> compressionfilter> <servlet-name> longservlet </servet-name> </servlet-name> <サーブレット> <サーブレットクラス> com.zj.sample.longservlet </servlet-class> </servlet> <servlet-name> longservlet </servlet-name> <url-pattern>/longservlet </url-pattern> </servlet-mapping>