什么是SpringMVC
概述
中文翻譯版:Servlet 棧的 Web 應用
Spring MVC是Spring Framework的一部分,是基于Java實現MVC的輕量級Web框架。
查看官方文檔:https://docs.spring.io/spring/docs/5.2.0.RELEASE/spring-framework-reference/web.html#spring-web
我們為什么要學習SpringMVC呢?
Spring MVC的特點:
- 輕量級,簡單易學
- 高效 , 基于請求響應的MVC框架
- 與Spring兼容性好,無縫結合
- 約定優于配置
- 功能強大:
RESTful
、數據驗證、格式化、本地化、主題等 - 簡潔靈活
Spring的web框架圍繞DispatcherServlet [ 調度Servlet ] 設計。
DispatcherServlet的作用是將請求分發到不同的處理器。從Spring 2.5開始,使用Java 5或者以上版本的用戶可以采用基于注解形式進行開發,十分簡潔;
正因為SpringMVC好 , 簡單 , 便捷 , 易學 , 天生和Spring無縫集成(使用SpringIoC
和Aop
) , 使用約定優于配置
. 能夠進行簡單的junit測試 . 支持Restful風格 .異常處理 , 本地化 , 國際化 , 數據驗證 , 類型轉換 , 攔截器 等等……所以我們要學習 .
最重要的一點還是用的人多 , 使用的公司多 .
中心控制器
Spring的web框架圍繞DispatcherServlet
設計。 DispatcherServlet的作用是將請求分發到不同的處理器。從Spring 2.5開始,使用Java 5或者以上版本的用戶可以采用基于注解的controller聲明方式。
Spring MVC框架像許多其他MVC框架一樣, 以請求為驅動 , 圍繞一個中心Servlet分派請求及提供其他功能,DispatcherServlet是一個實際的Servlet (它繼承自HttpServlet 基類)。
SpringMVC的原理如下圖所示:
當發起請求時被前置的控制器攔截到請求,根據請求參數生成代理請求,找到請求對應的實際控制器,控制器處理請求,創建數據模型,訪問數據庫,將模型響應給中心控制器,控制器使用模型與視圖渲染視圖結果,將結果返回給中心控制器,再將結果返回給請求者。
SpringMVC執行原理
圖為SpringMVC的一個較完整的流程圖,實線表示SpringMVC框架提供的技術,不需要開發者實現,虛線表示需要開發者實現。
簡要分析執行流程
- DispatcherServlet表示前置控制器,是整個SpringMVC的控制中心。用戶發出請求,DispatcherServlet接收請求并攔截請求。
我們假設請求的url為 : http://localhost:8080/SpringMVC/hello
如上url拆分成三部分:
http://localhost:8080服務器域名
SpringMVC部署在服務器上的web站點
hello表示控制器
通過分析,如上url表示為:請求位于服務器localhost:8080上的SpringMVC站點的hello控制器。
- HandlerMapping為處理器映射。DispatcherServlet調用HandlerMapping,HandlerMapping根據請求url查找Handler。
- HandlerExecution表示具體的Handler,其主要作用是根據url查找控制器,如上url被查找控制器為:hello。
- HandlerExecution將解析后的信息傳遞給DispatcherServlet,如解析控制器映射等。
- HandlerAdapter表示處理器適配器,其按照特定的規則去執行Handler。
- Handler讓具體的Controller執行。
- Controller將具體的執行信息返回給HandlerAdapter,如ModelAndView。
- HandlerAdapter將視圖邏輯名或模型傳遞給DispatcherServlet。
- DispatcherServlet調用視圖解析器(ViewResolver)來解析HandlerAdapter傳遞的邏輯視圖名。
- 視圖解析器將解析的邏輯視圖名傳給DispatcherServlet。
- DispatcherServlet根據視圖解析器解析的視圖結果,調用具體的視圖。
- 最終視圖呈現給用戶。
創建一個SpringMVC項目:HelloSpring
配置版
- 新建一個Moudle , springmvc-02-hello , 添加web的支持!
- 確定導入了SpringMVC 的依賴!
- 配置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>
- 編寫SpringMVC 的 配置文件!名稱:springmvc-servlet.xml : [servletname]-servlet.xml
ps:名字隨便寫,符合格式就行,這里的名稱要求是按照官方來的;
<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"></beans>
- 添加 處理映射器
<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>
- 編寫我們要操作業務Controller ,要么實現Controller接口,要么增加注解;需要返回一個ModelAndView,裝數據,封視圖;
package com.demo.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中。Modelmv.addObject("msg","HelloSpringMVC!");//封裝要跳轉的視圖,放在ModelAndView中mv.setViewName("hello"); //: /WEB-INF/jsp/hello.jspreturn mv;}}
- 將自己的類交給SpringIOC容器,注冊bean
<!--Handler-->
<bean id="/hello" class="com.demo.controller.HelloController"/>
- 寫要跳轉的jsp頁面,顯示ModelandView存放的數據,以及我們的正常頁面;
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>hello</title>
</head>
<body><h1>hello world</h1>
<h2>${msg}</h2></body>
</html>
- 配置Tomcat 啟動測試!
可能遇到的問題:訪問出現404,排查步驟:
- 查看控制臺輸出,看一下是不是缺少了什么jar包。
- 如果jar包存在,顯示無法輸出,就在IDEA的項目發布中,添加lib依賴!
- 重啟Tomcat 即可解決!
小結:看這個估計大部分同學都能理解其中的原理了,但是我們實際開發才不會這么寫,不然就瘋了,還學這個玩意干嘛!我們來看個注解版實現,這才是SpringMVC的精髓,到底有多么簡單,看這個圖就知道了。
有問題 參照 【JavaWeb】在復習MVC框架時,新建Servlet失敗,問題及解決方案 https://blog.csdn.net/qq_44896379/article/details/149666811
注解版
- 新建一個Moudle,springmvc-03-hello-annotation 。添加web支持!
建立包結構 com.demo.controller
- 由于Maven可能存在資源過濾的問題,我們將配置完善
<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>
- 在pom.xml文件引入相關的依賴:主要有Spring框架核心庫、Spring MVC、servlet , JSTL等。我們在父依賴中已經引入了!
<!-- 別忘了加上這個打包方式 -->
<packaging>war</packaging>
- 配置web.xml
注意點:
- 注意web.xml版本問題,要最新版!
servlet-class
注冊DispatcherServlet- 關聯SpringMVC的配置文件
param-value
- 啟動級別
load-on-startup
為1 - 映射路徑
url-pattern
為/
【不要用/*
,會404
】 :默認/
是加載除jsp
之外 所有文件
<?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><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錯。
- 添加Spring MVC配置文件
- 讓IOC的注解生效
- 靜態資源過濾 :HTML . JS . CSS . 圖片 , 視頻 ……
- MVC的注解驅動
- 配置視圖解析器
在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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvchttps://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 自動掃描包,讓指定包下的注解生效,由IOC容器統一管理 --><context:component-scan base-package="com.kuang.controller"/><!-- 讓Spring MVC不處理靜態資源 --><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/目錄下,這樣可以保證視圖安全,因為這個目錄下的文件,客戶端不能直接訪問。
- 創建Controller
編寫一個Java控制類: com.demo.controller.HelloController
, 注意編碼規范
package com.kuang.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.jspreturn "hello";}
}
- [@Controller](https://github.com/Controller)是為了讓Spring IOC容器初始化時自動掃描到;
- [@RequestMapping](https://github.com/RequestMapping)是為了映射請求路徑,這里因為類與方法上都有映射所以訪問時應該是`/HelloController/hello`;
- 方法中聲明Model類型的參數是為了把Action中的數據帶到視圖中;
- 方法返回的結果是視圖的名稱hello,加上配置文件中的前后綴變成WEB-INF/jsp/**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>
- 配置Tomcat運行
配置Tomcat , 開啟服務器 , 訪問 對應的請求路徑!
OK,運行成功!
小結
實現步驟其實非常的簡單:
- 新建一個web項目
- 導入相關
jar
包 - 編寫web.xml , 注冊
DispatcherServlet
- 編寫
springmvc
配置文件 - 接下來就是去創建對應的控制類 ,
controller
- 最后完善前端視圖和controller之間的對應
- 測試運行調試.
使用springMVC必須配置的三大件:
處理器映射器、處理器適配器、視圖解析器
通常,我們只需要手動配置視圖解析器org.springframework.web.servlet.view.InternalResourceViewResolver
,而處理器映射器和處理器適配器只需要開啟注解驅動即可,而省去了大段的xml配置