- - PR -
Filter内でのレスポンスへの書き込みがうまくできません。
1
| 投稿者 | 投稿内容 | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2004-03-03 14:06
質問させてください。
ServletFilterを使用してWebアプリケーションの出力に手を加えようと思っています。 ServletFilterのdoFilterメソッド内のjavax.servlet.FilterChain.doFilterメソッドの 前にはWebアプリケーションに渡す前に行う処理、 後ろにWebアプリケーションに渡した結果に手を加える処理 を記述すると理解しています。 以下がサンプルです。 とくに何も行いません。 ServletFilterのdoFilterメソッドの中身 public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { try { final ByteArrayOutputStream dummyout = new ByteArrayOutputStream(); // 仮の出力先を持つServletResponseWrapperを定義 HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper((HttpServletResponse) res) { PrintWriter writer = new PrintWriter(dummyout); ServletOutputStream out = new DummyServletStream(dummyout); public PrintWriter getWriter() { return writer; } public ServletOutputStream getOutputStream() { return out; } }; // 仮の出力先にWebアプリケーションの出力を書き込ませる chain.doFilter(req, wrapper); bais.close(); baos.close(); // 仮の出力先のコンテンツを本来の出力先へ出力 String content = new String(baos.toByteArray(),"UTF8"); res.setContentLength(content.getBytes(ENCODING).length); ---@ res.setContentType("text/html;charset="+ENCODING); ---A PrintWriter reswriter = res.getWriter(); reswriter.write(content); reswriter.close(); } catch (IOException ex) { } catch (ServletException ex) { } } これを実行すると@、Aのところで 『WARNING: Cannot set header. Response already committed.』 と怒られてしまいます。 javax.servlet.FilterChain.doFilterの前に@、Aの処理以外にsetHeaderなどを行うと『WARNING』は発生しません。 また直後に元のレスポンスresを参照して res.isCommited() --->レスポンスがコミットされたかどうかを論理値で返す。 とするとtrueが返され、元のレスポンスがコミットされているようです。 どうにかしてjavax.servlet.FilterChain.doFilterの後にレスポンスに手を加えたいのですが、どうしたらよいでしょうか? どなたでもご存知の方いらっしゃいましたらご教示よろしくお願いします。 | ||||||||||||
|
投稿日時: 2004-03-03 15:41
getWriter と getOutputStream 両方を上書きしていないときによく見かけるエラーですね・・・。どらぴさんのコードでは該当しませんが。
サーブレットコンテナには何をお使いでしょう? WebLogicだと requestDispatcher.forward() でもフィルタが動きますので、2重にフィルタされていないかチェックする必要があり、そのような現象が発生するかのうせいがあります。フラグは request に setAttribute() でもして判定すれば良いでしょう。 | ||||||||||||
|
投稿日時: 2004-03-05 10:06
インギさん、返答ありがとうございます。
サーブレットコンテナはWebSphereですね。
2重にFilterがあるとこのような現象が発生するのでしょうか? その場合はどう対処すれば良いのでしょう? | ||||||||||||
|
投稿日時: 2004-03-05 11:26
WASならフィルタが2重に起動されることはないと思います。
WebLogicでチェックをかけるとしたら [CODE] doFilter(...){ if(null != request.getAttribute("flag")){ request.setAttribute("flag","kicked"); //処理 } chain.doFilter(..); } {/CODE] どのコンテンツが本物のレスポンスに書き出されているかを切り分けるために、 chain.doFilter() の直後に flush() してみてはいかがでしょうか? | ||||||||||||
|
投稿日時: 2004-03-05 14:38
最初意味があまりわからなかったのですが インギさんの「2重」というのは
ということですよね? 私の「2重のFilter」というのは
というように勝手に思い込んでしまっていました。 インギさんの書き込み参照
私の書き込み参照
ラッパーしたもの、オリジナルのレスポンスどちらの OutputStreamもflushすると「Writerを既に取得した」というエラーが発生し、 Writerをflushすると特に何も起こりませんでした。 しかしその後setHeaderを行うと同様に『WARNING』が発生しました。 …?です。 | ||||||||||||
|
投稿日時: 2004-03-05 15:27
説明が悪くてごめんなさい。確かにわかりにくかったですね。
さて、現象のほうですがちょっとわかりません。 WAS には明るくないのですが、サンプルにレスポンスをラッパで受けてから返すようなフィルタはついていないでしょうか?それとみくらべてみたり、IBM に問い合わせてみたりしてみてはいかがでしょう。せっかく商用の製品を使っているんですから。 | ||||||||||||
1
