2009-07-27 8 views
6

イメージとPDF出力に変換しています。アプリケーションJSPによって生成される入力HTML文書が必要です。基本的には、JSPベースのアプリケーションの最終出力製品をStringまたはメモリにレンダリングし、その文字列を他の処理に使用する必要があります。Tomcat/Websphereを使用してJSPコンパイルを文字列またはメモリに変換する

通常、ユーザに出力される最終的なHTMLコンテンツを取得するためにJSPレンダラを呼び出すことはできますか? 理想的には、websphereのような複数のアプリケーションサーバーで動作するものを探しています。しかし、Tomcat固有のものも機能します。

他にもいくつかのアプローチがありますが、JSP(サブJSPを含む)をレンダリングするのが最良の方法です。

私はむしろ離れています。

  1. ソケットAPIを使用してページにネットワーク要求を行い、その特定のページからレンダリングされる最終出力を読み取ることができました。これはおそらく次善の選択肢ですが、複数のサーバーとJVMで作業します。必要なページをターゲットにすることは複雑になります。

  2. フィルタを使用して最終ページ出力を取得します。このOkですが、私はいつもフィルターや違法ステートメントに問題がありました。私が必要としている方法で100%働くことは決してないようです。

これは簡単なようです。 JSPコンパイラは、基本的に、入力されたJSPドキュメントとサブドキュメントを解析し、いくつかのHTMLコンテンツを出力するライブラリです。そのプロセスをJavaコードで呼びたいと思います。サーバー上、および場合によってはスタンドアロンのコンソールアプリケーションとして。

答えて

6

これは非常に刺激的な問題です。私が数回処理しなければならなかったものと、満足できる解決策を見つけたことのないものがあります。

基本的な問題は、サーブレットAPIがここで役に立たないということです。そのため、あなたはそれを騙さなければなりません。私の解決策は、getWriter()メソッドとgetOutput()メソッドをオーバーライドし、バッファにデータをキャプチャするHttpServletResponseWrapperのサブクラスを記述することです。キャプチャしたいJSPのURIにリクエストを転送し、元のレスポンスをラッパーレスポンスに置き換えます。その後、バッファからデータを抽出し、操作し、最終結果を元の応答に書き戻します。

public class CapturingResponseWrapper extends HttpServletResponseWrapper { 

    private final OutputStream buffer; 

    private PrintWriter writer; 
    private ServletOutputStream outputStream; 

    public CapturingResponseWrapper(HttpServletResponse response, OutputStream buffer) { 
     super(response); 
     this.buffer = buffer; 
    } 

    @Override 
    public ServletOutputStream getOutputStream() { 
     if (outputStream == null) { 
      outputStream = new DelegatingServletOutputStream(buffer); 
     } 
     return outputStream; 
    } 

    @Override 
    public PrintWriter getWriter() { 
     if (writer == null) { 
      writer = new PrintWriter(buffer); 
     } 
     return writer; 
    } 

    @Override 
    public void flushBuffer() throws IOException { 
     if (writer != null) { 
      writer.flush(); 
     } 
     if (outputStream != null) { 
      outputStream.flush(); 
     } 
    } 

} 

このようなものになることができ、それを使用するコード:

はここでこれを行うに私のコードです

HttpServletRequest originalRequest = ... 
HttpServletResponse originalResponse = ... 

ByteArrayOutputStream bufferStream = new ByteArrayOutputStream(); 
CapturingResponseWrapper responseWrapper = new CapturingResponseWrapper(originalResponse, bufferStream); 

originalRequest.getRequestDispatcher("/my.jsp").forward(originalRequest, responseWrapper); 

responseWrapper.flushBuffer(); 
byte[] buffer = bufferStream.toByteArray(); 
// now use the data 

それは非常に醜いですが、それは私が見つけた最高のソリューションです。疑問に思っている場合、サーブレットの仕様には、転送時やオリジナルの使用、またはラップされたバージョンの要求や応答オブジェクトを完全に入れ替えることができないため、ラッパー応答に元の応答が含まれている必要があります。

+0

+1私をビートしてください。 –

+0

私はみんな同じぞっとするような解決策を持っていると感じます。 – skaffman

+0

これは良いアプローチです。 「フィルタ」指向のアプローチのようなもの。 しかし、この問題には2つの問題があります。 1.これをスタンドアロンシステムとして実行することはできません。例えば。あなたが行うことはできません: main(){compileJSP()} 2.これをフィルターコード内で使用すると、一部のアプリケーションサーバーはrequestwrapperの状態をニックピッキングしています。私は不正な状態を取得する傾向があり、 JSPは文字列にレンダリングする(本質的に私がこれを行うときは決して簡単ではない)。 しかし、確かにそれは良い解決策です。 –

関連する問題