咱們最初的javaSE部分學習後,基本算是入門了,也熟悉了Java的語法和一些經常使用API,而後再深刻到數據庫操做、WEB程序開發,漸漸會接觸到JDBC、Servlet/Jsp之類的知識,期間可能會接觸一兩個關係型數據庫,例如MySQL/Oracle等等。像前面的MyBatis部分,主要是針對JDBC的進一步封裝,使得更適用於實際項目開發過程,可是JDBC、MyBatis或者Hibernate都是針對持久層數據庫操做,例如查詢、更新記錄等等,咱們開發程序最終的展示對象是用戶,而用戶操做程序每每用的是什麼?各類各樣的瀏覽器,而不是經過咱們後臺的這些測試代碼,用戶看不懂代碼,也不須要懂。用戶只須要點擊、須要輸入,好比點擊一個連接,跳轉到一個新頁面,頁面中的部分數據都是從數據庫中查詢獲取的;又或者是輸入一段文本,點擊提交按鈕,更新的是數據庫中的記錄。咱們要理清的是,這些頁面的操做指令是怎樣傳遞到後臺服務器,而後訪問到數據庫的;還有數據庫的數據是怎麼從後臺又傳回前端,怎樣顯示到頁面上的?html
若是有學習過Servlet/Jsp相關內容,應該會對上面的問題多少有些理解。首先回顧下什麼是Servlet,Servlet是運行在咱們服務器上的Java程序,做用於中間層,即客戶端請求和服務器之間,咱們發送請求,控制數據庫、業務邏輯、作出響應,返回前端頁面數據等等均可以經過其實現。Servlet的生命週期:1.初始化調用init()方法,2.處理客戶端請求調用service()方法,3.結束程序調用destroy方法,4.最後垃圾回收。JSP本質上也是Servlet,項目啓動,Web容器將JSP的代碼編譯成JVM可以識別的java類即Servlet。Jsp重點偏向於頁面的展現,應用html、CSS、JavaScript等前端技術在這裏都不成問題,而Servlet更傾向於後臺的業務邏輯、控制轉發等等。前端
SpringMVC是在Servlet基礎上進一步封裝開發的一套WEB層框架,因此若是能深刻理清Servlet的相關內容,那麼很容易就能夠上手SpringMVC,下面咱們先簡單回顧一下以前Servlet的實現過程。java
新建一個普通web工程或者maven web工程,經過繼承HttpServlet,建立咱們自定義的Servlet,以下所示web
package com.mmm.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyServletA extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //請求轉發,至關於一次請求 req.getRequestDispatcher("/a.jsp").forward(req, resp); //響應重定向,至關於二次請求,前一次請求設置的屬性值在頁面中將沒法獲取到 //resp.sendRedirect("./a.jsp"); //這裏每每還要經過持久層對象訪問數據庫,獲取或者更新數據 //獲取到的數據經過設置屬性,而後在前端Jsp頁面能夠經過el表達式之類的方法拿到而後渲染樣式展現出來 } }
這裏的/a.jsp,表明Jsp頁面路徑,爲web文件根目錄下例如webapp下,因此咱們在webapp下簡單建立a.jsp以下spring
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>a.jsp</title> </head> <body> 這是a.jsp </body> </html>
而後在web文件夾下WEB-INF文件夾下web.xml中<web-app></web-app>節點內添加以下內容數據庫
<servlet> <servlet-name>MyServletA</servlet-name> <servlet-class>com.mmm.servlet.MyServletA</servlet-class> </servlet> <servlet-mapping> <servlet-name>MyServletA</servlet-name> <url-pattern>/a.do</url-pattern> </servlet-mapping>
這裏的<servlet-name>的值在<servlet>和<servlet-mapping>中要保持一致,<servlet-class>即爲咱們前面自定義的Servlet全名(含包名),<url-pattern>用於匹配咱們在地址欄輸入的url地址。例如這裏經過localhost:8080/servlet-web/a.do就能夠匹配到該Servlet,從而運行到該Servlet中的相關方法,這裏會請求轉發到a.jsp,以下圖所示。瀏覽器
上面爲一個最基本的從前端http請求到後臺服務器,運行Servlet後,返回前端視圖的過程。可是實際狀況下,前端的請求不會是這樣簡單拿回一個靜態無數據的頁面,也不會只有一個,舉個例子,若是上面a.do對應一個增長一條商品數據的操做,即在咱們自定義的MyServlet中doPost()方法裏執行添加操做,那麼若是還有刪改查操做,按照這裏的路子,咱們須要再定義MyServletB、MyServletC、MyServletD,而後web.xml添加3段對應的Servlet節點定義,再繼續拓展,咱們不止對商品進行增刪改查,還有員工、銷售記錄等等進行操做,這樣下去,咱們得定義和配置多少個Servlet,有的人想到辦法,例如商品的操做路徑匹配都是a.do,而後加個參數判斷,及路徑後加上?action=add或者?action=del等等,這樣同一類對象的操做咱們將其統一匹配到同一個Servlet,在Servlet的方法內部再去根據具體的action操做類型去判斷到底要執行哪一種操做(運行哪段業務邏輯)。spring-mvc
SpirngMVC更是將這種思想進化到了極致,咱們在web,xml只定義有且只有一個Servlet,這個Servlet能匹配到全部的正常請求,而後能夠根據路徑精確解析到具體的執行某個類的某個方法,這裏的類即控制層Controller,例如一個商品的相關操做,咱們定義一個商品Controller類,類中定義各類操做方法,須要訪問數據庫的話,每每是經過Service層對象去調用持久層的代碼實現數據庫操做。下面就實例一段單獨經過SpringMVC來實現中間控制層效果的小案例。服務器
爲了方便管理jar包,這裏咱們能夠新建一個maven web項目,pom依賴可參考前面的環境搭建篇,這裏同Servlet對比,咱們僅須要一個Java類也就是上面提到的controller,而後是一個指定路徑下的jsp文件,最後稍微修改一下web.xml,這三步便可簡單過一遍SpringMVC的基本運行過程。下面分別詳細寫出這三步的內容。mvc
package com.mmm.web; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("demo") public class DemoController { @RequestMapping(value="/toPage") public String toPage() { return "page"; } }
從上往下,首先@Controller註解屬於Spring系列組件bean註解之一,對應web表現層的組件,相似的還有表明業務邏輯層的@Service,表明數據庫訪問層的@Repositoty,通用組件@Component等等,實際項目中,層與層之間類對象還會相互調用,基於Spring容器的IOC及依賴注入,咱們又還會接觸到@Autowired,@Autowired等等註解。在這裏咱們能夠簡單理解爲經過@Controller註解,Spring會識別並實例化這個bean,這個類對象的建立和管理將交由Spring容器去控制。
而後@RequestMapping("demo"),看英文單詞意思應該不難理解,Request請求,Mapping映射,請求映射,經過咱們客戶端例如瀏覽器那邊過來的http請求,前面咱們用過的Servlet會經過配置url匹配到訪問路徑從而匹配到相應的Servlet中,而在這裏相似,SpringMVC會根據咱們的訪問路徑匹配到相應的Contoller中的相應方法,是的,這裏還會進一步精確匹配到方法。下面@RequestMapping(value="/toPage")即方法名的映射,例如這裏把類和方法的映射名組合起來即爲demo/toPage,在本例中,咱們經過localhost:8080/spring-mvc/demo/toPage,便可匹配到這個DemoController的toPage方法中執行。
能夠看到方法的返回值是String字符串類型,這裏能夠理解爲用於獲取視圖頁面路徑。下面結合Spring MVC配置文件講解。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd"> <!-- 自動掃描開啓 --> <context:component-scan base-package="com.mmm.web" /> <mvc:annotation-driven/> <!-- Spring MVC視圖解析配置--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> </bean> </beans>
這裏的<context:component-scan base-package="com.mmm.web" />即用於Spring掃描識別bean註解,例如剛剛講到的@Controller,而<mvc:annotation-driven/>則用於掃描SpringMVC相關特定註解,例如這裏@RequestMapping等等。
下面的視圖解析配置即結合剛剛上面講到的視圖頁面路徑,prefix和suffix分別爲前綴和後綴的意思,結合前面的controller中方法,即頁面請求轉發路徑的統一先後綴,前面controller中方法的返回值爲"page",那麼組合先後綴,即爲/WEB-INF/views/page.jsp,而這個路徑對應哪裏,以下圖所示。
因此咱們要在這裏建立一個jsp文件,views文件夾也是。
最後在web.xml中加入以下內容
<servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:/application-mvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
咱們會發現這裏也是配置的Servlet,即org.springframework.web.servlet.DispatcherServlet,只不過只配置了這單獨一個,映射路徑匹配通用請求,同時init-param設置初始參數即咱們SpringMVC配置文件路徑。這樣一來,咱們請求都會被SpringMVC系列組件接受、解析路徑、分配到相應的Controller的相應方法。
上面步驟結束後,咱們發佈項目並啓動Tomcat服務器,在瀏覽器地址欄輸入http://localhost/spring-mvc/demo/toPage,看到以下頁面,即爲成功
經過上面基礎的實例,咱們能一步步理解從Servlet到web框架SpringMVC的使用,實際開發中一樣遵循這些基本規則,只不過事更多的業務邏輯、視圖文件等等,好比這裏講到頁面跳轉中的請求轉發,那麼是否相似Servlet還有響應重定向,還有,Controller中方法咱們不必定是跳轉到頁面,也能夠直接傳遞JSON數據返回前端,以及咱們前面學習到的MyBatis封裝持久層,那麼咱們在這裏怎麼與持久層鏈接起來去訪問數據庫查詢或者更新數據,還有到底什麼是業務邏輯,等等這些都是咱們須要考慮的問題,後面準備分別以具體實例展開說明,歡迎一塊兒探討。