主要介紹了第一個Spring MVC程式的環境搭建、父子項目結構、Tomcat配置、配置文件。對DispatcherServlet的講解,2個核心類型:1.RequestMappingHandlerMapping 2.RequestMappingHandlerAdapter,視圖解析器ViewRes... ...
第二章、第一個SpringMVC程式的開發
2.1開發版本
- JDK1.8+
- Maven3.6+
- IDEA2021+
- SpringFramework 5.1.4
- Tomcat8.5.29
- MySQL5.7.18
按照父子項目的結構,管理和創建項目,創建一個空Project作為父項目,pom文件如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baizhi</groupId>
<artifactId>baizhi-mvc-parent</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>baizhi-mvc-01</module>
</modules>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>
創建子項目Module:
子項目pom文件:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>baizhi-mvc-parent</artifactId>
<groupId>com.baizhi</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>baizhi-mvc-01</artifactId>
<packaging>war</packaging>
註意:初次創建web項目時,WEB-INF包下的web.xml引入的servlet規範的版本還是2.3,而我們使用的tomcat8至少需要3.0以上的規範,所以需要修複,刪除此文件後在Project Settings設置,如圖:
Tomcat配置
2.2 環境搭建
2.2.1 引入相關jar
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.27</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.27</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.27</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.3.27</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.27</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.3.27</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.27</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.19</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.13</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.27</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.27</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.8</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>org.logback-extensions</groupId>
<artifactId>logback-ext-spring</artifactId>
<version>0.1.5</version>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.30</version>
</dependency>
</dependencies>
註意:SpringMVC比前面所學習的Spring,就多引入了一個jar包,叫做spring-webmvc.jar
2.2.2 配置文件
SpringMVC的配置文件,就是Spring的配置文件
註意事項:
- 名字可以隨便命名,本次課程取名dispatcher.xml
- 放置路徑可以根據需要,隨意放置,本次課程放置在資源文件夾的根下.
2.2.3 初始化配置
- web.xml
<!--
alt+insert快捷鍵引入Spring提供的dispatcherServlet-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<!-- 整個SpringMVC的核心-->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--指定SpringMVC配置文件的路徑-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:dispatcher.xml</param-value>
</init-param>
<!--本Servlet會在tomcat啟動時創建-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
- DispatcherServlet稱為前端控制器(中央控制器)
- DispatcherServlet的核心作用:
-
用於創建Spring的工廠(容器)
等效於:ApplicationContext ctx = new ClassPathXmlApplicationContext(”dispatcher.xml”);
因為DispatcherServlet封裝的Spring工廠只能讀取xml,所以無法遷移到純註解編程 -
控制SpringMVC內部的運行流程
-
SpringMVC的配置文件dispatcher.xml
<!--設置註解掃描的路徑-->
<context:component-scan base-package="com.baizhi"/>
<!--引入SpringMVC的核心功能-->
<mvc:annotation-driven/>
mvc:annotaion-driven這段配置的主要作用:引入SpringMVC的核心功能
主要引入了2個核心類型:1.RequestMappingHandlerMapping 2.RequestMappingHandlerAdapter
-
RequestMappingHandlerMapping實現了HandlerMapping介面
它會處理@RequestMapping註解,並將其註冊到請求映射表中
-
RequestMappingHandlerAdapter實現了 HandlerAdapter介面
它是處理請求的適配器,確定調用某個符合要求的控制器類中具體服務的方法
SpringMVC對mvc:annotaion-driven的封裝
context:component-scan
-
進行註解掃描
-
DispatcherServlet所創建的工廠需要讀取XML的配置文件,不能使用純註解的開發。所以目前使用Spring配置文件+基礎註解的形式,進行開發
基礎註解可以用:@Component @Service @Repository,@Controller,@Scope,@Transsactional等
高級註解無效:@Configuration,@Bean,@ComponentScan
2.3編程思路
2.3.1 思路分析
基本流程
- 開發一個類在上面加入@Controller註解
- 提供一個控制器方法:參數是HttpServletRequest,HttpServletResponse,返回值是String的,同時加入@RequestMapping註解定義請求路徑
- 在控制方法中,完成核心開發功能,把對應JSP頁面的路徑,作為方法的返回值返回
2.3.2 編碼
@Controller
public class FirstController {
@RequestMapping("/first")
public String first(HttpServletRequest request, HttpServletResponse response) {
System.out.println("FirstController.first");
return "/result.jsp";
}
}
必須要進行@Controller註解的掃描,配置文件中:<context:component-scan base-package="com.baizhi"/>
2.3.3 一個控制器中,提供多個服務方法
-
Servlet作為控制器,一個類中只能提供一個服務方法
在原來的Servlet開發中,明確控制器的方法必須實現介面規定的service(HttpServletRequest request, HttpServletResponse response)方法,一個類中只能實現一次,所以一個類中只能有一個服務方法
-
SpringMVC的控制器,一個類中可以提供多個對外服務的方法
- SpringMVC控制器,沒有對於方法名的限制,所以可以提供多個服務方法
http://localhost:8989/basic/first http://localhost:8989/basic/second @Controller public class FirstController { @RequestMapping("/first") public String first(HttpServletRequest request, HttpServletResponse response) { System.out.println("FirstController.first"); return "/result.jsp"; } @RequestMapping(value="/second") public String second(HttpServletRequest request, HttpServletResponse response) { System.out.println("FirstController.second"); return "/result.jsp"; } }
- SpringMVC控制器,沒有對於方法名的限制,所以可以提供多個服務方法
2.3.4 註意
SpringMVC中我們開發的Controller,也稱之為Handler(SpringMVC內部的叫法)
2.4 第一個程式的細節分析
2.4.1 一種類型的SpringMVC控制器被創建幾次?
-
回顧:Servlet控制器被創建的次數
一種類型的Servlet,只會被Tomcat創建一次,所以Servlet是單實例。
-
Servlet是單實例並不是單例設計模式
-
SpringMVC的控制器被Spring創建的次數
控制器創建的次數,是由@Scope註解決定的,可以是一次也可以是多次
-
預設情況下SpringMVC的控制器只會被創建一次,會存線上程安全的問題
2.4.2@RequestMapping註解
核心作用:為控制器方法提供外部訪問的url路徑
http://localhost:8989/basic/first
@RequestMappring(”/first”)
public String first(HttpServletRequest request, HttpServletResponse response)
-
路徑分隔符 /可以省略
@RequestMapping(value="suns/second") public String second(HttpServletRequest request, HttpServletResponse response) { System.out.println("FirstController.second"); return "/result.jsp"; } # 註意 多級目錄開頭可以不寫/
-
在一個控制器方法上映射多個路徑
@Controller public class FirstController { @RequestMapping(**value={"first","third"}**) public String first(HttpServletRequest request, HttpServletResponse response) { System.out.println("FirstController.first"); return "/result.jsp"; } }
-
Controller類上加入@RequestMapping註解
http://localhost:8989/basic/user/first http://localhost:8989/basic/user/second @Controller @RequestMapping("/user") public class FirstController { @RequestMapping("/addUser") public String addUser(HttpServletRequest request, HttpServletResponse response) { System.out.println("FirstController.addUser"); return "/result.jsp"; } @RequestMapping(value="/deleteUser") public String deleteUser(HttpServletRequest request, HttpServletResponse response) { System.out.println("FirstController.deleteUser"); return "/result.jsp"; } }
設計目的
滿足單一職能原則,可以更好的按照功能,進行不同模塊的區分,有利於項目的管理。
- @RequestMapping限定用戶的請求方式
-
請求方式
-
所謂請求方式指的就是Web開發中的 POST請求與GET請求
回顧:Web開發中的POST請求與GET請求的區別
兩種請求提交數據的區別
- GET請求:通過請求行(地址欄)提交數據(QueryString),明文數據提交,不安全,提交的數據量小(不超過2048位元組)
- POST請求:通過請求體提交數據,密文提交(不是加密,指的是一般用戶不可見),相對安全,提交數據量大(理論上沒有限制)
-
-
兩種請求發起方式的區別
-
RequestMapping如何限定用戶的請求方式
-
預設情況下:@RequestMapping註解接受所有請求方式的訪問(Post、Get、…
-
通過@RequestMapping的參數可以限定某個控制器方法只接受特定的請求方式
@RequestMapping(value = "/m1",method = {RequestMethod.POST})
-
可以同時限定多種請求方式的訪問
@RequestMapping(value = "/m1",method = {RequestMethod.POST,RequestMethod.GET})
-
當用戶發起了@RequestMapping不支持的請求操作
SrpingMVC在伺服器端拋出一個405錯誤 Method Not Allowed
-
-
Http協議中其他的請求方式【瞭解】
- 除常規的POST、GET請求外,Http協議還提供了其他的請求方式:PUT、DELETE、OPTIONS….
- @RequestMapping註解,預設情況也支持其他請求方式的訪問,同時也可以根據需要進行限定
- 除POST、GET這2種請求方式外,其他的請求方式在瀏覽器支持的不好,所以可以使用專屬工具(PostMan)或者庫進行測試
- 其他的請求方式,大多數不支持響應視圖技術(JSP,Thymeleaf),只能返回簡單字元串或者JSON數據
2.4.3 控制器方法參數
SpringMVC在控制器方法參數設計的過程中,非常靈活,可以支持多種參數的設置方式,非常強大,它也把這種設計,叫做數據綁定。可以設置無參,也可以設置多個參數
-
代碼
@RequestMapping("first") public String first(HttpServletRequest request, HttpServletResponse response) @RequestMapping("first") public String first(HttpServletRequest request) @RequestMapping("first") public String first(HttpServletResponse response) @RequestMapping("first") public String first(HttpServletRequest request, HttpServletResponse response, HttpSession session) @RequestMapping("first") public String first() 註意:HttpSession也可以單獨使用 或者 組合使用 ServletContext(application) 不能應用在控制器方法中 做形參 獲取方法:session.getServletContext(); request.getSession().getServletContext();
思考:上述五種代碼形式,在後續開發中最常用哪種?
前四種不推薦的原因:與Servlet API存在耦合
第五種不推薦的原因:無法接受client的請求參數
2.4.4 視圖解析器(頁面跳轉)
-
目前頁面跳轉存在的問題
控制器中的跳轉路徑與實際視圖路徑存在耦合
-
視圖解析器ViewResolver
通過視圖解析器可以解決跳轉路徑的耦合
視圖解析器將首碼(路徑)和尾碼(文件類型)進行封裝,跟返回的頁面Name進行拼接,因此能訪問,並解耦合
@Controller @RequestMapping("/view") public class ViewController { @RequestMapping("m1") public String m1(HttpSession session) { System.out.println("session = " + session); return "result"; } }
配置文件:
註解開發
@Configuration public class AppConfig { @Bean public InternalResourceViewResolver viewResolver() { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setPrefix("/"); viewResolver.setSuffix(".jsp"); return viewResolver; } } **註意: 1. AppConfig配置Bean應該放置到<context:component-scan/>掃描的路徑下 2.結合前面所講,目前因為DispatcherServlet封裝的Spring工廠(容器)只能讀取xml,所以無法進行純註解替換。**
2.4.5 SpringMVC配置文件的預設設置【瞭解】
作者:揚眉劍出鞘
出處: https://www.cnblogs.com/eyewink/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。