struts2における静的ファイルについてのメモ

静的ファイルへのアクセス

通常jsやcssのファイルはWebContentやsrc/main/webapp(Maven Projectの場合)の中に置いて直接参照させます。
例えば、WebContent/css/main.csshttp://address/コンテキスト名/css/main.cssでアクセスできます。
もうひとつの方法として、社内フレームワークのようなものをstrutsのプラグインとして作る場合にプラグイン内に埋め込むということが出来ます。
簡単に言うと、下記のパッケージ(フォルダ)にあるファイルを/コンテキスト名/struts/ファイルへのpath/ファイル名でアクセスできます。もしくは/struts/の代わりに/static/でも同じ。

  • org.apache.struts2.static
  • template
  • org.apache.struts2.interceptor.debugging
  • static

例えば、struts2-jquery-pluginにある
template.js.base.jquery-1.x.x.jsは
/コンテキスト名/struts/js/base/jquery-1.x.x.jsでアクセス可能です。

ちなみに、デフォルトの状態だと
/static/simple/a.ftl
のようなアクセスが有効になってしまいます。
これはセキュリティ的にどうなのかなとちょっと思ってしまいます。

基本的な動作の流れ

デフォルトではorg.apache.struts2.dispatcher.DefaultStaticContentLoaderによってハンドリングされます。設定で変更可能です(後述)
クライアントからアクセスがあると、まずFilter#doFilter()が呼ばれます。
Filterはorg.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilterという前提で以下は説明します。FilterDispatcherはDeprecatedなので今回は無視します。
FilterはActionMapper#getMappingを呼び、対応するアクションクラスを探します。
見つからない場合、StaticContentLoaderの出番です。/static/や/struts/で始まっている場合、上記のフォルダからマッチするファイルを探してそれをクライアントに返します。
StaticContentLoaderも対象ファイルを見つけられない場合は、次のFilterに処理が渡されます。
通常は他のFilterはないと思うのでこの時点でWebContentやsrc/main/webappを見に行きそこにあるファイルがクライアントに返されます。

静的ファイルに関する設定

WebContentやsrc/main/webapp内の静的ファイルへのアクセスのパフォーマンス向上

上記のように、WebContentやsrc/main/webappにおいてあるファイルにアクセスする際は少しオーバーヘッドがあります。この処理をスキップさせる設定が可能です。
struts.xmlに下記のように追加します

<constant name="struts.action.excludePattern" value="/js/.*, /css/.*, /img/.*" />

これらのパターンにマッチするリクエストは、ActionMapper#getMappingやStaticContentLoaderの処理がスキップされます。

static contentとして探すpathを追加

上記の4つのpath以外に追加したい場合の設定です。
例えば、hoge.staticパッケージを追加したい場合はweb.xmlのフィルターの設定を書き換えます。

<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
<init-param>
<param-name>packages</param-name>
<param-value>hoge.static</param-value>
</init-param>
</filter>

これは起動時にDefaultStaticContentLoader#setHostConfig(HostConfig)で参照され、上記の4つのpathと同様に扱われます。

/struts/~~による静的ファイルへのアクセスを停止する

struts.xmlに下記の設定をするだけです。

<constant name="struts.serve.static" value="false" />

ただし、このようにすると独自でそれらのファイルを展開する必要があります。
パフォーマンス向上のための手段として使えます。
この値はDefaultStaticContentLoader#canHandle(String)で参照され、falseの場合は静的ファイルの探索は行いません。

静的ファイルをハンドリングするクラスをカスタマイズする

StaticContentLoaderをimplementsして新たなクラスを作成した上でstruts.xmlに設定を追加します。
この設定をしない場合、DefaultStaticContentLoaderが使用されます。

<bean type="org.apache.struts2.dispatcher.StaticContentLoader" class="MyStaticContentLoader" name="myLoader" />
<constant name="struts.staticContentLoader" value="myLoader" />

参考ページ
http://struts.apache.org/release/2.3.x/docs/static-content.html