10

実際の状況は次のとおりです。Java Web サーバー (Weblogic) がユーザーからの要求を受け取り、応答として ZIP アーカイブを送信する必要があります。アーカイブは、ユーザーが要求したいくつかのファイルと、サーバー自体によって生成された1 つの HTML レポートから動的に生成する必要があります。サーバーが他のケースで既に使用している JSF サーブレットを再利用して、このレポートを生成したいと考えています。したがって、基本的に、私が使用するのは次のとおりです。

HttpURLConnection  self = new URL ("http://me.myself.com/report.jsf?...").openConnection ();
String  report_html = fetchHtmlFromConnection (self);

次に、生成された HTML を含む要求された ZIP を作成します。

report.jsf問題は、このシナリオで( への) 内部 HTTP 要求を作成することをどうにかして回避できるかということです。これには、オペレーティング システム、HTTPD (別のマシン上にある可能性があります) などを介した基本的に無意味な (アプリケーションがとにかく自分自身と「対話」するため) ラウンドトリップが含まれます。

4

5 に答える 5

2

私は JSF にあまり詳しくありませんが、私が理解していることから、JSP ページにも適用できるテクニックを使用できます。

  • 独自のものを作成しますHttpServletResponseWrapper(応答を変更できるコンテナーで使用されるクラス)
  • これを使用してデフォルトWriter(レンダリングされたページを出力に書き込む)をオーバーライドしString、圧縮コードを供給する一時ファイルまたは一時ファイルに出力を書き込むものを提供します。

その方法を示す素晴らしくシンプルなチュートリアルがあります: http://blog.valotas.com/2011/09/get-output-of-jsp-or-servlet-response.html

それで

  • gyan に示唆されServletRequestDispatcherているように、JSF のレンダリングを呼び出すことができるサーブレットから を取得します
  • サーブレット呼び出しを転送して、独自のHttpServletResponseWrapper
  • を使用HttpServletResponseWrapperして、レンダリングされた HTML を取得し、それを郵便番号にフィードします。

したがって、zip サーブレットは次のようになります。

TempFileRespWrapper respWrapper = new TempFileRespWrapper();
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher( "/report.jsf");
dispatcher.forward(request, respWrapper);
File f = respWrapper.getOutputPath();
addFileToZip(f);
于 2014-02-24T06:11:37.443 に答える
2

「generateReport」サービスを複数のプレゼンテーション ビュー (「zip ファイル」ビューであっても) 内で使用できるように、ビジネス サービス層が必要です。

これは、EJB を介して標準的な J2EE の方法で行うか、注入可能なビジネス サービス (Spring など) を指定できるカスタム フレームワークを介して行うことができます。

ここでの主な問題は、クライアント インターフェイス (http) を介してのみレポートを生成できることだと思います。これにより、分離されたサービスになり、アプリケーションの他の部分では利用できなくなります。基本的にリファクタリングが必要です。

JSF または類似の内部でビジネスをコーディングしないでください。(ちなみに、jsfをまったく使用しないようにしてください:D)


  BUSINESS LAYER              PRESENTATION
generateReportService---|---jsf-HtmlReport
                     \__|___
                        |   \ 
someOtherContentService-|----jsf-Zip
于 2014-02-21T16:26:10.603 に答える
1

リクエスト/レスポンス オブジェクトがエントリ サーブレットからレポート サーブレットに送信される、リクエスト ディスパッチャー戦略について考えてみましょう。次に、レポート サーブレットがレポートを生成し、コントロールを次のサーブレットに送信して、残りの zip および送信プロセスを完了します。

RequestDispatcher オブジェクトを作成するには、ServletRequest.getRequestDispatcher()メソッドまたは メソッドのいずれかを使用できますServletContext.getRequestDispatcher()

RequestDispatcher dispatcher=getServletContext().getRequestDispatcher( "/report.jsf" );
dispatcher.forward( request, response );

次のサーブレットは、MIME タイプを「application/zip」に設定し、zip バイナリをブラウザに書き込みます。ユーザーのブラウザは、ブラウザの設定に応じてコンテンツをダウンロードの形で処理します。

