今日内容
- SpringMVC認識
- SpringMVC原理
- 接收請求參數
- 參數處理
- 接收請求頭
第一章 SpringMVC
1. MVC模式(了解)
MVC是一種用于設計建立 Web 應用程式表現層的模式,使用它可以将業務邏輯、資料、界面顯示代碼分離開來.
- Model(模型): 指的就是資料模型,用于封裝資料
- View(視圖): 用于資料展示
- Controller(控制器): 用于程式處理邏輯
web層職責
- 接收請求
- 調用service
- 傳回頁面
- 傳回資料
- 全局異常處理
2. SpringMVC介紹(了解)
SpringMVC是Spring産品對MVC模式的一種具體實作,它可以通過一套注解,讓一個簡單Java類成為控制器。
SpringMVC将Servlet分離為兩個部分,分别是負責請求轉發的DispatcherServlet和負責調用的JavaBean
第二章 SpringMVC入門案例(重點)
開發一個請求頁面, 向背景發送一個請求, 背景需要在控制台列印一句話, 然後跳轉到一個新的傳回頁面
1. 建立一個新工程, 導入坐标
<dependencies>
<!--springMVC-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<!--servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<!--jsp-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
2.提供一個springmvc的配置檔案
元件掃描 引入三大元件
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--元件掃描-->
<context:component-scan base-package="cn.com.mryhl.controller"></context:component-scan>
<!--三大元件-->
<!--注解驅動:相當于增強版的處理器擴充卡和處理器映射器-->
<mvc:annotation-driven />
<!--視圖解析器-->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"></bean>
</beans>
3. 在web.xml中配置前端控制器
<!--前端控制器-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<!--/ 預設配置,攔截的是除了.jsp之外的所有路徑-->
<url-pattern>/</url-pattern>
</servlet-mapping>
4. 開發請求頁面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--
User: mr_yhl
Date: 2020/9/26
Time: 9:48
--%>
<html>
<head>
<title>SpringMVC請求頁面</title>
</head>
<body>
<a href="${pageContext.request.contextPath}/demoController/demo1" target="_blank" rel="external nofollow" >demo1入門案例</a>
</body>
</html>
5. 開發一個控制器
/**
* @Controller将目前類放入SpringMVC容器中
*/
@Controller
public class DemoController {
/**
* 編寫控制器
* @RequestMapping:用于為目前方法綁定一個URL位址,作用就是為了前端請求的比對
*/
@RequestMapping("/demoController/demo1")
public String demo01(){
System.out.println("背景執行了...");
// 傳回值就是下一步要轉發的頁面
return "/WEB-INF/success.jsp";
}
}
6.開發響應頁面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--
User: mr_yhl
Date: 2020/9/26
Time: 11:58
--%>
<html>
<head>
<title>成功</title>
</head>
<body>
跳轉成功...
</body>
</html>
7. 部署測試
頁面正常跳轉到指定頁面,控制台列印出指定内容
8. 常用的注解
@RequestMapping:用于為目前方法綁定一個URL位址,作用就是為了前端請求的比對
@Controller将目前類放入SpringMVC容器中
第三章 SpringMVC原理(面試必問)
1. SpringMVC的工作流程(手畫)

