AliasInterceptorはパラメータにエイリアスをつける。


<package name="example" namespace="/hogehoge" extends="struts-default">
<action name="hoge" class="example.HogeAction" method="browse">
<param name="aliases">#{ 'foo' : 'bar' }</param> - (1)
<interceptor-ref name="alias"/> - (2)
<result name="success">/date.jsp</result>
</action>
</package>

class HogeAction{
private String foo;
private String bar;
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
public String getBar() {
return bar;
}
public void setBar(String bar) {
this.bar = bar;
}
}

上記のようなstruts.xmlとActionクラスがあるとする。
通常、http://struts2/hogehoge/hoge.action?foo=aaaとリクエストが来たらHogeActionクラスのfooに対して"aaa"が設定されるが、(1)と(2)があることによりHogeActionクラスのbarに対して"aaa"が設定される。複数のパラメータに対してエイリアスをつけたい場合は#{ 'foo' : 'bar', 'foo2' : 'bar2'}のようにカンマで区切れば良い。また、デフォルトのエイリアスキー"aliases"を変更したい場合は、以下のようにすればよい。(以下は"booboo"に変更)


<package name="example" namespace="/hogehoge" extends="struts-default">
<action name="hoge" class="example.HogeAction" method="browse">
<param name="booboo">#{ 'foo' : 'bar' }</param>
<interceptor-ref name="alias">
<param name="aliasesKey">booboo</param>
</interceptor-ref>
<result name="success">/date.jsp</result>
</action>
</package>

InterceptorはActionの実行前や実行後に処理を差し込むことができる。
Actionに対してinterceptorを追加、変更、削除したい場合はstruts.xmlを修正するだけで済む。
com.opensymphony.xwork2.interceptor.Interceptorやcom.opensymphony.xwork2.interceptor.AbstractInterceptorを継承して自分でInterceptorを作ることもできるが、大抵のものはFrameworkで用意されているのでそれを使用するとよい。(struts-default.xmlのinterceptor要素でFrameworkで用意されているinterceptorが定義されている。)

サンプル1


<package name="example" namespace="/hogehoge" extends="struts-default">

<action name="Foo" class="example.Foo" method="insert">
   <interceptor-ref name="defaultStack"/>
<result>/example/Foo.jsp</result>
</action>

<action name="Bar" class="example.Bar" method="update">
   <interceptor-ref name="defaultStack"/>
<result>/example/Foo.jsp</result>
</action>
<package/>

example.Foo.insert(),example.Bar.update()が実行される前にdefaultStackというinterceptorが実行される。interceptor-refのname属性は1つのinterceptorにつけられた名前、または複数のinterceptorをひとまとめにしたものに名前をつけたもになている。struts-default.xmlで確認するとわかるが、上記のdefaultStackというinterceptorは複数のinterceptorを1まとめにして名前をつけたものになっている。
また、上記のようにpackage要素内それぞれのactionで同じinterceptorを使うのであれば下記のようにdefault-interceptor-refを使った書き方もできる。


サンプル2

<package name="example" namespace="/hogehoge" extends="struts-default">
<default-interceptor-ref name="defaultStack"/>

<action name="Foo" class="example.Foo" method="insert">
<result>/example/Foo.jsp</result>
</action>

<action name="Bar" class="example.Bar" method="update">
<result>/example/Foo.jsp</result>
</action>
<package/>



自分で作成したinterceptorやstruts-default.xmlに記載してある方法以外でひとまとめにしたものを使用したい場合は下記のように定義をすればよい

サンプル3

<package name="example" namespace="/hogehoge" extends="struts-default">
<interceptors> - (1)
<interceptor name="hogehoge" class="example.HogeHogeInterceptor"> - (2)

<interceptor-stack name="defaultStackHogeHoge"> - (3)
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="hogehoge"/>
</interceptor-stack>
<interceptors>

<action name="Foo" class="example.Foo" method="insert">
<interceptor-ref name="hogeHoge"/>
<result>/example/Foo.jsp</result>
</action>

<action name="Bar" class="example.Bar" method="update">
<interceptor-ref name="defaultStackHogeHoge"/>
<result>/example/Foo.jsp</result>
</action>
<package/>

定義の仕方は(1)のようにinterceptors要素を定義し、子要素として、新たなinterceptorの定義は(2)のように、新たなinterceptorをまとめたものの定義は(3)のように記載する。

