Zero ConfigurationでHello World
まずは、例によって「Hello Worldアプリケーション」を作成していきましょう。次の図のように、ごくシンプルに、リンクをクリックすれば、Actionクラスが処理されて、文字列を表示するというものです。

ファイル構成
バージョンが2.1.6ということもありますので、新たなプロジェクト「ZeroProject」、としました。最初に、バージョン2.1.6のjarファイルをコピーしておきます。「http://www.meisei-u.ac.jp/mirror/apache/dist/struts/binaries/struts-2.1.6-all.zip」を解凍してできたlibディレクトリ以下のファイルが、Struts 2本体とプラグインファイルです。今回は、以下に示した、基本となるjarファイルとConventionプラグインを使用します。
- /WEB-INF/lib/commons-fileupload-1.2.1.jar
- /WEB-INF/lib/commons-io-1.3.2.jar
- /WEB-INF/lib/commons-logging-1.1.jar
- /WEB-INF/lib/freemarker-2.3.13.jar
- /WEB-INF/lib/junit-3.8.1.jar
- /WEB-INF/lib/ognl-2.6.11.jar
- /WEB-INF/lib/spring-test-2.5.6.jar
- /WEB-INF/lib/struts2-core-2.1.6.jar
- /WEB-INF/lib/xwork-2.1.2.jar
- /WEB-INF/lib/struts2-convention-plugin-2.1.6.jar
全体のファイル構成は、次のようになります。順に見ていきましょう。ここでは、「Hello Worldアプリケーション」の構成だけを示しています。ダウンロードできるサンプルには、後述するサンプルも含まれています。
<ContextRoot> ├ /WEB-INF │ ├ /classes │ │ ├ /zero.action │ │ │ └ ZeroAction.class │ │ └ struts.xml │ ├ /content │ │ └ zero.jsp │ ├ /lib │ │ └ 参照ライブラリー │ └ web.xml └ index.jsp
web.xml
web.xmlの記述も新しいバージョンでは、若干変更があります。
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>ZeroProject</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
<filter>タグで指定するクラスが、org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilterクラスとなりました。以前のFilterDispatcherクラスは、非推奨に変更されています。ただし、このクラスには、前述した文字コードの変換漏れがあるため、リクエスト文字などで文字化けが発生してしまいます。応急的な解決策としては、文字コードの変換処理をActionクラスに追加するか、以前のFilterDispatcherクラスを使うかのどちらかです。
それ以外は、2.0系列との違いはありません。
struts.xml
次にstruts.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" />
</struts>
「Zero Configuration」でなければ、Actionクラスの定義など、いろいろ記述する必要があるところですが、これだけで大丈夫です。画面遷移もまったく記述不要です。
Conventionプラグインの設定も、デフォルトでかまわないのであれば、特に指定する必要はありません(既定値などは後述します)。
Actonクラス
Actonクラスは、次のように、連載第一回目のものとほぼ同じです。異なるのは、このクラスが、あるルールに従っているところだけです。
package zero.action;
public class ZeroAction {
private static final long serialVersionUID = 1L;
private String replyMsg;
public String getReplyMsg() {
return replyMsg;
}
public void setReplyMsg(String message) {
this.replyMsg = message;
}
public String execute() throws Exception {
this.setReplyMsg( "これがZero Configuration" );
return "success";
}
}
あるルールとは、このクラスをActionクラスだと認識させるためのもので、struts.xmlでの定義の代わりになるものです。Conventionプラグインによって、デフォルトでは、以下のいずれかのルールに従っているクラスをActionクラスと認識します。
- com.opensymphony.xwork2.Actionインターフェイスを実装してるクラス
- クラス名が「Action」で終わっているクラス
またConventionプラグインは、この条件に当てはまるActionクラスを、struts、struts2、action、actionsという名前のパッケージからサーチします。
サンプルのZeroAction.javaでは、パッケージ名がzero.actionで、クラス名がZeroActionとなっていますので、このクラスはActionクラスとして認識されることになります。
Actionクラスの名前が、デフォルトのAction名の生成に使用され、execute()メソッドが呼び出されます。ただし、クラス名の最後の「Action」は、Action名から除かれ、さらに大文字と小文字を組みあわせたCamel形式の名前は、小文字をハイフンで区切った名前に変換されます。ZeroActionクラスなら、「zero.action」になるということです。
また、ここで重要なポイントは、パッケージの階層とクラス名が、ActionのURIと対応(マッピング)していることです。パッケージの階層を上位からサーチして、最初にActionクラスのパッケージだと認識したところがURIのルートになります。つまり、sample.actionパッケージにあるZeroActionクラスなら、sample.actionがルートとなり、「/zero.action」ということです。その他、クラス名とActionを示すURIのマッピング例は、次のとおりです。
| クラス名 | URI |
| zero.action.ZeroAction | /zero.action |
| sample.action.test.ZeroAction | /test/zero.action |
| sample.struts.company.details.HelloWorldAction | /company/details/hello-world |
なお、URIの.actionは省略可能ですので、「/zero」とするだけで、「/zero.action」と見なされます。
Result処理
Resultに指定するViewテンプレートファイルにもルールがあります。サンプルコードでは、/WEB-INF/content/zero.jspとしていますが、デフォルトでは、/WEB-INF/content/以下からファイルがサーチされます。サーチされるファイル名は、Resultコードと対応しており、「Action名-Resultコード.jsp」となります。つまり、zero.actionから呼ばれるメソッドが"success"を返すなら、「zero-success.jsp」となります。
なお、Resultコードが"success"の場合は省略可能ですので、サンプルコードのように「Action名.jsp」が対応します。また、Actionクラスがサブパッケージにあれば、対応するResultファイルも同じ階層にあるものが対応することになります。
実際のマッピング例は、次のとおりです。
| ActionのURI | サーチされるデフォルトのViewファイル |
| /zero.action | /zero.jsp |
| /test/zero.action | /test/zero-success.jsp |
| /company/details/hello-world | /company/details/hello-world.jsp |
なお、デフォルトのResultタイプが「Dispatcher」ですので、まずjspファイルがサーチされ、それがなければ、HTMLファイル(.html)、velocity(.vm)、freemarker(.ftl)の順に探していきます。
従ってサンプルコードでは、「/zero」を指定すると、「/WEB-INF/content/zero.jsp」がViewテンプレートファイルとして用いられることになります。
注意点
Conventionプラグインの動作で、注意が必要なものがあります。それは、Actionクラスが見つからない場合、Actionクラスの処理がスキップされて、Viewテンプレートのみを処理してしまうことです。例えば、/WEB-INF/content/zero2.jspというファイルだけがあり、対応するActionクラスがない状態でも、「/zero2.action」とすると、そのjspファイルが表示されてしまいます。
使い方によっては便利な機能ですが、危険な機能とも言えます。あやまって、Actionクラスと認識されないActionクラスを作ってしまうと、そのクラスの実行がスルーされることになってしまうのです。
