【SpringMVC 筆記】SpringMVC 原理 + 入門項目(xml 配置版 vs 註解版)

什麼是 SpringMVC?

Spring MVC 是 Spring Framework 的一部分,是基於Java 實現 MVC 的輕量級 Web 框架。

詳情查看:SpringMVC 官方文檔

中心控制器

Spring 的 web 框架圍繞 DispatcherServlet [ 調度Servlet ] 設計。

DispatcherServlet 的作用是將請求分發到不同的處理器

從 Spring 2.5 開始,使用 Java 5 或者以上版本的用戶可以採用基於註解形式進行開發,十分簡潔;

正因爲 SpringMVC 簡單、便捷、易學,天生和 Spring 無縫集成(使用 SpringIOC 和 Aop),使用 約定優於配置,能夠進行簡單的 JUnit 測試、支持 Restful 風格、異常處理、本地化、國際化、數據驗證、類型轉換、攔截器,等等… 所以我們要學習。

Spring MVC 框架像許多其他 MVC 框架一樣,以請求爲驅動,圍繞一箇中心 Servlet 分派請求及提供其他功能,DispatcherServlet 是一個實際的 Servlet (它繼承自 HttpServlet 基類)。

SpringMVC 執行原理

多看幾張原理圖,體會一下。。。
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
上圖爲 SpringMVC 的一個較完整的流程圖,實線表示 SpringMVC 框架提供的技術,不需要開發者實現,虛線表示需要開發者實現。

執行流程

DispatcherServlet 表示前置控制器,是整個 SpringMVC 的控制中心。

用戶發出請求,DispatcherServlet 接收請求並攔截請求。

我們假設請求的 URL 爲 : http://localhost:8080/sm/hello

如上 URL 拆分成三部分:

  • http://localhost:8080 表示服務器域名
  • sm 表示部署在服務器上的 web 站點
  • hello 表示控制器

通過分析,如上URL表示爲:

  1. 請求位於服務器 localhost:8080 上的 sm 站點的 hello控制器,用戶發出請求。

  2. HandlerMapping 爲處理器映射。
    DispatcherServlet 調用 HandlerMappingHandlerMapping 根據請求 url 查找 Handler。

  3. HandlerExecution 表示具體的 Handler。
    主要作用是根據 url 查找控制器,如上 url 被查找控制器爲:hello

  4. HandlerExecution 將解析後的信息傳遞給 DispatcherServlet,如解析控制器映射等。

  5. HandlerAdapter 表示處理器適配器,其按照特定的規則去執行 Handler。

  6. Handler 讓具體的 Controller 執行。

  7. Controller 將具體的執行信息返回給 HandlerAdapter,如 ModelAndView

  8. HandlerAdapter 將視圖邏輯名或模型傳遞給 DispatcherServlet。

  9. DispatcherServlet 調用視圖解析器 (ViewResolver) 解析 HandlerAdapter 傳遞的邏輯視圖名。

  10. 視圖解析器 將解析的邏輯視圖名傳給 DispatcherServlet

  11. DispatcherServlet 根據視圖解析器解析的視圖結果,調用具體的視圖。

  12. 最終視圖呈現給用戶。

xml 配置版

xml 配置版就是體驗一下,開發中不會使用,用的更多的是註解版。

1、創建一個 Web 項目

新建一個 Moudle , springmvc-hello , 添加 web 的支持。

2、pom.xml 中導入 SpringMVC 的依賴

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.6.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.2</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
</dependencies>