result要素の属性には、以下の値が設定できる
name: マッピング名。省略した場合は"success"になる
type: Actionクラスの処理終了後に呼ばれるタイプ。省略した場合は"dispatcher"になる

tpyeに設定できる値としてデフォルトでは以下のものが設定できる

Type説明
chain他のActionクラスを呼び出す
dispatcherviewにjspを使う
freemarkerviewにfreemarkerを使う
httpheaderHTMLのヘッダーのみ返す
redirect他のURLへリダイレクトする
redirectAction他のActionクラスへリダイレクトする
streamファイルのダウンロードで使用
velocityviewにvelocityを使う
xsltviewにxsltを使う
plainTextviewにplainTextを使う


上記の値はstruts-default.xml内のresult-typeに定義されている。

サンプルを使って説明

<package name="example" namespace="/hogehoge" extends="struts-default">
<action name="Foo" class="example.Foo">
<result>/example/Foo1.jsp</result>
<result name="input">/example/Foo2.jsp</result>
</action>
<package/>
  • example.Fooクラスが"success"を返すと/example/Foo1.jspが呼ばれる。
  • example.Fooクラスが"input"を返すと/example/Foo2.jspが呼ばれる。


struts-default.xml内に定義してあるもので要件を満たせなければ、com.opensymphony.xwork2.Resultインターフェース、もしくはそれらの子クラスを継承する形で自分で作れば良い。作ったものはstruts-default.xmlで記載してあるように<result-types>タグでくくって宣言すれば使えるようになる


<package name="example" namespace="/hogehoge" extends="struts-default">
<result-types>
<result-type name="freemarker2" class="example.FreemarkerResult2" />
</result-types>

<action name="Foo" class="example.Foo">
<result type="freemarker2">/example/Foo.ftl</result>
</action>
<package/>

action要素の属性には、以下の値が設定できる
name: マッピング名
class: 呼び出されるクラス。省略するとcom.opensymphony.xwork2.ActionSupportクラスが呼ばれる。
method: 呼び出されるメソッド。省略するとexecute()メソッドが呼ばれる。
converter: ???

サンプル(基本パターン)

<package name="example" namespace="/hoge" extends="struts-default">
<action name="aaa"> - (1)
<result>showcase.jsp</result>
</action>
<action name="bbb" class="example.FooAction"> - (2)
<result>/example/Foo.jsp</result>
</action>
<action name="ccc" class="example.BarAction" method="insert"> - (3)
<result>/example/Foo.jsp</result>
</action>
<action name="ddd" class="example.BarAction" method="update"> - (4)
<result>/example/Foo.jsp</result>
</action>
<package/>


コンテキスト名はstruts2,マッピングされる拡張子をactionとすると、
  • http://struts2/hoge/aaa.actionで(1)にマッピングされる。class、methodが省略されているのでcom.opensymphony.xwork2.ActionSupport.execute()が呼ばれる。
  • http://struts2/hoge/bbb.actionで(2)にマッピングされる。example.FooAction.execute()が呼ばれる
  • http://struts2/hoge/ccc.actionで(3)にマッピングされる。example.BarAction.insert()が呼ばれる
  • http://struts2/hoge/ccc.actionで(4)にマッピングされる。example.BarAction.update()が呼ばれる


ワイルドカードを使ったマッピングを行うこともできる。

サンプル(ワイルドカード使用パターン)
<package name="example" namespace="/hoge" extends="struts-default">
<action name="hoo_*" class="example.BarAction" method="{1}"> - (1)
<result>/example/Foo.jsp</result>
</action>
<action name="*_bar" class="example.Hoge{1}Action""> - (2)
<result>showcase.jsp</result>
</action>
<package/>
  • http://struts2/hoge/hoo_insert.actionで(1)にマッピングされる。example.BarAction.insert()が呼び出される。
  • http://struts2/hoge/hoo_bar.actionで(1)にマッピングされる。example.BarAction.update()が呼び出される。
  • http://struts2/hoge/hoge_insert.actionで(2)にマッピングされる。example.HogeinsertAction.execute()が呼び出される。
  • http://struts2/hoge/hoge_update.actionで()にマッピングされる。example.HogeupdaterAction.execute()が呼び出される。
