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/>

struts.xmlで使用できる属性、要素はここのdtdファイルでわかる。

まずはconstant要素

これはsturts2のデフォルトの設定を上書く際に使用する。
デフォルトの設定はstruts2-core-2.1.xxx.jarのorg/apache/struts2/default.propertiesに書かれている。
デフォルトでは以下の値が定義されている


struts.i18n.encoding=UTF-8
struts.objectFactory.spring.autoWire = name
struts.objectFactory.spring.useClassCache = true
struts.objectFactory.spring.autoWire.alwaysRespect = false
struts.multipart.parser=jakarta
struts.multipart.saveDir=
struts.multipart.maxSize=2097152
struts.action.extension=action,,
struts.serve.static=true
struts.serve.static.browserCache=true
struts.enable.DynamicMethodInvocation = true
struts.enable.SlashesInActionNames = false
struts.tag.altSyntax=true
struts.devMode = false
struts.i18n.reload=false
struts.ui.theme=xhtml
struts.ui.templateDir=template
struts.ui.templateSuffix=ftl
struts.configuration.xml.reload=false
struts.velocity.configfile = velocity.properties
struts.velocity.contexts =
struts.velocity.toolboxlocation=
struts.url.http.port = 80
struts.url.https.port = 443
struts.url.includeParams = none
struts.dispatcher.parametersWorkaround = false
struts.freemarker.templatesCache=false
struts.freemarker.beanwrapperCache=false
struts.freemarker.wrapper.altMap=true
struts.freemarker.mru.max.strong.size=100
struts.xslt.nocache=false
struts.mapper.alwaysSelectFullNamespace=false
struts.ognl.allowStaticMethodAccess=false

開発中のみ、値を変更する(false→ture)可能性が大きいパラメーター
  • struts.configuration.xml.reload:リクエストの度にxmlファイルを読み直す
  • struts.i18n.reload:リクエストの度にリソースファイルを読み直す(※と書いてあるけどファイルの内容を変更しても読み直してくれなかった。なぜ??)
  • struts.devMode:上記2つを1度に設定し、ログも詳細に吐き出される。
    また、jsp上に<s:debug></s:debug>タグを記載すると[debug]というリンクが出現し、クリックするとValueStackに積まれている内容を見ることができる。これは自分が想定していた値がjsp上でとれなかった場合に原因を探る際にすごく便利
開発以降、変更する可能性が大きいパラーメーター
struts.action.extension:デフォルトはstruts.action.extension=action,,となっている(カンマ区切りで空文字もあることに注意)これは、例えばstruts.xml内で<action name="hoge" class="HogeHoge">と定義があった場合、
xxx/hoge.actionまたは、xxx/hogeというURLでHogeHogeクラスが呼び出されることを意味する。なので、デフォルトのactionという拡張子や拡張子なしが嫌な場合は、この値を変更すればよい。

constantタグ以外でのパラメーターの変更方法
struts.xml内でconstantタグを使用して変更する以外に、変更したい値をstruts.propertiesに書き、classpathが通っているフォルダの直下に置くことでも変更することができる。もし、struts.xmlとstruts.properties両方で同じパラメータに対し違う値を設定していたら、struts.propertiesで設定した値が有効になる。

例)struts.xmlでは<constant name="struts.action.extension" value="do,," />、struts.propertiesではstruts.action.extension=cgiと設定した場合、<action name="hoge">のhogeにマッピングされてるクラスに対してはxxx/hoge.cgiでのみアクセスでき、xxx/hoge.doやxxx/hogeではアクセスできない。

このやり方よりもMavenを使ったほうが楽だったので変更する。

前提

  • ここの前提の状態が終了していること
  • Mavenがインストール、環境設定への設定済みで、eclipseにM2_REPOが設定してあること。(m2eclipseなどのeclipseからMavenを利用する為のプラグインは入れる必要はなし。)

手順
  1. [Java Project]を新規に作成(プロジェクト名はstruts2-showcaseとして以後説明)
  2. 作成したプロジェクトを右クリック→[import]→[General]→[File System]を選択
  3. [File Directory:]にここでダウンロード、展開したフォルダ内のsrc/apps/showcaseまでを入力し[shoucase]にチェックをいれ[Finish]ボタンをクリック。(pom.xmlにもチェックが入っていること。また、この時点ではコンパイルエラーが出てるが気にしない。)
  4. コンソールにて1.で作成したプロジェクト名まで移動し mvn eclipse:eclipse とコマンドを打つ。「BUILD SUCCESSFUL」 が出力されれば成功。
  5. eclipse上から作成したプロジェクト上でF5を押し、コンパイルエラーがなくなっていることを確認する。
  6. Project Explorer上から作成したプロジェクト上で、右クリック→[Properties]→[Tomcat]→[全般]タブを選択し、以下の処理を行う
    ・[Tomcatプロジェクト]にチェックを入れる
    ・コンテキスト名を入力(ここでは「struts2-showcase」とする。)
    ・Webアプリケーション・ルートとするサブディレクトリーに「/src/main/webapp」を入力。
  7. [開発用クラスローダーのクラスパス]タブで以下の処理を行う
    ・開発用クラスローダーを有効にする」にチェックを入れる。
    ・M2_REPO/javax/servlet/servlet-api/servlet-api-2.4.jar以外のチェックボックスにチェックを入れる
  8. Project Explorerのプロジェクト上で、右クリック→[Tomcat プロジェクト]→[コンテキストの定義を更新]
  9. eclipse上のtomcatアイコンをクリックしてtomcatを起動。
  10. http://localhost:8080/struts2にアクセス(struts2-showcaseは6.の「コンテキスト名」で入力した名前)