于 2013-10-09T09:39:11.017 に答える
0

テスト済みのソリューション!

このソリューションは、実際にここに既に投稿されているアイデアを取得します (特に @gyan から)。

  1. zip するサーブレットを作成する

(これにもフィルターを使用できます。たとえば、ZipFilter があるとします。すべての *.zip にフィルターをマップし、そのフィルターをそれぞれの .jsf URL の URLRewrite フィルターでチェーンすることができます)。

public class ZipServlet
    extends HttpServlet {

    @Override
    public void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException,
            IOException {

        ZipEntry zipEntry = new ZipEntry("helloWorld.html");
        ZipHttpServletResponseWrapper respWrapper = new ZipHttpServletResponseWrapper(response, zipEntry);
        RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/helloWorld.jsf");
        dispatcher.forward(request, respWrapper);
        response.setContentType("application/zip");
        response.setHeader("Content-Disposition", "inline; filename=output.zip;");
        response.flushBuffer();
        respWrapper.getOutputStream().close();

    }

}
  • : はい、RequestDispatcher を使用する必要があります

    1. ZipHttpServletResponseWrapper

それについて言うことはあまりありません。Java 7 から、ネイティブ クラスを使用して zip ファイルを適切に作成できます。response.getOutputStream() の上に ZipOutputStream を指定してDecorator パターンを使用することをお勧めします。

HttpServletResponseWrapper はデコレーターであることを思い出してください。ターゲットの「サーブレット」出力を直接再利用したくない場合は、これを使用しないでください (HttpServletResponseWrapper を使用する代わりに、スタント HttpServletResponse を使用できます)。

public class ZipHttpServletResponseWrapper
    extends HttpServletResponseWrapper {

    private ZipEntry entry;
    private ZipServletOutputStreamWrapper streamWrapper;
    private ZipOutputStream outputStream;
    private PrintWriter printWriter;

    public ZipHttpServletResponseWrapper(HttpServletResponse response, ZipEntry entry) {
        super(response);
        this.entry = entry;
    }

    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        if (streamWrapper == null) {
            outputStream = new ZipOutputStream(this.getResponse().getOutputStream());
            outputStream.putNextEntry(entry);
            streamWrapper = new ZipServletOutputStreamWrapper(outputStream);
        }
        return streamWrapper;
    }

    @Override
    public PrintWriter getWriter() throws IOException {
        if (printWriter == null) {
            printWriter = new PrintWriter(getOutputStream());
        }
        return printWriter;
    }

    private class ZipServletOutputStreamWrapper
        extends ServletOutputStream {

        private ZipOutputStream outputStream;

        public ZipServletOutputStreamWrapper(ZipOutputStream outputStream) {
            this.outputStream = outputStream;
        }

        @Override
        public void close() throws IOException {
            outputStream.closeEntry();
            outputStream.finish();
        }

        @Override
        public void write(int b) throws IOException {
            outputStream.write(b);
        }
    }

}
  1. さて、その秘訣は、賢くマッピングすることです!

JSF のいくつかの重要な部分はフィルター チェーンを使用できます (たとえば、Apache の myfaces はいくつかの拡張機能を使用して、いくつかの JSF コンポーネントを提供します)。この場合、これらのフィルターでダイジェスト FORWARD および REQUEST を指定する必要があります。

    <filter-mapping>
        <filter-name>extensionsFilter</filter-name>
        <url-pattern>*.jsf</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>    
    </filter-mapping>
于 2014-02-28T18:45:11.520 に答える
0

Web サーバーが html をキャッシュするように構成されていることを確認してください(generated)。心配する必要はありません。完全または部分的な URL への最初の要求は、jsf ジェネレーターへの呼び出しを生成し、後で Web サーバーのキャッシュからフェッチされます。

はい、多少のオーバーヘッドが発生します

(ソース -> サーバー -> ジェネレータ ページまたはキャッシュ)

しかし、最終的には簡単になります。

于 2014-02-27T16:50:54.827 に答える