(1)は基本パターンの(3)と(4)を1つにまとめて書く例になっている。


Springと一緒に使用して、Actionをspringに管理させる場合は以下のようになる。
サンプル(ActionクラスをSpringで管理パターン)
<package name="example" namespace="/hoge" extends="struts-default">
<action name="hoge" class="hogehoge">
<result>/example/Foo.jsp</result>
</action>

これはspringで使用するapplicationContext.xmlの一部

<bean id="hogehoge" class="example.HogeAction" scope="request" ></bean>

classで指定しているhogehogeがhogehoge.javaではなく、springで管理しいるbeanのidとマッピングされる。springで管理する際にはscope要素に気をつける。springはデフォルトスコープがsingletonだが、struts2のActionクラスはステートフルなクラスなのでスコープがsingletonということはほぼない。大抵はrequestでよいと思われる。Actionクラスをセッションで管理したければsessionにすればよい。

package要素の属性には、以下の値が設定できる
name :複数のアクションをグループ可する際の名前。別のpakage名とダブらないようにする(必須)
extends :別のpackageを継承する。継承することによりそのパッケージの要素にアクセスできるようになる(任意)
namespace:urlの一部になる(任意)
abstract :trueを設定すると、子要素のactionが必須項目でなくなる(任意)

サンプルを使って説明


<package name="example" namespace="/hogehoge" extends="struts-default">
<action name="Foo" class="example.Foo">
<result>/example/Foo.jsp</result>
</action>

<action name="Bar" class="example.Bar">
<result>/example/Bar.jsp</result>
</action>
<package/>

上の例だと、
・exampleという名前でグループ化
・アプリケーションのコンテキストがstruts2とすると、このグループのURLはhttp(s)://struts2/hogehoge/xxx になる
・struts-defaultの要素にアクセスできる
・abstract要素がないので子要素にはactionが必ず必要
ということになる。

ちなみにstruts-defaultのパッケージ要素はstruts2がデフォルトで持っているもので、
src/main/resources/struts-default.xml内に記載してある。以下がその内容。

<package name="struts-default" abstract="true">
<result-types>
<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
<result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/>
<result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
<result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/>
<result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/>
<result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>
<result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>
<result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/>
<result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
<result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" />
</result-types>

<interceptors>
<interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
<interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
<interceptor name="chain" class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>
<interceptor name="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/>
<interceptor name="clearSession" class="org.apache.struts2.interceptor.ClearSessionInterceptor" />
<interceptor name="createSession" class="org.apache.struts2.interceptor.CreateSessionInterceptor" />
<interceptor name="debugging" class="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" />
<interceptor name="externalRef" class="com.opensymphony.xwork2.interceptor.ExternalReferencesInterceptor"/>
<interceptor name="execAndWait" class="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/>
<interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>
<interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>
<interceptor name="i18n" class="com.opensymphony.xwork2.interceptor.I18nInterceptor"/>
<interceptor name="logger" class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/>
<interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
<interceptor name="scopedModelDriven" class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/>
<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
<interceptor name="actionMappingParams" class="org.apache.struts2.interceptor.ActionMappingParametersInteceptor"/>
<interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>
<interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
<interceptor name="scope" class="org.apache.struts2.interceptor.ScopeInterceptor"/>
<interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/>
<interceptor name="sessionAutowiring" class="org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor"/>
<interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>
<interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/>
<interceptor name="tokenSession" class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/>
<interceptor name="validation" class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/>
<interceptor name="workflow" class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/>
<interceptor name="store" class="org.apache.struts2.interceptor.MessageStoreInterceptor" />
<interceptor name="checkbox" class="org.apache.struts2.interceptor.CheckboxInterceptor" />
<interceptor name="profiling" class="org.apache.struts2.interceptor.ProfilingActivationInterceptor" />
<interceptor name="roles" class="org.apache.struts2.interceptor.RolesInterceptor" />
<interceptor name="jsonValidation" class="org.apache.struts2.interceptor.validation.JSONValidationInterceptor" />
<interceptor name="annotationWorkflow" class="com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor" />

<!-- Basic stack -->
<interceptor-stack name="basicStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="actionMappingParams"/>
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*,^struts\..*</param>
</interceptor-ref>
<interceptor-ref name="conversionError"/>
</interceptor-stack>