xworkのソースを別途ダウンロードしなくても、mvnコマンドを打ったときにダウンロードとjarファイルにアタッチしてくれるので楽

ここを参考に導入。

java


public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}

xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="false" />
<include file="example.xml"/>
<package name="default" namespace="/" extends="struts-default">
<default-action-ref name="index" />
<action name="index">
<result type="redirectAction">
<param name="actionName">HelloWorld</param>
<param name="namespace">/example</param>
</result>
</action>
</package>
<!-- Add packages here -->
</struts>


おー、いい感じ。

struts2のサンプルをデバックしながら動かす際に、struts2自体のソースもデバックで追えるようにする。

※Mavenが使用できるのであればここの手順のほうがよい

事前準備

 xworksのソースここからダウンロードしておく。(struts2.1.6で使用している2.1.2のソースの直リンク
 ※xworksはstruts2が継承しているフレームワーク。
 

手順

  1. ここで作ったプロジェクトを右クリック→[Properties]
  2. [Java Build Path]→[Libraries]
  3. [Web App Librarie]内の[struts2-core-2.1.6.jar]→[Source attachment]をダブルクリック
  4. [Extarnal Folder]をクリックし、以前ダウンロードし展開したフォルダ内のsrc/core/src/main/javaまでを選択し、OKをクリック
  5. [Web App Librarie]内の[xwork-2.1.2.jar]→[Source attachment]をダブルクリック
  6. [Extarnal Folder]をクリックし、事前準備でダウンロードし展開したフォルダ内の/src/javaまでを選択入力し、OKをクリック

上記手順終了後、Project Explorerで該当プロジェクトの[Java Resources: src]→[libraries]→[Web App Libraries]内のstruts2-core-2.1.6.jarとxwork-2.1.2.jar内の適当なクラスファイルをクリックすれば、ソースが見れるようになり、デバックポイントも張れるようになる。

※Mavenが使用できるのであればここの手順のほうがよい

前提

  • eclipseインストール済み(バージョン3.4)
  • tomcatプラグインインストール済み(まず、eclipseのdropinsフォルダに展開したフォルダをごと配備し、次にtomcatのlibフォルダにDevLoader.zipのみを配備する)


手順
  1. eclipseのProject Explorer上で右クリック→[import > ]→[WAR file]
  2. ダイアログが出るので、「WAR file:」にstruts2-showcase-2.1.6.warが置いてある場所を入力して[Finish]
  3. Project Explorer上にstruts2-showcase-2.1.6ができるので、右クリック→[Properties]で、[Java Compailer]を選択し、JDKのバージョンが1.5以上であることを確認。
  4. [Java Build Path]→[Libraries]→[Add External Jars]でtomcatのlibフォルダにあるservlet-api.jarを追加。
    (JVMAction.javaと言うクラスがコンパイルできないため)
  5. [Tomcat]→[全般]で以下の処理を行う
    ・[Tomcatプロジェクト]にチェックを入れる。
    ・コンテキスト名を入力(ここでは「struts2」とする。)
    ・Webアプリケーション・ルートとするサブディレクトリーに「/WebContent」を入力。 
  6. [Tomcat]→[開発用クラスローダーのクラスパス]で以下の処理を行う
    ・開発用クラスローダーを有効にする」にチェックを入れる。
    ・4.で追加したservlet-api.jar以外のチェックボックスにチェックを入れる
  7. Project Explorerのプロジェクト上で、右クリック→[Tomcat プロジェクト]→[コンテキストの定義を更新]
  8. eclipse上のtomcatアイコンをクリックしてtomcatを起動。
  9. http://localhost:8080/struts2にアクセス(struts2は5.の「コンテキスト名」で入力した名前)
これで、eclipse上からブレークポイントを張ってデバックしながら動作を確認できる。

2009/06/09

struts2

復習もかねて、つらつらと書いていく。

前提

  • javaインストール済み(バージョン6)
  • tomcatインストール済み(バージョン6)

まずは、サンプルを動かしてみる。
ここから全部入りのstruts-2.1.x-all.zipファイルをダウンロード、展開する。
(今の最新バージョンはstruts-2.1.6-all.zip。以後、このバージョンで話をすすめる。)

appsフォルダにあるのがサンプルアプリ。
その中のstruts2-showcase-2.1.6.warをtomcatのwebappsフォルダにコピー。

tomcatを起動し、http://localhost:8080/struts2-showcase-2.1.6 にアクセス。




validationチェック、tokenチェック、ファイルアップロードなど、いろいろなサンプルがある。画面下のView Sourcesをクリックすれば、そのサンプルがどのようなソースコードで作られてるか確認できる。

AmazonからGrails徹底入門が届いたのでGrailsを触ってみる。

以下、Grailsではないが、ちょっとはまったこと。

P.34 手順3 Grailsを使えるように設定するで
export JAVA_HOME=xxxx (未設定の場合)
export GRAILS_HOME=xxxx

とあるが、以下の設定もしないと次の手順4 Grailsを使ってみるで
$ grails xxxx とコマンドとコマンドを打っても
bash: grails: command not found
となってしまうので注意!!!

export PATH=$PATH:$JAVA_HOME/bin (未設定の場合)
export PATH=$PATH:$GRAILS_HOME/bin