3、配置 web.xml,註冊 DispatcherServlet

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
        version="4.0">

   <!--1.註冊DispatcherServlet-->
   <servlet>
       <servlet-name>springmvc</servlet-name>
       <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
       <!--關聯一個springmvc的配置文件:【servlet-name】-servlet.xml-->
       <init-param>
           <param-name>contextConfigLocation</param-name>
           <param-value>classpath:springmvc-servlet.xml</param-value>
       </init-param>
       <!--啓動級別-1-->
       <load-on-startup>1</load-on-startup>
   </servlet>

   <!--/ 匹配所有的請求;(不包括.jsp)-->
   <!--/* 匹配所有的請求;(包括.jsp)-->
   <servlet-mapping>
       <servlet-name>springmvc</servlet-name>
       <url-pattern>/</url-pattern>
   </servlet-mapping>

</web-app>

4、編寫 SpringMVC 的配置文件:springmvc-servlet.xml

resources 下創建配置文件springmvc-servlet.xml,往其中添加以下配置:

  • 處理映射器(BeanNameUrlHandlerMapping)
  • 處理適配器(SimpleControllerHandlerAdapter)
  • 視圖解析器(InternalResourceViewResolver)
<?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.xsd">

    <!--添加處理映射器-->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    <!--添加處理適配器-->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

    <!--視圖解析器:DispatcherServlet 給他的 ModelAndView-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
        <!--前綴-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!--後綴-->
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--Handler-->
    <bean id="/hello" class="com.yusael.controller.HelloController"/>

</beans>

5、編寫操作業務 Controller

Controller 要麼實現 Controller 接口,要麼使用 @Controller 註解;

  • 實現 Controller 需要返回一個 ModelAndView,封裝 數據視圖
package com.yusael.controller;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

// 實現 Controller 接口
public class HelloController implements Controller {

   public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
       // ModelAndView 模型和視圖
       ModelAndView mv = new ModelAndView();

       // 封裝對象, 放在 ModelAndView 中
       mv.addObject("msg", "HelloSpringMVC!");
       // 封裝要跳轉的視圖,放在 ModelAndView 中
       mv.setViewName("hello"); // 根據視圖解析器, 自動拼接成 /WEB-INF/jsp/hello.jsp
       return mv;
  }
}

6、配置文件中註冊 bean

springmvc-servlet.xml 中將自己的類交給 SpringIOC 容器,註冊 bean:

<!--Handler-->
<bean id="/hello" class="com.yusael.controller.HelloController"/>

7、創建視圖層 hello.jsp

編寫一個要跳轉 hello.jsp 頁面,顯示 ModelandView 存放的數據,以及我們的正常頁面;

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
   <title>yusael</title>
</head>
<body>
${msg}
</body>
</html>

8、配置 Tomcat 啓動測試!

URL:http:localhost:8080/hello

可能遇到的問題:訪問出現404

在 IDEA 的項目發佈中,添加 lib 依賴!

  • 重啓 Tomcat 即可解決!

註解版

1、創建一個 Web 項目

新建一個 Moudle,springmvc-hello-annotation,添加 web 支持。

2、pom.xml 中導入 SpringMVC 的依賴

主要有 Spring 框架核心庫、Spring MVC、servlet , JSTL 等。

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.6.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.2</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
</dependencies>

資源過濾 問題

由於 Maven 可能存在 資源過濾 的問題,pom.xml 增加如下配置:

<build>
   <resources>
       <resource>
           <directory>src/main/java</directory>
           <includes>
               <include>**/*.properties</include>
               <include>**/*.xml</include>
           </includes>
           <filtering>false</filtering>
       </resource>
       <resource>
           <directory>src/main/resources</directory>
           <includes>
               <include>**/*.properties</include>
               <include>**/*.xml</include>
           </includes>
           <filtering>false</filtering>
       </resource>
   </resources>
</build>

3、配置 web.xml,註冊 DispatcherServlet

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
        version="4.0">

   <!--1.註冊servlet-->
   <servlet>
       <servlet-name>SpringMVC</servlet-name>
       <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
       <!--通過初始化參數指定SpringMVC配置文件的位置,進行關聯-->
       <init-param>
           <param-name>contextConfigLocation</param-name>
           <!-- 關聯 SpringMVC 配置文件 -->
           <param-value>classpath:springmvc-servlet.xml</param-value>
       </init-param>
       <!-- 啓動順序,數字越小,啓動越早 -->
       <load-on-startup>1</load-on-startup>
   </servlet>
   
   <!--所有請求都會被springmvc攔截 -->
   <servlet-mapping>
       <servlet-name>SpringMVC</servlet-name>
       <url-pattern>/</url-pattern>
   </servlet-mapping>

</web-app>

/ 和 /* 的區別

<url-pattern> / </url-pattern> 不會匹配到 .jsp, 只針對我們編寫的請求;即:.jsp 不會進入 spring 的 DispatcherServlet 類 。

<url-pattern> /* </url-pattern> 會匹配 *.jsp,會出現返回 jsp 視圖 時再次進入 spring 的DispatcherServlet 類,導致找不到對應的 controller 所以報 404。

4、編寫 SpringMVC 的配置文件:springmvc-servlet.xml

resource 目錄下添加 springmvc-servlet.xml 配置文件,配置的形式與 Spring 容器配置基本類似,爲了支持基於註解的 IOC,設置了 自動掃描包 的功能,具體配置信息如下:

<?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: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.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       https://www.springframework.org/schema/mvc/spring-mvc.xsd">

   <!-- 自動掃描包,讓指定包下的註解生效,由IOC容器統一管理 -->
   <context:component-scan base-package="com.kuang.controller"/>
   <!-- 讓Spring MVC不處理靜態資源: HTML、JS、CSS、圖片、視頻 .....-->
   <mvc:default-servlet-handler />
   <!--
   支持mvc註解驅動
       在 spring 中一般採用 @RequestMapping 註解來完成映射關係
       要想使 @RequestMapping 註解生效
       必須向上下文中註冊 DefaultAnnotationHandlerMapping
       和一個 AnnotationMethodHandlerAdapter 實例
       這兩個實例分別在類級別和方法級別處理。
       而 annotation-driven 配置幫助我們自動完成上述兩個實例的注入。
    -->
   <mvc:annotation-driven />

   <!-- 視圖解析器 -->
   <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
         id="internalResourceViewResolver">
       <!-- 前綴 -->
       <property name="prefix" value="/WEB-INF/jsp/" />
       <!-- 後綴 -->
       <property name="suffix" value=".jsp" />
   </bean>

</beans>

在視圖解析器中我們把所有的視圖都存放在 /WEB-INF/ 目錄下,這樣可以保證視圖安全,因爲這個目錄下的文件,客戶端不能直接訪問。

5、編寫操作業務 Controller

編寫一個 Java 控制類:com.yusael.controller.HelloController

package com.yusael.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/HelloController")
public class HelloController {

	//真實訪問地址 : 項目名/HelloController/hello
	@RequestMapping("/hello")
	public String sayHello(Model model){
		// 向模型中添加屬性 msg 與值,可以在 JSP 頁面中取出並渲染
		model.addAttribute("msg", "hello,SpringMVC");
		// web-inf/jsp/hello.jsp
		return "hello";
	}
}
  • @Controller 是爲了讓 Spring IOC 容器初始化時自動掃描到;
  • @RequestMapping 是爲了映射請求路徑,這裏因爲類與方法上都有映射所以訪問時應該是 /HelloController/hello
  • 方法中聲明 Model 類型的參數是爲了把 Action 中的數據帶到視圖中;
  • 方法返回的結果是視圖的名稱 hello,加上配置文件中的前後綴變成 WEB-INF/jsp/hello.jsp

6、創建視圖層 hello.jsp

WEB-INF/jsp 目錄中創建 hello.jsp , 視圖可以直接取出並展示從 Controller 帶回的信息;

可以通過 EL 表示取出 Model 中存放的值,或者對象;

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
   <title>SpringMVC</title>
</head>
<body>
${msg}
</body>
</html>

7、配置 Tomcat 運行

URL:http://localhost:8080/HelloController/hello

入門項目總結

實現步驟其實非常的簡單:

  1. 新建一個web項目
  2. 導入相關依賴
  3. 編寫 web.xml,註冊 DispatcherServlet
  4. 編寫 springmvc 配置文件
  5. 接下來就是去創建對應的控制類,controller
  6. 最後完善前端視圖和 controller 之間的對應
  7. 測試運行調試

使用 SpringMVC 必須配置的三大件:

  • 處理器映射器處理器適配器視圖解析器

通常,我們只需要 手動配置視圖解析器,而 處理器映射器 和 處理器適配器 只需要開啓註解驅動即可,而省去了大段的 xml 配置。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章