Springを使ったWebアプリケーション4

Requestからパラメータを直接取得したりしていたのでそこら辺を改善したい。
Springはパラメータの保持にCommandというのを使うらしいので使ってみる。まずは、userNameとpasswordを受け取るCommand。

spring.sample.LogonCommand.java

package spring.sample;

public class LogonCommand {
    
    private String userName = null;
    private String password = null;

    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
}

このコマンドを扱うにはCommandControllerが必要なので、コントローラも作成。とりあえずのところSimpleFormControllerを継承して、LogonControllerを以下のように変えてみる。

spring.sample.LogonController.java

package spring.sample;

import java.util.HashMap;
import java.util.Map;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;

public class LogonController extends SimpleFormController {
    
    protected ModelAndView onSubmit(Object command) throws Exception {
        LogonCommand logonCommand = (LogonCommand) command;
        String userName = logonCommand.getUserName();
        String password = logonCommand.getPassword();
        Map model = new HashMap();
        model.put("userName", userName);
        model.put("password", password);
        return new ModelAndView("logonResult", "model", model);
    }
}

Commandとコントローラを登録。

/WEB-INF/springapp-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<!--  - Application context definition for "springapp" DispatcherServlet.  -->
<beans>
    <bean id="logonController" class="spring.sample.LogonController">
        <property name="commandClass">
            <value>spring.sample.LogonCommand</value>
        </property>
    </bean>
    <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/logon.html">logonController</prop>
            </props>
        </property>
    </bean>
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass"><value>org.springframework.web.servlet.view.JstlView</value></property>
        <property name="prefix"><value>/WEB-INF/jsp/</value></property>
        <property name="suffix"><value>.jsp</value></property>
    </bean>

</beans>

ちゃんと動いた。パラメータをCommandにバインドするところは自動的にやってくれるのですね。
んじゃ、ユーザ名とパスワードの必須チェックをしてみる。
まずはメッセージリソースを作る。

/WEB-INF/src/messages.properties

error.required={0}に値が入力されていません。

Springで国際化されたメッセージを扱うのはMessageSourceらしいです。

/WEB-INF/applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <bean id="messages" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basename"><value>messages</value></property>
    </bean>
</beans>

使うのはValidatorですか。。


    

Springを使ったWebアプリケーション3

もうちょっと実際にありそうな感じにしていきます。ということで、ログイン画面を作ってみる。とりあえずjspから。

/WEB-INF/jsp/logon.jsp

<%@ include file="/WEB-INF/jsp/include.jsp" %>
<%@ page contentType="text/html; charset=Windows-31J" %>

<html>
  <head>
    <title>Login</title>
  </head>
  <body>
    <form action="logon.html" method="POST">
       ユーザ名:<input type="text" name="userName"/><br/>
       パスワード:<input type="password" name="password"/><br/>
       <input type="submit" value="ログイン" />
    </form>
  </body>
</html>

/WEB-INF/jsp/logonResult.jsp

<%@ include file="/WEB-INF/jsp/include.jsp" %>
<%@ page contentType="text/html; charset=Windows-31J" %>

<html>
  <head>
    <title>Logon Result</title>
  </head>
  <body>
     ユーザ名:<c:out value="${model.userName}"/><br/>
     パスワード:<c:out value="${model.password}"/><br/>
  </body>
</html>

コントローラも新しく作ります。

spring.sample.HelloController.java

package spring.sample;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

public class LogonController implements Controller {

    public ModelAndView handleRequest(HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        String userName = request.getParameter("userName");
        String password = request.getParameter("password");
        Map model = new HashMap();
        model.put("userName", userName);
        model.put("password", password);
        return new ModelAndView("logonResult", "model", model);
    }

}

コントローラの登録。

/WEB-INF/springapp-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<!--  - Application context definition for "springapp" DispatcherServlet.  -->
<beans>
    <bean id="helloSpringController" class="spring.sample.HelloController"/>
    <bean id="logonController" class="spring.sample.LogonController"/>
    <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/logon.html">logonController</prop>
            </props>
        </property>
    </bean>
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass"><value>org.springframework.web.servlet.view.JstlView</value></property>
        <property name="prefix"><value>/WEB-INF/jsp/</value></property>
        <property name="suffix"><value>.jsp</value></property>
    </bean>

</beans>

できました。

しかし、納得できないくらいかっこ悪いやり方ですね。

Springを使ったWebアプリケーション2

return new ModelAndView("helloSpring");

