要將相關(guān)的方法組織在一個檔案中,只使用一個handleRequest()方法似乎是不夠的,我們希望同一個Controller中可以根據(jù)我們的指定來Action中的某個方法,而不只是使用handleRequest()方法。
作為org.springframework.web.servlet.mvc.AbstractController下的另一個子類別:org.springframework.web.servlet.mvc.multiaction.MultiActionController,它可以讓我們在一個Controller類別中定義多個方法,並根據(jù)我們的請求來呼叫當(dāng)中的某個方法來執(zhí)行。
如果您瞭解Struts,其DispatchAction就類似於Spring的MultiActionController類別,所不同的是,MultiActionController擁有比Struts的DispatchAction更多樣化的方式來參數(shù)化與組織這些Action。
要使用MultiActionController,您要配合一個MethodNameResolver的實(shí)例,MultiActionController預(yù)設(shè)是InternalPathMethodNameResolver,這是最簡單的方式,根據(jù)您所給的網(wǎng)址最後的檔案名稱來判斷要執(zhí)行Action中的哪一個方法,但通常我們不會使用InternalPathMethodNameResolver,因?yàn)檫@就失去了使用MultiActionController的一些優(yōu)點(diǎn),像是依請求參數(shù)來決定要呼叫的方法。
我們通常會使用ParameterMethodNameResolver或PropertiesMethodNameResolver,在一個網(wǎng)址上結(jié)合請求參數(shù),以參數(shù)來決定要執(zhí)行哪一個Action,這邊以ParameterMethodNameResolver為例,首先,我們可以在bean定義檔中這麼撰寫:
<?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="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/book.do">bookAction</prop> </props> </property> </bean> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass"> <value>org.springframework.web.servlet.view.InternalResourceView</value> </property> <property name="prefix"> <value>/WEB-INF/jsp/</value> </property> <property name="suffix"> <value>.jsp</value> </property> </bean> <bean id="paraMethodResolver" class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver"> <property name="paramName"><value>method</value></property> <property name="defaultMethodName"><value>list</value></property> </bean> <bean id="bookAction" class="onlyfun.caterpillar.GuestBookAction"> <property name="methodNameResolver"> <ref bean="paraMethodResolver"/> </property> <property name="testPage"> <value>test</value> </property> </bean> </beans>
在paraMethodResolver中,我們使用paramName定義在http請求中使用method參數(shù)來指定要呼叫的方法,若是請求中沒有指定method參數(shù),則會使用defaultMethodName所指定的方法,這邊指定的是list()方法。
GuestBookAction是個繼承MultiActionController的類別,當(dāng)中我們可以定義我們在method參數(shù)指定下所要呼叫的方法,例如:
package onlyfun.caterpillar; import javax.servlet.http.*; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.multiaction.MultiActionController; public class GuestBookAction extends MultiActionController { privateString testPage; public ModelAndView list(HttpServletRequest req, HttpServletResponse res) { returnnew ModelAndView(this.getTestPage(),"executed", "list"); } public ModelAndView add(HttpServletRequest req, HttpServletResponse res) { returnnew ModelAndView(this.getTestPage(),"executed", "add"); } public ModelAndView delete(HttpServletRequest req, HttpServletResponse res) { returnnew ModelAndView(this.getTestPage(),"executed", "delete"); } publicString getTestPage() { return testPage; } public void setTestPage(String testPage) { this.testPage = testPage; } }
注意到我們的方法必須包括HttpServletRequest與HttpServletResponse作為參數(shù),您也可以使用帶有第三個參數(shù)HttpSession的版本。
上面的類別只是一個簡單的範(fàn)例,用於測試MultiActionController的運(yùn)作,我們測試用的JSP網(wǎng)頁如下:
<html>
<head><title>Test</title></head>
<body>
<H1> "${executed}" method is executed.</H2>
</body>
</html>
當(dāng)您使用以下的網(wǎng)址請求資源時:
http://localhost:8080/springapp/book.do?method=add
我們的測試網(wǎng)頁將傳回以下的內(nèi)容:
<html>
<head><title>Test</title></head>
<body>
<H1> "add" method is executed.</H2>
</body>
</html>
您也可以將所有相對應(yīng)的方法專門組織在一個委託(delegate)物件中,而不是撰寫在Controller類別中,當(dāng)請求來到時,將委託給這個物件來執(zhí)行指定的方法,您只要定義MultiActionController的delegate屬性即可,例如我們的委託物件如下:
package onlyfun.caterpillar; import javax.servlet.http.*; import org.springframework.web.servlet.ModelAndView; public class BookActionDelegate { privateString testPage; public ModelAndView list(HttpServletRequest req, HttpServletResponse res) { returnnew ModelAndView(this.getTestPage(),"executed", "list"); } public ModelAndView add(HttpServletRequest req, HttpServletResponse res) { returnnew ModelAndView(this.getTestPage(),"executed", "add"); } public ModelAndView delete(HttpServletRequest req, HttpServletResponse res) { returnnew ModelAndView(this.getTestPage(),"executed", "delete"); } publicString getTestPage() { return testPage; } public void setTestPage(String testPage) { this.testPage = testPage; } }
現(xiàn)在我們不用定義GuestBookAction了,直接使用MultiActionController,只要定義Bean定義檔就好了:
<?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="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/book.do">bookAction</prop> </props> </property> </bean> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass"> <value>org.springframework.web.servlet.view.InternalResourceView</value> </property> <property name="prefix"> <value>/WEB-INF/jsp/</value> </property> <property name="suffix"> <value>.jsp</value> </property> </bean> <bean id="paraMethodResolver" class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver"> <property name="paramName"><value>method</value></property> <property name="defaultMethodName"><value>list</value></property> </bean> <bean id="bookActionDelegate" class="onlyfun.caterpillar.BookActionDelegate"> <property name="testPage"> <value>test</value> </property> </bean> <bean id="bookAction" class="org.springframework.web.servlet.mvc.multiaction.MultiActionController"> <property name="methodNameResolver"> <ref bean="paraMethodResolver"/> </property> <property name="delegate"> <ref bean="bookActionDelegate"/> </property> </bean> </beans>
測試的結(jié)果與上面是相同的。
以上說明的是ParameterMethodNameResolver,而PropertiesMethodNameResolver的設(shè)定方法是類似的,有興趣的話,可以看一下Spring參考手冊中有關(guān)MultiActionController的說明,當(dāng)中也有個簡明的設(shè)定範(fàn)例。