2

SiteMeshデコレータに応答のコンテンツタイプを変更するように説得しようとしていますが、喜びはありません。コンテンツタイプは、デコレータのタイプではなく、常にデコレートされたJSPと同じになります。

たとえば、ヘッダー付きのJSPがあるとします

<%@ page contentType="application/xhtml+xml" %>

これを定義するSiteMeshデコレータJSPもあります。

<%@ page contentType="application/vnd.wap.xhtml+xml" %>

私が欲しいのは、デコレートされた応答にデコレータのmimeタイプを持たせることです(ここで使用される実際のMIMEタイプは重要ではありません。これは、問題を説明するためだけのものです)。

SiteMesh 2.4.1ソースを掘り下げると、問題はContentBufferingResponseターゲットの出力をキャプチャする責任があるクラスにあることがわかります。これはメソッドをオーバーライドし、setContentType()後で使用するために値を記録しますが、を呼び出しsuper.setContentType()て、ターゲットJSPのコンテンツタイプを直接応答に効果的に渡します。それが行われると、他の方法で行うように応答を説得する量のcajolingはありません。

それで、これの回避策はありますか?ターゲットJSPのコンテンツタイプを抑制し、代わりにデコレータから取得できますか?

4

2 に答える 2

1

はへのContentBufferingResponse.setContentType呼び出しをトリガーしますHttpServletResponseWrapper.setContentType。後で、デコレータはRequestDispatcher.include、ステータスコードを変更したりヘッダーを設定したりできないを使用して応答に含まれます(変更を試みても無視されます)。したがって、基本的に、コンテンツタイプ、つまりゲームオーバーを設定すると、変更することはできません。

私が見る限り、メソッドはクラスがインスタンス化さSiteMeshFilter.obtainContentれる唯一の場所であるため、回避策を探す場所になります。ContentBufferingResponseSiteMeshFilterContentBufferingResponse

obtainContent考えられる回避策の1つは、のサブクラスを上書きし、SiteMeshFilterポリモーフィズムを使用して実行時に適切なメソッドを呼び出せるようにすることです。これには1つだけ問題がありますobtainContent。プライベートとしてマークされているため、ポリモーフィズムは機能しません。別のメソッドを呼び出すにobtainContentは、フィルター内のこのメソッドよりもはるかに多くを上書きする必要がありますdoFilter。メソッド自体が含まれるのではないかと思います。

別の回避策は、装飾されたページのmimeタイプではsetContentType呼び出されない、別のバージョンのメソッドを何らかの方法で呼び出すことです。ただし、のコードでは「new」を使用してインスタンスをインスタンス化しているsuper.setContentTypeため、呼び出しを別のメソッドに変更することはできません。obtainContentContentBufferingResponse

この時点ContentBufferingResponseで、プロジェクト内に(同じパッケージ宣言の下で)クラスのコピーを作成できます。このクラスでは、装飾されたページのmimeタイプではなく、必要なmimeタイプでsetContentTypeメソッドが呼び出されます。super.setContentType次に、クラスパスを操作し、SiteMeshのjarにあるクラスの前にクラスがロードされていることを確認することで、サーバーをだまして元のクラスではなくクラスをロードさせることができます。ここでの主な問題は、複数のデコレータがある場合に異なるmimeタイプ間で管理することです(そして、あなたは:Dを持っていると確信しています)。

3番目の(これも醜い)回避策は、SiteMeshのコードをハックして、それを回避することです(ライセンスで問題が発生するかどうかはわかりません)。

したがって、私の意見では、いくつかの醜い回避策に頼るつもりがない限り、一度設定されたコンテンツタイプを変更することはできません。

于 2010-04-15T10:04:34.280 に答える
0

ページに適用するサーブレットフィルタを記述setContentType()し、superを呼び出さないようにオーバーライドします。次に、デコレータでコンテンツタイプを任意に設定できます。

これを行うには、サーブレットフィルタをもう1つ作成する必要がありますが、これは非常に単純なはずです。

于 2011-02-22T05:12:28.570 に答える