ModelAndViewという名前にも関わらずViewの情報しか返してないのでモデルも返してみる。
ModelAndViewのAPIを見るとMapを引数に取るものと、StringとObjectを引数に取るものがある。おそらく複数のモデルを返す場合はMap、モデルが一つの場合はString,Objectを使うのでしょう。
とりあえずMap引数バージョンを使ってみる。
コントローラをこんな感じに修正しました。

spring.sample.HelloController.java

package spring.sample;

import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

public class HelloController implements Controller {
    public ModelAndView handleRequest(HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        Map model = new HashMap();
        model.put("greeting", "Hello");
        model.put("name", "Spring");
        return new ModelAndView("helloSpring", "model", model);
    }
}

jspはこんな感じです。

/WEB-INF/jsp/helloSpring.jsp

<%@ include file="/WEB-INF/jsp/include.jsp" %>
<html>
  <head>
    <title>Spring Application</title>
  </head>
  <body>
    <h1><c:out value="${model.greeting}"/> <c:out value="${model.name}"/>!</h1>
  </body>
</html>

ふむふむ。問題なく出ました。
せっかくなのでbean定義に書いてJavaBeanの方も試してみますか。

spring.sample.HelloSpringModel.java

package spring.sample;

public class HelloSpringModel {
    private String greeting = null;
    private String name = null;
    public String getGreeting() {
        return greeting;
    }
    public void setGreeting(String greeting) {
        this.greeting = greeting;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

POJOです。

bean定義ファイルに追加。今度はapplicationContext.xmlに設定してみます。

/WEB-INF/applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <bean id="helloSpringModel" class="spring.sample.HelloSpringModel">
        <property name="greeting"><value>Hello</value></property>
        <property name="name"><value>Spring</value></property>
    </bean>
</beans>

お次はコントローラ。ApplicationContextを取得するにはRequestContextUtilsを使う。

spring.sample.HelloController.java

package spring.sample;

import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.ApplicationContext;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.support.RequestContextUtils;

public class HelloController implements Controller {
    public ModelAndView handleRequest(HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        ApplicationContext context = 
            RequestContextUtils.getWebApplicationContext(request);
        Object model = context.getBean("helloSpringModel");
        return new ModelAndView("helloSpring", "model", model);
    }
}

これも当然ですがうまく行きました。
なかなか簡単です、Spring MVC

Springを使ったWebアプリケーション1

環境

spring framework 1.2
Tomcat 5.0
Eclipse3.0.1

フォルダ構成

springapp
 +-webapps
   +-WEB-INF
     +-jsp…JSPはここに置く
     +-lib…ライブラリファイル関連
     +-src…ソースコード
     +-classes…ビルドフォルダ
     +-springapp-servlet.xml…bean定義ファイル
     +-applicationContext.xml…bean定義ファイル

とりあえず、[サーブレット名]-servlet.xmlとapplicationContext.xmlの区別が良くわからん。今回はコントローラー関連はspringapp-servlet.xml。springに依存しなそうなモデルや、ビジネスオブジェクト関連はapplicationContext.xmlにしておく。

Hello Spring

定番のアレ。
なにはともあれ、まずはサーブレットをweb.xmlに定義しないと。ついでにapplicationContext.xmlをロードするContextLoaderListenerも。

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC '-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN' 'http://java.sun.com/dtd/web-app_2_3.dtd'>
<web-app>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <servlet>
    <servlet-name>springapp</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>springapp</servlet-name>
    <url-pattern>*.html</url-pattern>
  </servlet-mapping>
</web-app>

とりあえず、Controllerインタフェースをそのまま実装する方向で。

spring.sample.HelloController.java

package spring.sample;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

public class HelloController implements Controller {
    public ModelAndView handleRequest(HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        return new ModelAndView("/WEB-INF/jsp/helloSpring.jsp");
    }
}

/WEB-INF/jsp/helloSpring.jsp

<%@ include file="/WEB-INF/jsp/include.jsp" %>
<html>
  <head>
    <title>Spring Application</title>
  </head>
  <body>
    <h1>Hello Spring!</h1>
  </body>
</html>

/WEB-INF/jsp/include.jsp

<%@ page session="false"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %>

作ったコントローラを登録する。

springapp-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<!--  - Application context definition for "springapp" DispatcherServlet.  -->
<beans>
    <bean id="helloSpringController" class="spring.sample.HelloController"/>
    <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/hello.html">helloSpringController</prop>
            </props>
        </property>
    </bean>
</beans>

http://localhost:8080/springapp/hello.html
にアクセスすると。。


でました。

ふむふむ。超ショボイですね。まあ、今のところControllerを生で実装してるのでこんな感じでしょうか。。
とりあえず、

return new ModelAndView("/WEB-INF/jsp/helloSpring.jsp");

では、さすがに酷すぎるのでちょっと手を入れてみます。そこで使ってみるのは、ViewResolverです。
ModelAndViewの第一引数がView名なんだけど、論理的なView名から物理的なリソースパスへ変換するわけですね。
springapp-servlet.xmlに登録しまする。

springapp-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<!--  - Application context definition for "springapp" DispatcherServlet.  -->
<beans>
    <bean id="helloSpringController" class="spring.sample.HelloController"/>
    <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/hello.html">helloSpringController</prop>
            </props>
        </property>
    </bean>
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass"><value>org.springframework.web.servlet.view.JstlView</value></property>
        <property name="prefix"><value>/WEB-INF/jsp/</value></property>
        <property name="suffix"><value>.jsp</value></property>
    </bean>
</beans>

使用しているViewクラスがJstlViewで、プリフィックスサフィックスが指定できる。というわけで、上記の設定。結局コントローラから物理的なファイル名から拡張子を除いたものを返さなければならないけど、上の要領で拡張したクラスを登録すればどうとでもできると言うわけですね。
これに合わせてコントローラを変更。

spring.sample.HelloController.java

package spring.sample;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

public class HelloController implements Controller {

    public ModelAndView handleRequest(HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        return new ModelAndView("helloSpring");
    }

}

サーブレット関連

HttpServletBean

HttpServletを継承したクラス。web.xmlに設定されたパラメータをBeanのプロパティとして保持する。リクエスト処理を行うロジックはサブクラスに定義する。このクラスはSpringのDI機能への依存がない。

FrameworkServlet

HttpServletBeanを継承した抽象クラス。WebApplicationContextを使用して、<サーブレット>-servlet.xmlを読み込む。別のファイル名を指定する場合は、web.xmlservlet要素のinit-paramにcontextConfigLocationとして登録する。

  <servlet>
    <servlet-name>springapp</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/config.xml</param-value>
    </init-param>
  </servlet>

リクエスト処理はサブクラスで実装したdoService()で行う。ちなみに普通のDIコンテナの定義ファイルを読み込む場合は、ContextLoaderListenerをweb.xmlに設定する。

DispatcherServlet

FrameworkServletを継承したクラス。doService()を実装した、リクエスト処理を行うクラス。

リファレンス

Chapter 12. Web MVC framework

12.1. Introduction to the web MVC framework

Spring MVCはとても素晴らしい、と言うことが書いてある。
Spring MVCの中心となるのはDispatcherServlet。コントローラにはControllerというインタフェースが用意されている。

public interface Controller {

	/**
	 * Process the request and return a ModelAndView object which the DispatcherServlet
	 * will render. A null return is not an error: It indicates that this object
	 * completed request processing itself, thus there is no ModelAndView to render.
	 * @param request current HTTP request
	 * @param response current HTTP response
	 * @return a ModelAndView to render, or null if handled directly
	 * @throws Exception in case of errors
	 */
	ModelAndView handleRequest(
                 HttpServletRequest request, 
                 HttpServletResponse response)
             throws Exception;

}

ただし、Controllerインタフェースを実装する以外に、Spring フレームワークによって既に提供されているAbstractController, AbstractCommandController and SimpleFormControllerなどを使用することも可能。
handleRequestの戻り値はModelAndViewクラス型となっているが、これは基本的にはViewの名前とモデルとなるMapで構成されている。レンダリングを行うViewクラスを自分で実装して設定することも可能。

例.必ずエラーページに遷移するView。

public class ErrorView implements View {
    public void render(Map model, HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/jsp/error.jsp");
        rd.forward(request, response);
    }
}

例.ErrorViewを返すコントローラ

public class MyController implements Controller {
    public ModelAndView handleRequest(HttpServletRequest arg0,
            HttpServletResponse arg1) throws Exception {
        if (error) {
            ErrorView ev = new ErrorView();
            return new ModelAndView(ev);
        }
    }
}

せっかくなのでbean定義に書いてみる。

<beans>
    …
    <bean id="errorView" class="ErrorView" />
    <bean id="errorModelAndView" class="org.springframework.web.servlet.ModelAndView">
        <property name="view">
            <ref bean="errorView" />
        </property>
    </bean>
    …
</beans>

bean定義からModelAndViewを読み込むコントローラ。

public class MyController implements Controller {
    public ModelAndView handleRequest(HttpServletRequest arg0,
            HttpServletResponse arg1) throws Exception {
        ApplicationContext context
            = RequestContextUtils.getWebApplicationContext(arg0);
        return (ModelAndView) context.getBean("errorModelAndView");
    }

}

こんな感じに使うのが正しいかどうかは不明!

12.1.1. Pluggability of other MVC implementations

他のWEB MVCフレームワークを使えますよ、ということが書かれている。ここで具体名が出ているのはStrutsとWebWork。

12.1.2. Features of Spring MVC

  • 各役割の明確な分割…コントローラ、バリデータ、コマンドオブジェクト、フォームオブジェクト、モデル、DispatcherServlet、ハンドラマッピング、Viewリゾルバ...
  • フレームワーク、アプリケーションクラスのJavaBeanとしてのコンフィグレーション、及びその取得の容易性
  • コントローラを拡張することでどのような画面シナリオにも対応可能。
  • 既存のクラスをそのままSpring MVCで使用することが出来る。
  • データバインディング、バリデーションがカスタマイズ可能
  • ハンドラマッピング、Viewリゾルバがカスタマイズ可能。
  • 柔軟なモデル転送。
  • ロケール対応、テーマがカスタマイズ可能。
  • タグライブラリ。

12.2. The DispatcherServlet

Spring MVCも他のMVCフレームワーク同様、サーブレットがコントローラにリクエスト処理をディスパッチするリクエストドリブンなフレームワークである。SpringのDispathcerServletはWebApplicationContextと連携し、Springの機能を利用できるようにしている。
当然だけど、DispathcerServletはweb.xmlに設定する。

web.xml

<web-app>
    ...
    <servlet>
        <servlet-name>example</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>example</servlet-name>
        <url-pattern>*.form</url-pattern>
    </servlet-mapping>
</web-app>

DispatcherServletで使用されるデフォルトのBeanFactoryはXmlBeanFactory。DispathcerServletは初期化時に[サーブレット名]-servlet.xmlというファイルをWEB-INFディレクトリ直下から取得する。
WebApplicationContextはRequestContextUtilsを使用することでWeb層のどこからでも取得が可能。

WebApplicationContextの取得

RequestContextUtils.getWebApplicationContext(ServletRequest request)

DispatcherServletにはリクエスト処理やViewのレンダリングで使用する特別なBeanがいくつかある。これらのBeanは他のBean同様、bean定義ファイルに登録することで利用可能となる。

handler mapping(s) ある条件を満たしたときに実行されるプリ/ポストプロセッサ、コントローラ。
controller(s) コントローラ。
view resolver View名をViewに変換する。
locale resolver クライアントのロケールを取得する。
theme resolver アプリケーションで扱うテーマを決定する。
multipart resolver ファイルアップロードを処理する。
handlerexception resolver 例外処理を実行する。
DispatcherServletの処理フロー。

  1. WebApplicationContextを取得し、リクエスト属性に保存する。保存時のデフォルトのキーは「DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE」
  2. ロケールゾルバがリクエスト属性に保存される。
  3. テーマリゾルバがリクエスト属性に保存される。
  4. マルチパートリゾルバが登録されており、リクエストがファイルアップロードである場合、リクエストをMultipartHttpServletRequestでラップする。
  5. 適切なリクエストハンドラを検索し、プリプロセッサ・ポストプロセッサ・コントローラのチェーンを実行する。
  6. 実行結果としてモデルが返却されたら、WebApplicationContextに登録されたViewリゾルバを使用して、Viewのレンダリングを実行する。モデルが返却されない場合は、既にViewのレンダリングが行われているものとし、レンダリングは行わない。

リクエスト処理中に発生した例外は、WebApplicationContextに登録した、handlerexceptionリゾルバによって処理される。
また、以下のパラメータをweb.xmlに設定することで、DispatcherServletをカスタマイズすることが可能。

contextClass WebApplicationContext実装クラス名。指定しない場合はXmlWebApplicationContext。
contextConfigLocation コンフィグレーションファイルの場所。カンマ区切りで複数指定可能。
namespace WebApplicationContextの名前空間。指定しない場合はサーブレット名-servlet

12.3. Controllers

コントローラはユーザ入力を受け取り、それをビューによって使用されるにモデル反映する。Springのコントローラの基本はContrllerインタフェースである。

Controllerインタフェース。

public interface Controller {

    /**
     * Process the request and return a ModelAndView object which the DispatcherServlet
     * will render.
     */
    ModelAndView handleRequest(
        HttpServletRequest request,
        HttpServletResponse response)
    throws Exception;
}

Springでは様々なController実装を用意しているとのことで、各コントローラについて。

12.3.1. AbstractController and WebContentGenerator

Springが提供しているControllerクラスは全てAbstractControllerクラスを継承している。
AbstractControllerがサポートする属性。

supportedMethods サポートするHTTPのメソッド(GETとかPOSTとか)。カンマ区切りで指定する。サポートしないメソッドのアクセスがあった場合は例外が発生する。
requiresSession セッションが必要かどうか。セッションが生成されていないリクエストが来たら例外が発生する。
synchronizeSession セッション単位で同期処理を行うかどうか。
cacheSeconds レスポンスのキャッシュ設定。-1に設定するとキャッシュしない。
useExpiresHeader HTTP1.0のExpires属性。デフォルトはtrue。
useCacheHeader HTTP1.1のCache-Control属性。デフォルトはtrue。

12.3.2. Other simple controllers

他にもシンプルなコントローラがあるよ、ってこと。

12.3.3. The MultiActionController

MultiActionControllerは一つのコントローラーに複数の操作を定義したい場合に使用する。MultiActionControllerはリクエストとメソッド名をマッピングし、適切なメソッドを呼び出す。デフォルトではリクエストされたリソース名の拡張子を除いた部分のメソッドを起動する。http://〜/hello.htmというパスの場合は、helloという名前のメソッドを実行する。

delegate MultiActionControllerの使用方法には二つのシナリオがある。一つ目はMultiActionControllerのサブクラスを作成し、サブクラスにMethodNameResolverによって決定されるメソッドを定義する場合(この場合はdelegate属性は定義不要)。もう一つはMultiActionController(及びそのサブクラス)には実行メソッドを定義せず、delegate属性に指定されたクラスのメソッドを実行する方法である。
methodNameResolver リクエスト情報から実行するメソッドを決定するクラス。指定しない場合はInternalPathMethodNameResolver。
実行されるメソッドは

ModelAndView actionName(HttpServletRequest, HttpServletResponse);

※actionNameは適切なメソッド名に変換すること。

の型でなければならない。(ソースを見ると第三引数にHttpSessionがあってもよさそう)

delegate属性はわかりにくいけど、要は、

<beans>
    <bean id="springappController" class="org.springframework.web.servlet.mvc.multiaction.MultiActionController">
        <property name="delegate">
            <ref bean="delegate" />
        </property>
    </bean>
    <bean id="delegate" class="DelegateObject"/>
</beans>

で、DelegateObjectにModelAndView actionName(HttpServletRequest, HttpServletResponse);を定義しろってことだと思う。

また、第三引数をException型にすることで例外処理を行うことが出来る。

ModelAndView anyMeaningfulName(HttpServletRequest, HttpServletResponse, ExceptionClass);

※anyMeaningfulNameは適切なメソッド名に変換すること。

MethodNameResolverはリクエスト情報から実行するメソッド名を決定する。Springでは以下の三つのMethodNameResolverを用意している。

  1. ParameterMethodNameResolver…リクエストパラメータをメソッド名とする。設定時に「paramName」で指定した値がメソッドを取得する対象のリクエストパラメータ名になる。
  2. InternalPathMethodNameResolver…ユーザがリクエストしたリソース名の拡張子を除いた部分が起動対象のメソッド名となる。
  3. PropertiesMethodNameResolver…ユーザがリクエストしたパス名とメソッド名をマッピングしたプロパティファイルを作成しておき、そこから実行対象のメソッド名を取得する。

例.PropertiesMethodNameResolver

<bean id="propsResolver" class="org....mvc.multiaction.PropertiesMethodNameResolver">
    <property name="mappings">
        <props>
            <prop key="/index/welcome.html">retrieveIndex</prop>
            <prop key="/**/notwelcome.html">retrieveIndex</prop>
            <prop key="/*/user?.html">retrieveIndex</prop>
        </props>
    </property>
</bean>

<bean id="paramMultiController" class="org....mvc.multiaction.MultiActionController">
    <property name="methodNameResolver"><ref bean="propsResolver"/></property>
    <property name="delegate"><ref bean="delegate"/></property>
</bean>
12.3.4. CommandControllers

CommandControllerはモデルオブジェクトとの連携、リクエストパラメータの動的なバインディングを提供する。

  • AbstractCommandController…CommandControllerの抽象基底クラス。リクエストパラメータのモデルへのバインドを行う。このクラスはフォーム機能は提供していないが、バリデーション機能は提供する。
  • AbstractFormController…フォームのサブミットをサポートするController。
  • SimpleFormController…AbstractFormControllerを実装したクラス。
  • AbstractWizardFormController…ウィザード形式の画面遷移を実行するコントローラ。