本文轉自:http://www.cnblogs.com/xrq730/p/5342650.html
什么是SPRing MVC
Spring MVC框架是一個MVC框架,通過實現Model-View-Controller模式來很好地將數據、業務與展現進行分離。從這樣一個角度來說,Spring MVC和Structs、Structs2非常類似。Spring MVC的設計是圍繞DispatcherServlet展開的,DispatcherServlet負責將請求派發到特定的handler。通過可配置的hander mappings、view resolution、locale以及theme resolution來處理請求并且轉到對應的視圖。Spring MVC請求處理的整體流程如圖:
Spring MVC有基于注解版與基礎.xml版的兩種用法,不過現在的企業級開發基本都使用的是注解版,沒別的原因,就是方便而已。因此后面的代碼示例,都是基于注解版本的,想了解基于.xml版本的Spring MVC的朋友可以自行上網查詢。
Spring MVC環境搭建
要開始本文后面的內容,自然要搭建一個Spring MVC的環境,那么首先建立一個java Web的工程,我建立的工程名字叫做SpringMVC,要搭建一個基礎功能的Spring MVC環境,必須引入的jar包是beans、context、core、expression、web、webmvc以及commons-logging。
然后,對web.xml添加一些內容:
<?xml version="1.0" encoding="UTF-8"?><web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name></display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <!-- 該監聽器將在Web容器啟動時激活Spring --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 處理由JavaBeans,Introspector的使用而引起的緩沖泄露,建議配置此監聽器 --> <listener> <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class> </listener> <!--configure the setting of springmvcDispatcherServlet and configure the mapping--> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping></web-app>兩個listener不是必須的,但是servlet是必須的,url-pattern用于開發者選擇哪些路徑是需要讓Spring MVC來處理的。接著在classpath下按照我們約定的名字springmvc-servlet.xml寫一個xml文件:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"> <context:annotation-config /> <context:component-scan base-package="com.xrq.controller"/> <!-- 配置視圖解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- WebRoot到一指定文件夾文件路徑 --> <property name="prefix" value="/" /> <!-- 視圖名稱后綴 --> <property name="suffix" value=".jsp" /> </bean> </beans>
另外,由于使用了Spring,所以Tomcat啟動的時候默認會去WEB-INF下找applicationContext.xml,所以放一個空的applicationContext.xml到WEB-INF下:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd"> </beans>寫一個Java POJO,用于處理具體的請求:
@Controller@RequestMapping(value = "/test")public class TestController{ @RequestMapping public String dispatchTest() { System.out.println("Enter TestController.dispatchTest"); return "test"; }}注意,這里有一個@Controller,這個注解和@Service注解意思差不多,都表示該類是一個Spring Bean,這樣就不需要再在Spring文件中為這個類定義Bean了。
另外,由于我前面在springmvc-servlet.xml中配置了prefix和suffix,因此return的時候就可以方便一些,不需要寫前綴和后綴,Spring MVC默認會轉發到(請求轉發是Spring MVC默認的頁面跳轉方式)"/test.jsp"路徑下。
最后別忘了,因為在web.xml中設置了啟動激活Spring,因此還需要寫一個applicationContext.xml(Spring文件的默認名字),當然,里面除了基本的聲明,什么實際內容都不需要。最終,WebRoot文件夾應該是這么一個結構:
最后,啟動容器,訪問"localhost:8080/SpringMVC/test",容器就會把該請求轉發到"localhost:8080/SpringMVC/test.jsp"頁面下了。
@RequestMapping注解
Spring MVC中最重要的注解應該就是@RequestMapping了,它是用于處理請求映射的。繼續看剛才的TestController:
@Controller@RequestMapping(value = "/test")public class TestController{ @RequestMapping public String dispatchTest() { System.out.println("Enter TestController.dispatchTest()"); return "test"; }}類上的RequestMapping是用于第一層匹配的。"localhost:8080/SpringMVC/test"和"localhost:8080/SpringMVC/add",value是test,自然走的是前者。
接著看,比如我在TestController中又定義了三個方法,此時類上不使用RequestMapping注解:
@RequestMapping(value = "/add")public String dispatchAddTest(){ System.out.println("Enter TestControll.dispatchAddTest()"); return "test";} @RequestMapping(value = "/add/add")public String dispatchAddAddTest(){ System.out.println("Enter TestControll.dispatchAddAddTest()"); return "test";}@RequestMapping(value = "/del")public String dispatchDelTest(){ System.out.println("Enter TestControll.dispatchDelTest()"); return "test";}那么這三個方法分別匹配的路徑是:
"localhost:8080/SpringMVC/add""localhost:8080/SpringMVC/add/add""localhost:8080/SpringMVC/del"關于路徑匹配,再提一點,假如在類上和方法上都加了RequestMapping,那么將會以類路徑為基準,再向方法路徑做匹配,比如:
@Controller@RequestMapping(value = "/test/")public class TestController{ @RequestMapping(value = "common") public String root() { System.out.println("Enter TestController.root()!"); return "result"; }}這種寫法,匹配的應當是:
"localhost:8080/SpringMVC/test/common""localhost:8080/SpringMVC/test/common/""localhost:8080/SpringMVC/test/common.html""localhost:8080/SpringMVC/test/common.jsp""localhost:8080/SpringMVC/test/common.vm"類似這種的路徑,如果還想往"localhost:8080/SpringMVC/test/common/"再添加內容,那么root()這個方法就無法匹配到了,必須再添加方法。多說一句,"/"一直是一個容易弄混的東西,我自己試驗的時候發現,RequestMapping里面的value屬性,只要路徑不存在多級的關系,加不加"/"是沒有什么影響的。
另外,@RequestMapping還可以匹配請求類型,到底是GET還是POST還是其他的,這么做:
@RequestMapping(method = RequestMethod.POST)public String dispatchTest(){ System.out.println("Enter TestController.dispatchTest()"); return "test";}這樣就指定了該方法只匹配"localhost:8080/SpringMVC/test"且請求方式為POST的請求。
前面頁面跳轉的方式都是轉發(dispatch)的方式,轉發在我看來未必是一種很好的方式,典型的就是處理表單的時候會有表單重復提交的問題,那么如何使用重定向(redirect)的方式進行頁面跳轉?可以這么寫Controller的方法,差別在于return部分:
@RequestMappingpublic String dispatchTest(Test test){ System.out.println("Enter TestController.dispatchTest(), test: " + test); return "redirect:/test.jsp";}最后,@RequestMapping中還有params、headers、consumes等幾個屬性,不過這幾個都不重要,也不常用,就不講了。
參數匹配
處理url也好、表單提交也好,參數匹配是非常重要的一個內容,萬幸,Spring MVC對參數請求的支持做得非常好----它會自動根據url或者表單中參數的名字和方法中同名形參進行匹配并賦值。
舉一個例子:
@Controller@RequestMapping(value = "/test")public class TestController{ @RequestMapping public String dispatchTest(String testId, String ttestId) { System.out.println("Enter TestController.dispatchTest(), testId = " + testId + ", ttestId = " + ttestId); return "test"; }}此時,我訪問"localhost:8080/SpringMVC/test?testId=1&ttestId=2",控制臺打印出:
Enter TestController.dispatchTest(), testId = 2, ttestId = 3不僅如此,方法中還可以放入一個實體類對象:
public class Test{ private String tid; private String nid; private String bid; public void setTid(String tid) { this.tid = tid; } public void setNid(String nid) { this.nid = nid; } public void setBid(String bid) { this.bid = bid; } public String toString() { return "tid = " + tid + ", nid = " + nid + ", bid = " + bid; }}注意,實體類對象中如果私有屬性不打算對外提供,getter可以沒有,但是為了Spring MVC可以將對應的屬性根據屬性名稱進行匹配并賦值,setter必須要有。把TestController稍作改造,傳入一個對象:
@RequestMappingpublic String dispatchTest(Test test){ System.out.println("Enter TestController.dispatchTest(), test: " + test); return "test";}此時我訪問"http://localhost:8080/SpringMVC/test?tid=0&bid=1&nid=2",控制臺上打印出:
Enter TestController.dispatchTest(), test: tid = 0, nid = 2, bid = 1看到,參數完全匹配。
不僅如此,再多試驗一點:
@RequestMappingpublic String dispatchTest(Test test1, Test test2, String tid, String nid){ System.out.println("Enter TestController.dispatchTest(), test1:" + test1 + "; test2:" + test2 + "; tid:" + tid + "; nid:" + nid); return "test";}訪問一樣地址"http://localhost:8080/SpringMVC/test?tid=0&bid=1&nid=2",結果是:
Enter TestController.dispatchTest(), test1:tid = 0, nid = 2, bid = 1; test2:tid = 0, nid = 2, bid = 1; tid:0; nid:2結論就是:
假如方法的參數是普通的字符串,只要字符串名字有和請求參數中的key完全匹配的,Spring MVC就會將完全匹配的自動賦值假如方法的參數是實體類,只要實體類中的參數有和請求參數中的key完全匹配的,Spring MVC就會將完全匹配的自動賦值對于url如此,應用到表單中也是一樣的,有興趣的可以自己試驗一下。
|
新聞熱點
疑難解答