【SSM】SSM之SpringMVC框架:SpringMVC一個請求執行過程

一個簡單的SpringMVC程序:

我們先通過創建一個簡單的動態的JavaWeb項目“springmvc01”來認識一下SpringMVC,這樣方便我們對其進行分析。

1、拷貝jar包:

對於所有框架而言,這一步都是必不可少的,我們需要在web工程的“WEB-INF”的目錄下的lib文件夾中拷貝下列jar包,由於SpringMVC是spring家族的,使用它就必不可少的要拷貝spring框架的jar包:

  • a.Spring框架的jar包:
    在這裏插入圖片描述
  • b.Spring框架的依賴包:
    在這裏插入圖片描述
  • c.SpringMVC框架的jar包:
    在這裏插入圖片描述
  • d.SpringMVC框架的依賴包:
    在這裏插入圖片描述
2、創建一個JSP視圖:

在“WEB-INF”目錄下新建一個文件夾“jsp”用於存放JSP視圖,在此目錄下的視圖非常安全,只能通過請求轉發的方式訪問。我們在此創建一個視圖“hello.jsp”,該視圖用於在瀏覽器客戶端響應給用戶。

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>Hello</title>
	</head>
	<body>
		Hello SpringMVC
	</body>
</html>
3、定義一個控制器Controller:

這一步是SpringMVC框架的集中體現,之前衆多Servlet現在都可以寫在一個類(控制器)中,大大的簡化了代碼。我們在src目錄下新建一個包“cn.jingpengchong.hello.controller”,在該包中新建一個類HelloController:

package cn.jingpengchong.hello.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class HelloController {

	@RequestMapping("hello")
	public String hello() {
		return "hello";
	}
}
  • @Controller:添加該註解後該類可以被Spring掃描器到,並且告訴Spring該類是一個控制器;
  • @RequestMapping():該註解用於使處理器映射器將其value屬性值與請求地址進行匹配,以確定應該執行的方法;
4、配置spring的xml核心配置文件:

在spring的xml核心配置文件中配置一個掃描器,用於將自定義的處理器HelloController交給Spring來管理;除此之外還需要配置一個視圖解析器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"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd">

	<!-- 配置controller包掃描 -->
	<context:component-scan base-package="cn.jingpengchong.hello"></context:component-scan>
	<!-- 配置視圖解析器:這個配置可以簡化控制器中返回的請求路徑 -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<!-- 將接受的url路徑片段字符串拼接上前綴 -->
		<property name="prefix" value="/WEB-INF/jsp/"/>
		<!-- 將接受的url路徑片段字符串拼接上後綴 -->
		<property name="suffix" value=".jsp"/>
	</bean>
</beans>
5、配置web.xml核心配置文件:

要發揮控制器的作用,在這裏需要配置核心控制器(或稱前端控制器),並且設置哪些請求路徑會被匹配到並進行處理:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>springmvc01</display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
  <!--  核心控制器的配置 -->
	<servlet>
		<servlet-name>springmvc</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<!-- DispatcherServlet繼承了父類FrameworkServlet的contextConfigLocation屬性,因此這裏可以給個初始值 -->
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:springmvc.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>springmvc</servlet-name>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>
</web-app>
6、測試:

將此項目添加進tomcat服務器並啓動tomcat服務器,打開瀏覽器,並在地址欄輸入“http://127.0.0.1/springmvc01/hello.do”後回車,結果如下:
在這裏插入圖片描述

請求的執行過程:

1、從在地址欄輸入“http://127.0.0.1/springmvc01/hello.do”並回車,發送請求;

在這裏插入圖片描述

2、首先找到web.xml文件:

用於該請求以“.do”結尾,所以被url-pattern標籤匹配到,然後根據servlet-name標籤找到核心處理器“DispatcherServlet”。
在這裏插入圖片描述

3、然後找到springmvc.xml文件:

爲核心處理器“DispatcherServlet”初始化contextConfigLocation屬性時找到springmvc.xml文件。
在這裏插入圖片描述

4、然後找到HelloController.java文件:

