SpringMVC是Spring家族的一員,Spring是將如今開發中流行的組件進行組合而成的一個框架!它用在基於MVC的表現層開發,相似於struts2框架html
咱們在以前已經學過了Struts2這麼一個基於MVC的框架....那麼咱們已經學會了Struts2,爲啥要要學習SpringMVC呢???java
下面咱們來看一下Struts2不足之處:web
基於這麼一些緣由,而且業內如今SpringMVC已經逐漸把Struts2給替代了...所以咱們學習SpringMVC一方面可以讓咱們跟上業界的潮流框架,一方面SpringMVC確實是很是好用!spring
能夠這麼說,Struts2能作的東西,SpringMVC也可以作....express
在Struts2中,咱們的開發特色是這樣的:瀏覽器
前6個是Spring的核心功能包【IOC】,第7個是關於web的包,第8個是SpringMVC包微信
Action實現Controller接口mvc
public class HelloAction implements Controller {
@Override
public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {
return null;
}
}
複製代碼
咱們只要實現handleRequest方法便可,該方法已經說了request和response對象給咱們用了。這是咱們很是熟悉的request和response對象。然而該方法返回的是ModelAndView這麼一個對象,這是和Struts2不一樣的。Struts2返回的是字符串,而SpringMVC返回的是ModelAndViewapp
ModelAndView其實他就是將咱們的視圖路徑和數據封裝起來而已【咱們想要跳轉到哪,把什麼數據存到request域中,設置這個對象的屬性就好了】。框架
public class HelloAction implements Controller {
@Override
public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {
ModelAndView modelAndView = new ModelAndView();
//跳轉到hello.jsp頁面。
modelAndView.setViewName("/hello.jsp");
return modelAndView;
}
}
複製代碼
在Struts2中,咱們想要使用Struts2的功能,那麼就得在web.xml文件中配置過濾器。而咱們使用SpringMVC的話,咱們是在web.xml中配置核心控制器
<!-- 註冊springmvc框架核心控制器 -->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--到類目錄下尋找咱們的配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:hello.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<!--映射的路徑爲.action-->
<url-pattern>*.action</url-pattern>
</servlet-mapping>
複製代碼
咱們在hello.xml配置文件中把SpringMVC的控制器建立出來
<!-- 註冊控制器 name屬性的值表示的是請求的路徑【也就是說,當用戶請求到/helloAction時,就交由HelloAction類進行處理】 -->
<bean class="HelloAction" name="/hello.action"></bean>
複製代碼
當咱們在瀏覽器訪問http://localhost:8080/hello.action
的時候,Spring會讀取到咱們的訪問路徑,而後對比一下咱們的配置文件中是否有配置/hello.action
,若是有。那麼就交由對應的Action類來進行處理。Action類的業務方法將其請求輸出到hello.jsp頁面上。
上面的工做流程中,咱們是沒有講過映射器,適配器,視圖解析器這樣的東西的。可是SpringMVC的環境仍是被咱們搭建起來了。
下面就由我來一個一個來介紹他們是有什麼用的!
咱們在web.xml中配置規定只要是.action爲後綴的請求都是會通過SpringMVC的核心Servlet。
當咱們接收到請求的時候,咱們發現是hello.action,是會通過咱們的核心Servlet的,那麼核心Servlet就會去找有沒有專門的Action類來處理hello.action請求的。
也就是說:映射器就是用於處理「什麼樣的請求提交給Action」處理。【默承認省略的】.....
其實咱們在快速入門的例子已經配置了:name屬性就是規定了hello.action到HelloAction控制器中處理!
<!-- 註冊控制器 name屬性的值表示的是請求的路徑【也就是說,當用戶請求到/helloAction時,就交由HelloAction類進行處理】 -->
<bean class="HelloAction" name="/hello.action"></bean>
複製代碼
映射器默認的值是這樣的:
<!-- 註冊映射器(handler包)(框架)【可省略】 -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
</bean>
複製代碼
固然了,上面咱們在建立控制器的時候【也就是HelloAction】能夠不使用name屬性來指定路徑,可使用咱們的映射器來配置。如如下的代碼:
<bean class="HelloAction" id="helloAction"></bean>
<!-- 註冊映射器(handler包)(框架) -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/hello.action">helloAction</prop>
</props>
</property>
</bean>
複製代碼
當咱們須要多個請求路徑都交由helloAction控制器來處理的話,咱們只要添加prop標籤就好了!
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/hello.action">helloAction</prop>
<prop key="/bye.action">helloAction</prop>
</props>
</property>
</bean>
複製代碼
當咱們映射器找到對應的Action來處理請求的時候,核心控制器會讓適配器去找該類是否實現了Controller接口。【默承認省略的】
也就是說:適配器就是去找實現了Controller接口的類
<!-- 適配器【可省略】 -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
複製代碼
咱們把結果封裝到ModelAndView之後,SpringMVC會使用視圖解析器來對ModelAndView進行解析。【默承認省略的】
也有一種狀況是不能省略的。咱們在快速入門的例子中,將結果封裝到ModelAndView中,用的是絕對真實路徑!若是咱們用的是邏輯路徑,那麼就必須對其配置,不然SpringMVC是找不到對應的路徑的。
那什麼是邏輯路徑呢???咱們在Struts2中,返回的是"success"這樣的字符串,從而跳轉到success.jsp這樣的頁面上。咱們就能夠把"success"稱做爲邏輯路徑。
在Action中返回hello,hello是一個邏輯路徑。須要咱們使用視圖解析器把邏輯路基補全
public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {
ModelAndView modelAndView = new ModelAndView();
//跳轉到hello.jsp頁面。
modelAndView.setViewName("hello");
return modelAndView;
}
複製代碼
若是不使用視圖解析器的話,那麼就會找不到頁面:
所以,咱們須要配置視圖解析器
<!-- 若是Action中書寫的是視圖邏輯名稱,那麼視圖解析器就必須配置 若是Action中書寫的是視圖真實名稱,那麼視圖解析器就可選配置 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 路徑前綴 -->
<property name="prefix" value="/"/>
<!-- 路徑後綴 -->
<property name="suffix" value=".jsp"/>
<!-- 前綴+視圖邏輯名+後綴=真實路徑 -->
</bean>
複製代碼
咱們在以前使用Struts2的時候,若是僅僅要跳轉到某個WEB-INF/JSP頁面,也要寫業務方法。而業務方法也僅僅是返回一個簡單的字符串。
以下的代碼:
public String home(){
return "home";
}
複製代碼
<package name="nsfw-home" namespace="/nsfw" extends="struts-default">
<action name="nsfw_*" class="zhongfucheng.nsfw.HomeAction" method="{1}">
<result name="{1}">/WEB-INF/jsp/nsfw/{1}.jsp</result>
</action>
</package>
複製代碼
在SpringMVC中,若是僅僅是跳轉到某個視圖上,咱們能夠省略該Action和業務方法。配置的Action只要繼承着ParameterizableViewController這個類就好了!
<!-- 專用於jsp到jsp/html的轉發控制器 -->
<bean name="/ok.action" class="org.springframework.web.servlet.mvc.ParameterizableViewController">
<!-- 轉發到真實視圖名 -->
<property name="viewName" value="/WEB-INF/ok.jsp"/>
</bean>
複製代碼
到目前爲止,咱們都沒有將SpringMVC是怎麼接收web端傳遞過來的參數的。
咱們在Struts2中,只要在Action類上寫對應的成員變量,給出對應的set和get方法。那麼Struts2就會幫咱們把參數封裝到對應的成員變量中,是很是方便的。
那麼咱們在SpringMVC中是怎麼獲取參數的呢????咱們是將Action繼承AbstractCommandController這麼一個類的。
public class HelloAction extends AbstractCommandController {
@Override
protected ModelAndView handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, BindException e) throws Exception {
return null;
}
}
複製代碼
在講解該控制器以前,首先咱們要明白SpringMVC控制器一個與Struts2不一樣的地方:SpringMVC的控制器是單例的,Struts2的控制器是多例的!
也就是說:Struts2收集變量是定義成員變量來進行接收,而SpringMVC做爲單例的,是不可能使用成員變量來進行接收的【由於會有多個用戶訪問,就會出現數據不合理性】!
那麼SpringMVC做爲單例的,他只能經過方法的參數來進行接收對應的參數!只有方法才能保證不一樣的用戶對應不一樣的數據!
實體的屬性要和web頁面上的name提交過來的名稱是一致的。這和Struts2是同樣的!
public class User {
private String id;
private String username;
public User() {
}
public User(String id, String username) {
this.id = id;
this.username = username;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String toString() {
return "User{" +
"id='" + id + '\'' +
", username='" + username + '\'' +
'}';
}
}
複製代碼
<form action="${pageContext.request.contextPath}/hello.action" method="post">
<table align="center">
<tr>
<td>用戶名:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>編號</td>
<td><input type="text" name="id"></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="提交">
</td>
</tr>
</table>
</form>
複製代碼
<bean class="HelloAction" id="helloAction"></bean>
<!-- 註冊映射器(handler包)(框架) -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/hello.action">helloAction</prop>
</props>
</property>
</bean>
複製代碼
public class HelloAction extends AbstractCommandController {
/*設置無參構造器,裏邊調用setCommandClass方法,傳入要封裝的對象*/
public HelloAction() {
this.setCommandClass(User.class);
}
/** * * @param httpServletRequest * @param httpServletResponse * @param o 這裏的對象就表示已經封裝好的了User對象了。! * @param e * @return * @throws Exception */
@Override
protected ModelAndView handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, BindException e) throws Exception {
User user = (User) o;
System.out.println(user);
ModelAndView modelAndView = new ModelAndView();
//跳轉到ok.jsp
modelAndView.setViewName("/WEB-INF/ok.jsp");
//將數據封裝到ModelAndView中
modelAndView.addObject("USER", user);
return modelAndView;
}
}
複製代碼
Struts2和SpringMVC存值的區別:
若是文章有錯的地方歡迎指正,你們互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同窗,能夠關注微信公衆號:Java3y