- 使用者通過浏覽器發送請求至DispatcherServlet
- DispatcherServlet收到請求調用HandlerMapping
- HandlerMapping找到具體的處理器鍊傳回給DispatcherServlet
- DispatcherServlet會根據傳回的處理器鍊調用HandlerAdapter
- HandlerAdapter經過适配調用具體的Handler(controller)
- Controller執行完成傳回一個執行結果
- HandlerAdapter将Handler的結果ModelAndView對象傳回給DispatcherServlet
- DispatcherServlet将ModelAndView對象傳給ViewReslover
- ViewReslover解析後得到具體View,并傳回給DispatcherServlet
- DispatcherServlet根據View進行視圖渲染(即将模型資料填充至視圖中)
- DispatcherServlet會将渲染後的視圖響應給浏覽器
2. SpringMVC的三大元件
處理器映射器 負責根據URL尋找對應的處理器方法
處理器擴充卡 負責真正的去調用某個處理器方法
視圖解析器 負責将邏輯視圖轉換成實體視圖
SpringMVC自帶三大元件,如果不進行配置也能正常使用.配置的相當于增強版
<!--視圖解析器-->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--SpringMVC的前端控制器允許我們以配置的形式傳入字首和字尾,他會在跳轉視圖的時候自動拼接-->
<property name="prefix" value="/WEB-INF/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
3.RequestMapping(會用)
RequestMapping用于建立請求URL和處理方法之間的對應關系,也可以通過它的屬性對請求做出各種限制
- value: 用于限制請求URL(和path作用一樣)
- method:用于限制請求類型
- params:用于限制請求參數的條件
此注解可以标注在方法上,也可以标注在類上,标注在類上代表類中的所有方法都可以共用一段URL
@Controller
@RequestMapping("/demoController")
public class DemoController {
/**
* 編寫控制器
* @RequestMapping:用于為目前方法綁定一個URL位址,作用就是為了前端請求的比對
*/
@RequestMapping("/demo1")
public String demo01(){
System.out.println("背景執行了...");
// 傳回值就是下一步要轉發的頁面
return "success";
}
}
4. 限制請求路徑
4.1 頁面
<a href="${pageContext.request.contextPath}/demoController/demo2" target="_blank" rel="external nofollow" >[email protected]</a>
<a href="${pageContext.request.contextPath}/demoController/demo3" target="_blank" rel="external nofollow" >[email protected]</a>
4.2 背景
@RequestMapping(path = {"/demo2","/demo3"})
public String demo02(){
System.out.println("背景執行了...");
// 傳回值就是下一步要轉發的頁面
return "success";
}
5. 限制請求類型
method,作用就是用于限定目前方法的送出方式,支援數組寫法(同時多個)
如果不寫method,代表所有請求方式都能運作
5.1 頁面
<form action="${pageContext.request.contextPath}/demoController/demo4" method="post">
<input type="submit" value="[email protected]">
</form>
5.2 背景
/**
* 編寫控制器
* @RequestMapping:用于為目前方法綁定一個URL位址,作用就是為了前端請求的比對
* method,作用就是用于限定目前方法的送出方式,支援數組寫法(同時多個)
* 如果不寫method,代表所有請求方式都能運作
*/
@RequestMapping(value = "/demo4",method = RequestMethod.POST)
public String demo04(){
System.out.println("value = \"/demo3\",method = RequestMethod.POST");
// 傳回值就是下一步要轉發的頁面
return "success";
}
6. 限制請求參數
params用于限定請求參數的必傳,不寫代表不限制
6.1 頁面
<a href="${pageContext.request.contextPath}/demoController/demo5?username=11" target="_blank" rel="external nofollow" >[email protected]</a><br>
6.2 背景
/**
* 編寫控制器
* @RequestMapping:用于為目前方法綁定一個URL位址,作用就是為了前端請求的比對
* params用于限定請求參數的必傳,不寫代表不限制
*/
@RequestMapping(value = "/demo5",params = "username")
public String demo05(){
System.out.println("username");
// 傳回值就是下一步要轉發的頁面
return "success";
}
第四章 接收請求參數(重點)
在SpringMVC中可以使用多種類型來接收前端傳入的參數(字元串)
1. 簡單類型
隻需要保證前端傳遞的參數名稱跟方法的形參名稱一緻就好
1.1頁面
<a href="${pageContext.request.contextPath}/demoController/demo6?username=張三&age=11" target="_blank" rel="external nofollow" >demo6接收參數--簡單類型</a><br>
1.2背景
/**
* 編寫控制器,接收簡單參數
* 簡單類型參數接收:需要保證前端傳遞的參數名稱跟方法的形參名稱一緻就好
* 對于簡單類型的資料,SpringMVC底層内置了類型轉換器
*/
@RequestMapping(value = "/demo6")
public String demo06(String username,Integer age){
System.out.println("username = "+username+", age = " + age);
// 傳回值就是下一步要轉發的頁面
return "success";
}
// username = 張三, age = 11
2. 對象類型
隻需要保證前端傳遞的參數名稱跟pojo的屬性名稱(set方法)一緻就好
2.1 頁面
<a href="${pageContext.request.contextPath}/demoController/demo7?username=張三&age=11" target="_blank" rel="external nofollow" >demo7接收參數--對象類型</a><br>
2.2 封裝一個實體
public class User {
private String username;
private Integer age;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", age=" + age +
'}';
}
}
2.3 背景
/**
* 編寫控制器,接收對象類型
* 接收對象類型:需要保證前端傳遞的參數名稱跟pojo的屬性名稱(set方法)一緻就好
*/
@RequestMapping(value = "/demo7")
public String demo07(User user){
System.out.println(user);
// 傳回值就是下一步要轉發的頁面
return "success";
}
3.數組類型
隻需要保證前端傳遞的參數名稱跟方法中的數組形參名稱一緻就好
3.1 頁面
<a href="${pageContext.request.contextPath}/demoController/demo8?students=張三&students=李四" target="_blank" rel="external nofollow" >demo8接收參數--數組類型</a><br>
3.2背景
/**
* 如果前端傳入的是數組,但是背景以字元串接收, Spring會将參數以,分隔拼接成一個串傳進來[ public String demo8(String students)]
* 如果前端傳入的是數組,背景也是以數組接收, 隻需要保證前端傳遞的參數名稱跟方法中的數組形參名稱一緻就好
*/
@RequestMapping(value = "/demo8")
public String demo08(String[] students){
for (String student : students) {
System.out.println(student);
}
// 傳回值就是下一步要轉發的頁面
return "success";
}
4. 集合類型
擷取集合參數時,要将集合參數包裝到一個pojo中才可以
4.1頁面
<form action="${pageContext.request.contextPath}/demoController/demo9" method="post">
第1個User的username:<input type="text" name="users[0].username" value="張三"><br>
第1個User的age:<input type="text" name="users[0].age" value="16"><br>
第2個User的username:<input type="text" name="users[1].username" value="李四"><br>
第2個User的age:<input type="text" name="users[1].age" value="15"><br>
map的第一個元素:<input type="text" name="map['1001']" value="zs">
map的第二個元素:<input type="text" name="map['1002']" value="ls">
<input type="submit" value="接收參數--集合類型"><br>
</form>
4.2封裝一個Vo對象
public class Vo {
private List<User> users = new ArrayList<User>();
private Map<String,String> map = new HashMap<String, String>();
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
public Map<String, String> getMap() {
return map;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
@Override
public String toString() {
return "Vo{" +
"users=" + users +
", map=" + map +
'}';
}
}
4.3 背景
/**
*擷取集合參數時,要将集合參數包裝到一個pojo中才可以
*/
@RequestMapping(value = "/demo9")
public String demo09(Vo vo){
System.out.println(vo);
// 傳回值就是下一步要轉發的頁面
return "success";
}
5.日期類型(面試)
對于一些常見的類型, SpringMVC是内置了類型轉換器的, 但是對于一些格式比較靈活的參數(日期 時間), SpringMVC無法完成類型轉換
這時候就必須自定義類型轉換器
其實SpringMVC也内置日期類型的轉換器, 格式: yyyy/MM/dd
5.1 頁面
<a href="${pageContext.request.contextPath}/demoController/demo10?myDate=2020-09-26" target="_blank" rel="external nofollow" >demo10接收參數--日期類型</a><br>
5.2 自定義時間類型轉換器
1) 自定義一個類型轉換器類,實作類型轉換的方法
/**
* 自定義一個類型轉換器,實作類型轉換方法(必須實作Converter<原始類型,目标類型>接口)
*/
public class DateConverter implements Converter<String,Date> {
public Date convert(String s){
Date date = null;
try{
date= new SimpleDateFormat("yyyy-MM-dd").parse(s);
}catch (ParseException e){
e.printStackTrace();
}
return date;
}
}
2) 将轉換器的類注冊到轉換服務,并且将轉換服務注冊到Springmvc的注冊驅動中
<!--注解驅動:相當于增強版的處理器擴充卡和處理器映射器-->
<mvc:annotation-driven conversion-service="conversionService2" />
<bean id="conversionService2" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="cn.com.mryhl.converters.DateConverter"></bean>
</set>
</property>
</bean>
5.3 背景
/**
*擷取日期類型參數
*/
@RequestMapping(value = "/demo10")
public String demo10(Date myDate){
System.out.println(myDate);
// 傳回值就是下一步要轉發的頁面
return "success";
}
6. 檔案類型(檔案上傳)
6.1 加入檔案上傳的包
<!--檔案上傳-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
6.2配置檔案上傳解析器
<!--
檔案上傳解析器
注意:此處的id是固定值
-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--限制每此上傳檔案的大小,機關是B-->
<property name="maxUploadSize" value="5242880"></property>
</bean>
6.3 單檔案上傳
6.3.1 頁面
<%--
檔案上傳三要素:
1) method = "post"
2) enctype = "multipart/form-date"
3) 必須有一個type = file的input域
--%>
<form method="post" enctype="multipart/form-data" action="${pageContext.request.contextPath}/demoController/demo11">
<input type="file" name="uploadFile">
<input type="submit" value="單檔案上傳">
</form>
6.3.2背景
/**
*檔案上傳
* 參數類型必須是MultipartFile,參數名必須域前台一緻
*/
@RequestMapping(value = "/demo11")
public String demo11(MultipartFile uploadFile) throws IOException {
// 生産新的檔案名
String newFileName = UUID.randomUUID().toString() + uploadFile.getOriginalFilename();
// 定義一個本地目錄
File newFile = new File(new File("F:\\code\\spring\\day04_MVC"), newFileName);
uploadFile.transferTo(newFile);
return "success";
}
6.4 多檔案上傳
6.4.1頁面
<form method="post" enctype="multipart/form-data" action="${pageContext.request.contextPath}/demoController/demo12">
<input type="file" name="uploadFiles" multiple>
<input type="submit" value="多檔案上傳">
</form>
6.4.2 背景
/**
*檔案上傳
* 參數類型必須是MultipartFile,參數名必須域前台一緻
*/
@RequestMapping(value = "/demo12")
public String demo12(MultipartFile[] uploadFiles) throws IOException {
for (MultipartFile uploadFile : uploadFiles) {
// 生産新的檔案名
String newFileName = UUID.randomUUID().toString() + uploadFile.getOriginalFilename();
// 定義一個本地目錄
File newFile = new File(new File("F:\\code\\spring\\day04_MVC"), newFileName);
uploadFile.transferTo(newFile);
}
return "success";
}
第五章 接收參數的處理
5.1 中文亂碼
SpringMVC在使用post送出請求時, 對于中文參數是有亂碼問題的, 針對這種情況它提供了一個中文亂碼過濾器, 我們隻需要進行配置一下就可以了.
<!--中文亂碼過濾器-->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
5.2 @RequestParam
@RequestParam标注在方法參數之前,用于對傳入的參數做一些限制,支援三個屬性:
- value:預設屬性,用于指定前端傳入的參數名稱
- required:用于指定此參數是否必傳
- defaultValue:當參數為非必傳參數且前端沒有傳入參數時,指定一個預設值
5.2.1 前端
<a href="${pageContext.request.contextPath}/demoController/demo13?students=張三&students=李四" target="_blank" rel="external nofollow" >demo13接收參數[email protected]</a><br>
5.2.2背景
/**
* @RequestParam 标注在方法參數之前, 用于表示目前參數是擷取的前端傳遞過來的哪個參數的值
* @RequestParam 标注在方法參數之前, 此參數就是必傳選項,不傳就會報錯 , 但是可以使用required=false來取消這個限制
* defaultValue 可以為目前參數設定一個預設值, 目前端不再傳遞此參數的時候,就使用預設值
* @RequestParam(value = "students") 可以接收一個集合參數,直接封裝到一個集合對象中去
*/
@RequestMapping(value = "/demo13")
public String demo13(
@RequestParam(value = "page_size", required = false, defaultValue = "20") String pageSize,
@RequestParam(value = "students") List<String> students
) {
System.out.println(pageSize);
for (String student : students) {
System.out.println(student);
}
return "success";
}
第六章 接收請求頭資訊(了解)
1. 前端
<a href="${pageContext.request.contextPath}/demoController/demo14" target="_blank" rel="external nofollow" >demo14接收請求頭參數</a><br>
2. 背景
/**
* 接收請求頭
* @RequestHeader 用于接收請求頭中的所有資訊, 會封裝到一個Map結構中去
* @RequestHeader(key) 用于接收請求頭中的某一項資訊
* @CookieValue(key) 用于接收cookie中的某一項資訊
*/
@RequestMapping(value = "/demo14")
public String demo14(
@RequestHeader Map map,
@RequestHeader("cookie") String cookie,
@CookieValue("JSESSIONID") String jsessionid
) {
System.out.println(map);
System.out.println(cookie);
System.out.println(jsessionid);
return "success";
}
運作結果
{host=localhost:8080, connection=keep-alive, upgrade-insecure-requests=1, user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36, accept=text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9, sec-fetch-site=same-origin, sec-fetch-mode=navigate, sec-fetch-user=?1, sec-fetch-dest=document, referer=http://localhost:8080/, accept-encoding=gzip, deflate, br, accept-language=zh-CN,zh;q=0.9, cookie=Idea-affb8a85=347d378c-a966-4e19-a8bb-71aac3e665bb; JSESSIONID=372DA54978F9BF7DC7ED8CF9DD78F197}
Idea-affb8a85=347d378c-a966-4e19-a8bb-71aac3e665bb; JSESSIONID=372DA54978F9BF7DC7ED8CF9DD78F197
372DA54978F9BF7DC7ED8CF9DD78F197
@RequestParam
@RequestParam标注在方法參數之前,用于對傳入的參數做一些限制,支援三個屬性:
- value:預設屬性,用于指定前端傳入的參數名稱
- required:用于指定此參數是否必傳
- defaultValue:當參數為非必傳參數且前端沒有傳入參數時,指定一個預設值