由於springmvc.xml文件中配置了Spring掃描器,掃描器會去“cn.jingpengchong.hello”包下逐一查找添加了特定註解的類,由於類HelloController添加了@Controller註解,所以便被掃描到,並且根據該註解斷定該類是一個處理器。
在這裏插入圖片描述
在這裏插入圖片描述

5、DispatcherServlet內部代碼流程:

我們知道一個請求被servlet捕獲後必定會調用service方法,由service方法根據請求類別再調用doGet或doPost方法,對於DispatcherServlet也是一樣。而由於DispatcherServlet沒有重寫其父類FrameworkServlet的service方法,因此請求必定會執行FrameworkServlet中的service():
在這裏插入圖片描述
由於“HttpMethod.PATCH == httpMethod || httpMethod == null”的返回值時false,所以調用了父類的service()方法,在其父類的service()方法中,發現其又執行了doGet()方法:
在這裏插入圖片描述
由於FrameworkService類中重寫了doGet()方法,所以執行到了FrameworkService類中的doGet()方法:
在這裏插入圖片描述
在該方法中又執行了processRequest()方法,在processRequest()方法中又執行了doService()方法:
在這裏插入圖片描述
我們發現doService()方法發現其是一個抽象方法,既然是一個抽象方法,那麼該類的子類必定有實現該方法的,恰巧DispatcherServlet類就是FrameworkServlet類的子類,我們點開該方法的實現,發現DispatcherServlet確實實現了該方法,那麼當執行doService()方法時必定是執行DispatcherServlet類中的doService()方法了,向下執行,發現確實執行到了DispatcherServlet類中的doService()方法,並且在該方法中執行了doDispatch()方法:
在這裏插入圖片描述
在doDispatch()方法中,發現裏面通過getHandler()方法獲得了一個處理器映射器,該映射器獲得了將要被執行的HelloController類中的hello()方法:
在這裏插入圖片描述
接着向下走,發現其又獲得了一個處理器適配器,並且將處理器映射器獲得的hello()方法交給該處理器適配器執行:
在這裏插入圖片描述
接着向下執行,到了processDispatchResult()方法:
在這裏插入圖片描述
在processDispatchResult()方法中又執行了render()方法:
在這裏插入圖片描述
在render()方法中又獲得了一個View類的實例化對象,並調用了該對象的render()方法:
在這裏插入圖片描述
接着向下執行,發現View的render()方法其實是View的子類AbstractView中實現的方法:
在這裏插入圖片描述
在該方法中又執行了renderMergedOutputModel()方法:
在這裏插入圖片描述
接着向下執行,發現renderMergedOutputModel()方法其實是AbstractView的子類InternalResourceView中的方法:
在這裏插入圖片描述
在renderMergedOutputModel()方法中獲得了一個RequestDispatcher類對象:
在這裏插入圖片描述
接着向下執行,發現在方法的最後調用了該對象的forward()方法,此時RequestDispatcher的實例化對象rd中已經有了響應的完整路徑:
在這裏插入圖片描述
我們在學習Servlet時就知道了“request.getRequestDispatcher(“路徑”).forward(request, response);”是一個請求轉發,可見在SpringMVC中,控制器處理請求後默認是用請求轉發來響應頁面給用戶的!爲了進一步驗證我們的觀點,我們不妨對HelloController類中的hello()方法做一些改造,直接讓它以請求轉發的方式響應給用戶:

@RequestMapping("hello")
public String hello() {
	return "forward:/WEB-INF/jsp/hello.jsp";
}

再次發送同樣的請求,我們發現,效果真實一樣的!
在這裏插入圖片描述
那麼用重定向的方式可以響應嗎?我們試一下:

@RequestMapping("hello")
public String hello() {
	return "redirect:/WEB-INF/jsp/hello.jsp";
}

在這裏插入圖片描述
從上面的圖中可以發現,重定向是不可以的,這也是爲什麼在WEB-INF目錄下的jsp頁面是安全的了,因爲在該目錄下的資源只能通過請求轉發的方式訪問!

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