2

jsp:include私は、同じ jar から tomcat の数百のコンテキストにデプロイされるjspx-files と -includes を多用する Web アプリケーションを持っています。現在、個々のインスタンスのレイアウトを変更するには、CSS を変更するか、他のファイル ディレクトリにある特定のファイルを上書きする必要があります。

webapp.jar に という名前のファイルが含まれているとします。/css/forms.cssこの場合、webapp は GETtinghttp://mydomain/cust1/res/css/forms.cssがそのファイルにマップされるようにします。"override directory" を参照するように webapp が構成されている場合、この/data/cust1/ファイルという名前のファイルがある場合/data/cust1/css/forms.css、アプリケーション アーカイブ内のファイルからではなく、このファイルが提供されます。これは、webapp 自体によって保証されます。

過去数年間、これは非常に成功していましたが、最近、「オーバーライド」できない多かれ少なかれ静的なjspxの制限の痛みを感じています;)基本的に、それぞれのjspxファイルを「オーバーライド」できるようにしたいと思いますコンテキストごとにカスタム webapp-jar をコンパイルおよびデプロイすることなく、デプロイされたコンテキスト。(カスタムsomething:includeJspタグを付けても問題ありません)。

基本的に、webapp は、個々の jspx ファイルの jsp(x) コンパイラにオーバーライドを提供できる必要があります。たとえば、次の構造例を見てください。

<!-- webapp.jar:/jspx/view.jspx -->
<jsp:root ...>
  <ns:customInclude src="inc/include.jspx" />
</jsp:root>

<!-- webapp.jar:/jspx/inc/include.jspx -->
<jsp:root ...>
  Default-Markup from the webapp.jar
</jsp:root>

<!-- /data/cust1/jspx/inc/include.jspx -->
<jsp:root ...>
  Custom markup for "cust1"
</jsp:root>

今、要求されたときに、Tomcat によってコンパイルおよび実行されhttp://.../cust1/jspx/view.jspxたいと考えています。/data/cust1/jspx/inc/include.jspx基本的に、実際に必要なことはすべて Tomcat のどこかで既に可能であることを知っています (ファイルを含む jspx から Java-Bytecode へのコンパイルなど) が、Tomcat/Jasper が jsp-spec に準拠していることも知っています。コードを見て、これはそれほど簡単ではないことを理解しました...

基本的に、このようなセットアップを機能させる方法を知っている人はいますか? おそらく誰かがすでにこれを解決しましたか?または、現在のアプローチに代わるものはありますか?

4

1 に答える 1

1

に-Tag をFileDirContext介して含まれる独自の実装を終了しました。実際、私は 2 つを実装しました - の拡張と の拡張です。これは、Eclipse (ファイル構造にデプロイする) を使用した開発中と、展開されていない .war ファイルからデプロイするサーバーで同じメカニズムを有効にしたかったためです。<Resources>context.xmlorg.apache.naming.resources.WARDirContextorg.apache.naming.resources.FileDirContext

どちらもコンテキスト記述子を介して構成でき、複数の「仮想オーバーレイ」を使用できます。オーバーレイは、ファイル システム パスまたは外部 .war ファイル (実際には、.war に名前が変更された .zip に似ています)、または展開された .war ファイルにパックされた .jar ファイルのいずれかです。

1 つの仮想オーバーレイを使用してソリューションを調整する手順は次のとおりです。

  1. 前述MagicWARContextWARDirContext.
  2. このクラスで静的内部クラスを作成しますProtectedMethodVisibleMaker extends FileDirContext。これにより、Tomcat の元の実装の特定の保護されたメソッドにアクセスできます。と をオーバーライドdoGetRealPathdoLookupます。
  3. 独自の WAR コンテキストで、フィールドprivate String overlayとフィールドのゲッターとセッターを作成private ProtectedMethodVisibleMaker overlayContextし、このフィールドに新しい空のインスタンスをインスタンス化します。
  4. allocate()WAR コンテキストで呼び出しoverlayContext.setDocBase(overlay)ます。overlayContext.release()念のため、必ずから電話してくださいrelease()
  5. さらに 5 つのメソッドをオーバーライドする必要があります。WARDirContext
    • doGetRealPath(String)
    • doLookup(String)
    • getAttributes(Name, String[])
    • list(String)
    • list(Name) もちろん、両方の結果の列挙にlistは、仮想オーバーレイのエントリと元のコンテキストが含まれている必要があります。NamingEnumerationそのため、デリゲートの名前付け列挙のリストを反復処理し、名前付きの各エントリが 1 回だけ出力されるようにする独自のコードを作成することになりました。
  6. コンテキスト記述子からマジック コンテキストをインスタンス化します。

    <Resources 
        className="package.name.tomcatextensions.MagicWARContext" 
        overlay="/data/some/dir"/>
    
  7. クラスを jar にパックし、これをコピーします。tomcat/lib

注意事項

Tomcat の内部クラスをオーバーライドしています。これにより、このコードは当然変更にさらされます。そのため、バージョンのアップグレード後にすべてが期待どおりに機能することを誰かが確認する必要があります。一部の保護されたメソッドの代わりに、実際の公開されたメソッドをオーバーライドできますが、それらのいくつかは最終的なものであるため、基本的に運が悪いです。

さらに、ルックアップ メソッドを介して非魔法のサブコンテキストを他のアプリケーション レイヤーに公開することができます。つまり、そのオーバーレイがもうないか、デプロイされた戦争のフォールバック リソースが含まれていないことを意味します。サブコンテキストが要求されたときに、いくつかの警告をログに追加することになりました。起動時に、これは で 1 回、 で 1 回の 2 回発生/WEB-INF/classes/WEB-INF/libます。
私のユースケースでは、これらのパスのいずれかを含む仮想オーバーレイを追加することを禁止しています。これは、Web コンテキストに外部クラス ファイルを表示させたくないためです。これは問題ではありません。ただし、他のクライアントがこれらのメソッドを呼び出して、予期しないことを行っている可能性があります。テスト中に問題は見つかりませんでしたが、キャッシュを有効にしたり、リソースを列挙したりすると、奇妙な効果が発生する可能性があります。サブコンテキストが使用されている場合に問題になる... もちろん、ルックアップによって返されたサブコンテキストの周りに仮想化されたラッパーを作成することもできますが、これが不要であることを願っているので、まだこれを行っていません。

もちろん、この方法を使用すると、不発の war デプロイメントでフォールバック webapp の特定のリソースをオーバーライドできます。Web コンテキストに外部リソースを追加する必要があるだけの場合は、Tomcat を使用できますaliases( How do I add aliases to a Servlet Context in java? を参照)。

自己責任で使用し、楽しんでください。

于 2013-04-09T07:26:40.857 に答える