1. 程式人生 > >SSM框架開發web項目系列(六) SpringMVC入門

SSM框架開發web項目系列(六) SpringMVC入門

商品 rwx tmx quest npv you odm pci vdp

  前言

  我們最初的javaSE部分學習後,基本算是入門了,也熟悉了Java的語法和一些常用API,然後再深入到數據庫操作、WEB程序開發,漸漸會接觸到JDBC、Servlet/Jsp之類的知識,期間可能會接觸一兩個關系型數據庫,例如MySQL/Oracle等等。像前面的MyBatis部分,主要是針對JDBC的進一步封裝,使得更適用於實際項目開發過程,但是JDBC、MyBatis或者Hibernate都是針對持久層數據庫操作,例如查詢、更新記錄等等,我們開發程序最終的展現對象是用戶,而用戶操作程序往往用的是什麽?各種各樣的瀏覽器,而不是通過我們後臺的這些測試代碼,用戶看不懂代碼,也不需要懂。用戶只需要點擊、需要輸入,比如點擊一個鏈接,跳轉到一個新頁面,頁面中的部分數據都是從數據庫中查詢獲取的;又或者是輸入一段文本,點擊提交按鈕,更新的是數據庫中的記錄。我們要理清的是,這些頁面的操作指令是怎樣傳遞到後臺服務器,然後訪問到數據庫的;還有數據庫的數據是怎麽從後臺又傳回前端,怎樣顯示到頁面上的?

  如果有學習過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的實現過程。

  Servlet篇

  新建一個普通web工程或者maven web工程,通過繼承HttpServlet,創建我們自定義的Servlet,如下所示

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如下

<%@ 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操作類型去判斷到底要執行哪種操作(運行哪段業務邏輯)。

  SpirngMVC更是將這種思想進化到了極致,我們在web,xml只定義有且只有一個Servlet,這個Servlet能匹配到所有的正常請求,然後可以根據路徑精確解析到具體的執行某個類的某個方法,這裏的類即控制層Controller,例如一個商品的相關操作,我們定義一個商品Controller類,類中定義各種操作方法,需要訪問數據庫的話,往往是通過Service層對象去調用持久層的代碼實現數據庫操作。下面就實例一段單獨通過SpringMVC來實現中間控制層效果的小案例。

  SpringMVC篇  

  為了方便管理jar包,這裏我們可以新建一個maven web項目,pom依賴可參考前面的環境搭建篇,這裏同Servlet對比,我們僅需要一個Java類也就是上面提到的controller,然後是一個指定路徑下的jsp文件,最後稍微修改一下web.xml,這三步即可簡單過一遍SpringMVC的基本運行過程。下面分別詳細寫出這三步的內容。

  DemoController.java

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,即可匹配到這個DemoControllertoPage方法中執行。

  可以看到方法的返回值是String字符串類型,這裏可以理解為用於獲取視圖頁面路徑。下面結合Spring MVC配置文件講解。

  application-mvc.xml

<?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封裝持久層,那麽我們在這裏怎麽與持久層連接起來去訪問數據庫查詢或者更新數據,還有到底什麽是業務邏輯,等等這些都是我們需要考慮的問題,後面準備分別以具體實例展開說明,歡迎一起探討。

SSM框架開發web項目系列(六) SpringMVC入門