<!-- Sample validation and workflow stack -->
<interceptor-stack name="validationWorkflowStack">
<interceptor-ref name="basicStack"/>
<interceptor-ref name="validation"/>
<interceptor-ref name="workflow"/>
</interceptor-stack>

<!-- Sample JSON validation stack -->
<interceptor-stack name="jsonValidationWorkflowStack">
<interceptor-ref name="basicStack"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel</param>
</interceptor-ref>
<interceptor-ref name="jsonValidation"/>
<interceptor-ref name="workflow"/>
</interceptor-stack>

<!-- Sample file upload stack -->
<interceptor-stack name="fileUploadStack">
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="basicStack"/>
</interceptor-stack>

<!-- Sample model-driven stack -->
<interceptor-stack name="modelDrivenStack">
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="basicStack"/>
</interceptor-stack>

<!-- Sample action chaining stack -->
<interceptor-stack name="chainStack">
<interceptor-ref name="chain"/>
<interceptor-ref name="basicStack"/>
</interceptor-stack>

<!-- Sample i18n stack -->
<interceptor-stack name="i18nStack">
<interceptor-ref name="i18n"/>
<interceptor-ref name="basicStack"/>
</interceptor-stack>

<!-- An example of the paramsPrepareParams trick. This stack
is exactly the same as the defaultStack, except that it
includes one extra interceptor before the prepare interceptor:
the params interceptor.
This is useful for when you wish to apply parameters directly
to an object that you wish to load externally (such as a DAO
or database or service layer), but can't load that object
until at least the ID parameter has been loaded. By loading
the parameters twice, you can retrieve the object in the
prepare() method, allowing the second params interceptor to
apply the values on the object. -->
<interceptor-stack name="paramsPrepareParamsStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*,^struts\..*</param>
</interceptor-ref>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="actionMappingParams"/>
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*,^struts\..*</param>
</interceptor-ref>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel</param>
</interceptor-ref>
</interceptor-stack>
<!-- A complete stack with all the common interceptors in place.
Generally, this stack should be the one you use, though it
may do more than you need. Also, the ordering can be
switched around (ex: if you wish to have your servlet-related
objects applied before prepare() is called, you'd need to move
servletConfig interceptor up.
This stack also excludes from the normal validation and workflow
the method names input, back, and cancel. These typically are
associated with requests that should not be validated.
-->
<interceptor-stack name="defaultStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="debugging"/>
<interceptor-ref name="profiling"/>
<interceptor-ref name="scopedModelDriven"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="actionMappingParams"/>
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*,^struts\..*</param>
</interceptor-ref>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
</interceptor-stack>
<!-- The completeStack is here for backwards compatibility for
applications that still refer to the defaultStack by the
old name -->
<interceptor-stack name="completeStack">
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
<!-- Sample execute and wait stack.
Note: execAndWait should always be the *last* interceptor. -->
<interceptor-stack name="executeAndWaitStack">
<interceptor-ref name="execAndWait">
<param name="excludeMethods">input,back,cancel</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="execAndWait">
<param name="excludeMethods">input,back,cancel</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>

<default-interceptor-ref name="defaultStack"/>
<default-class-ref class="com.opensymphony.xwork2.ActionSupport" />
</package>

でましたね。
http://www.eclipse.org/

スプラッシュ画面は3.4とほとんど同じだけど、Welcome画面が大分変わってた。



かっちょいい。

struts.xmlを分割して管理したい場合に使用。


(例)


<struts>
 ...

<include file="struts-chat.xml" />
<include file="struts-interactive.xml" />
<include file="struts-hangman.xml" />
<include file="struts-tags.xml"/>
<include file="struts-validation.xml" />
<include file="struts-actionchaining.xml" />
<include file="struts-ajax.xml" />
<include file="struts-fileupload.xml" />
<include file="struts-person.xml" />
<include file="struts-wait.xml" />
<include file="struts-jsf.xml" />
<include file="struts-token.xml" />
<include file="struts-model-driven.xml" />
<include file="struts-integration.xml" />
<include file="struts-filedownload.xml" />
<include file="struts-conversion.xml" />
<include file="struts-freemarker.xml" />
<include file="struts-tiles.xml" />
<include file="struts-xslt.xml" />

 ...

<struts/>