SpringMVC將請(qǐng)求和響應(yīng)的數(shù)據(jù)轉(zhuǎn)換為JSON格式的幾種方式
RESTful
概述
REST:Representational State Transfer,表現(xiàn)層資源狀態(tài)轉(zhuǎn)移。
表現(xiàn)層:前端的視圖頁(yè)面和后端的控制層就是表現(xiàn)層
資源
資源是一種看待服務(wù)器的方式,即,將服務(wù)器看作是由很多離散的資源組成。每個(gè)資源是服務(wù)器上一個(gè)可命名的抽象概念。因?yàn)橘Y源是一個(gè)抽象的概念,所以它不僅僅能代表服務(wù)器文件系統(tǒng)中的一個(gè)文件、數(shù)據(jù)庫(kù)中的一張表等等具體的東西,可以將資源設(shè)計(jì)的要多抽象有多抽象,只要想象力允許而且客戶端應(yīng)用開(kāi)發(fā)者能夠理解。與面向?qū)ο笤O(shè)計(jì)類似,資源是以名詞為核心來(lái)組織的,首先關(guān)注的是名詞。一個(gè)資源可以由一個(gè)或多個(gè)URI來(lái)標(biāo)識(shí)。URI既是資源的名稱,也是資源在Web上的地址。對(duì)某個(gè)資源感興趣的客戶端應(yīng)用,可以通過(guò)資源的URI與其進(jìn)行交互。
URI :統(tǒng)一資源標(biāo)識(shí)符(Uniform Resource Identifier,URI)是一個(gè)用于標(biāo)識(shí)某一互聯(lián)網(wǎng)資源名稱的字符串。
統(tǒng)一資源定位符(Uniform Resource Locator,URL),統(tǒng)一資源名稱(Uniform Resource Name,URN)是URI的子集。
資源的表述
資源的表述是一段對(duì)于資源在某個(gè)特定時(shí)刻的狀態(tài)的描述??梢栽诳蛻舳?服務(wù)器端之間轉(zhuǎn)移(交換)。資源的表述可以有多種格式,例如 HTML/XML/JSON/純文本/圖片/視頻/音頻等等。資源的表述格式可以通過(guò)協(xié)商機(jī)制來(lái)確定。請(qǐng)求-響應(yīng)方向的表述通常使用不同的格式。
狀態(tài)轉(zhuǎn)移
狀態(tài)轉(zhuǎn)移說(shuō)的是:在客戶端和服務(wù)器端之間轉(zhuǎn)移(transfer)代表資源狀態(tài)的表述。通過(guò)轉(zhuǎn)移和操作資源的表述,來(lái)間接實(shí)現(xiàn)操作資源的目的。
RESTful的實(shí)現(xiàn)
具體說(shuō),就是 HTTP 協(xié)議里面,四個(gè)表示操作方式的動(dòng)詞:GET、POST、PUT、DELETE。
它們分別對(duì)應(yīng)四種基本操作:GET 用來(lái)獲取資源,POST 用來(lái)新建資源,PUT 用來(lái)更新資源,DELETE 用來(lái)刪除資源。
REST 風(fēng)格提倡 URL 地址使用統(tǒng)一的風(fēng)格設(shè)計(jì),從前到后各個(gè)單詞使用斜杠分開(kāi),不使用問(wèn)號(hào)鍵值對(duì)方式攜帶請(qǐng)求參數(shù),而是將要發(fā)送給服務(wù)器的數(shù)據(jù)作為 URL 地址的一部分,以保證整體風(fēng)格的一致性。
操作傳統(tǒng)方式REST風(fēng)格查詢操作
| 操作 | 傳統(tǒng)方式 | REST風(fēng)格 |
|---|---|---|
| 查詢操作 | getUserById?id=1 | user/1–>get請(qǐng)求方式 |
| 保存操作 | saveUser | user–>post請(qǐng)求方式 |
| 刪除操作 | deleteUser?id=1 | user/1–>delete請(qǐng)求方式 |
| 更新操作 | updateUser | user–>put請(qǐng)求方式 |
該案例我寫(xiě)在 demo3 中(也可創(chuàng)建一個(gè)新的項(xiàng)目),大致需要的文件如下:

創(chuàng)建 user.html 并編寫(xiě)用來(lái)測(cè)試的表單和超鏈接
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>使用RESTFul模擬操作用戶資源(增刪改查)</title>
</head>
<body>
<h1>使用RESTFul模擬操作用戶資源(增刪改查)</h1>
<a th:href="@{/user}" rel="external nofollow" >查詢所有用戶信息</a><br/>
<a th:href="@{/user/1}" rel="external nofollow" >根據(jù)用戶ID查詢用戶信息</a><br/>
<form method="post" th:action="@{/user}">
用戶名:<input type="text" name="username"><br/>
密碼:<input type="text" name="password"><br/>
<input type="submit" value="添加用戶信息">
</form>
<form method="put" th:action="@{/user}">
用戶名:<input type="text" name="username"><br/>
密碼:<input type="text" name="password"><br/>
<input type="submit" value="根據(jù)用戶ID修改用戶信息">
</form>
<form method="delete" th:action="@{/user}">
用戶ID:<input type="text" name="id"><br/>
<input type="submit" value="根據(jù)用戶ID刪除對(duì)應(yīng)用戶信息">
</form>
</body>
</html>
編寫(xiě)對(duì)應(yīng)的控制器方法
package com.laoyang.mvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
/**
* @ClassName UserController
* @Description: 使用RESTFul模擬操作用戶資源(增刪改查)
* @Author Laoyang
* @Date 2022/1/13 15:53
*/
@Controller
public class UserController {
/**
* 查詢所有用戶信息
* /user ---> GET
*/
@RequestMapping(value = "/user", method = RequestMethod.GET)
public String findAllUser() {
System.out.println("查詢所有用戶信息");
return "success";
}
/**
* 根據(jù)用戶ID查詢用戶信息
* /user/1 ---> GET
*/
@RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
public String findByUserId(@PathVariable("id") Integer id) {
System.out.println("id=" + id);
System.out.println("根據(jù)用戶ID查詢用戶信息");
return "success";
}
/**
* 添加用戶信息
* /user ---> POST
*/
@RequestMapping(value = "/user", method = RequestMethod.POST)
public String saveUser(String username, String password) {
System.out.println("username=" + username + ";password=" + password);
System.out.println("添加用戶信息");
return "success";
}
/**
* 根據(jù)用戶ID修改用戶信息
* /user ---> PUT
*/
@RequestMapping(value = "/user", method = RequestMethod.PUT)
public String updateUser(String username, String password) {
System.out.println("username=" + username + ";password=" + password);
System.out.println("根據(jù)用戶ID修改用戶信息");
return "success";
}
/**
* 根據(jù)用戶ID刪除對(duì)應(yīng)用戶信息
* /user/1 ---> DELETE
*/
@RequestMapping(value = "/user", method = RequestMethod.DELETE)
public String deleteUser(Integer id) {
System.out.println("id=" + id);
System.out.println("根據(jù)用戶ID刪除對(duì)應(yīng)用戶信息");
return "success";
}
}
在 spring-mvc.xml 文件中配置頁(yè)面跳轉(zhuǎn)
<?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">
<!-- 掃描組件 -->
<context:component-scan base-package="com.laoyang.mvc" />
<!-- 配置 Thymeleaf 視圖解析器 -->
<bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<!-- 優(yōu)先級(jí) -->
<property name="order" value="1"/>
<!-- 字符編碼 -->
<property name="characterEncoding" value="UTF-8"/>
<!-- 模板 -->
<property name="templateEngine">
<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver">
<bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<!-- 視圖前綴 -->
<property name="prefix" value="/WEB-INF/templates/"/>
<!-- 視圖后綴 -->
<property name="suffix" value=".html"/>
<!-- 模板模型 -->
<property name="templateMode" value="HTML5"/>
<!-- 頁(yè)面編碼格式 -->
<property name="characterEncoding" value="UTF-8"/>
</bean>
</property>
</bean>
</property>
</bean>
<!--
path:設(shè)置處理的請(qǐng)求地址,該路徑是和 @RequestMapping 注解中的地址是一樣的
簡(jiǎn)單理解:就是把 controller 中用來(lái)跳轉(zhuǎn)頁(yè)面的控制器方法寫(xiě)在了配置文件中
view-controller:設(shè)置請(qǐng)求地址所對(duì)應(yīng)的視圖名稱
-->
<!-- 訪問(wèn)方式:http://localhost:8080/springmvc/ -->
<mvc:view-controller path="/" view-name="index"/>
<!-- 訪問(wèn)方式:http://localhost:8080/springmvc/doView -->
<mvc:view-controller path="/doView" view-name="view" />
<!-- 訪問(wèn)方式:localhost:8080/springmvc/doUser,這一步是新增的代碼 -->
<mvc:view-controller path="/doUser" view-name="user"/>
<!-- 開(kāi)啟 mvc 的注解驅(qū)動(dòng) -->
<mvc:annotation-driven />
</beans>
啟動(dòng)Tomcat查看效果(訪問(wèn)localhost:8080/springmvc/doUser)
- 查詢所有用戶
- 根據(jù)用戶ID查詢對(duì)應(yīng)的用戶信息
- 添加用戶信息

以上三個(gè)都是可以正常訪問(wèn)的,但是瀏覽器效果都是跳轉(zhuǎn)到 success 頁(yè)面,所以大家看控制臺(tái)打印就可以看那個(gè)方法被執(zhí)行了。
- 根據(jù)用戶ID修改用戶信息
- 根據(jù)用戶ID刪除對(duì)應(yīng)用戶信息


這里截的圖是修改的效果,目前是不滿足我們的需求的,刪除效果和這個(gè)差不多,就不另做演示了
- 問(wèn)題說(shuō)明: 因?yàn)樾薷暮蛣h除的表單提交的請(qǐng)求方式是 put 和 delete,而瀏覽器基本上都只支持 get 和 post 請(qǐng)求,所以會(huì)導(dǎo)致無(wú)法通過(guò) put 或 delete 方式進(jìn)行處理,所以遇到這種情況的時(shí)候,瀏覽器默認(rèn)會(huì)以 get 請(qǐng)求方式進(jìn)行處理,所以修改和刪除所映射到的控制器方法是 GET 類型的(查詢所有用戶,可以觀察控制臺(tái)打印的語(yǔ)句)
- 解決方案: 可注冊(cè) HiddenHttpMethodFilter 過(guò)濾器處理除 get 和 post 之外的幾種請(qǐng)求方式,通過(guò)這個(gè)過(guò)濾器就可以解決剛才的問(wèn)題
這里我先簡(jiǎn)單說(shuō)明一下,如果想要在了解一些東西可以看后面的 HiddenHttpMethodFilter 解析
在 web.xml 中配置 HiddenhttpMethodFilter
<?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">
<!-- 配置HiddenHttpMethodFilter過(guò)濾器 -->
<filter>
<filter-name>hidden</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<!-- 注冊(cè)前端控制器 DispatcherServlet -->
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 初始化參數(shù) -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<!-- 初始化前端控制器,將前端控制器 DispatcherServlet 的初始化時(shí)間提前到服務(wù)器啟動(dòng)時(shí) -->
<load-on-startup>1</load-on-startup>
</servlet>
<!--
設(shè)置字符編碼格式
注意:設(shè)置編碼格式之前不可以獲取任何請(qǐng)求參數(shù),如果獲取了,就會(huì)導(dǎo)致設(shè)置的字符編碼失效!從而導(dǎo)致拿到的數(shù)據(jù)是亂碼。
> 所以字符編碼的 filter-mapping 標(biāo)簽一定要放在其它 filter-mapping 標(biāo)簽前面?。?!
-->
<filter>
<filter-name>encoding-filter</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>
<!-- 強(qiáng)制使用我們?cè)O(shè)置的編碼格式,默認(rèn)是false(不強(qiáng)制) -->
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<!-- 字符編碼的處理規(guī)則,必須在其他處理規(guī)則之前 -->
<filter-mapping>
<filter-name>encoding-filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 前端控制器請(qǐng)求處理規(guī)則 -->
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 請(qǐng)求方式的處理規(guī)則 -->
<filter-mapping>
<filter-name>hidden</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
注意: 編寫(xiě) web.xml 文件的時(shí)候一定要注意,字符編碼的處理規(guī)則一定要放在最上面!因?yàn)樵O(shè)置字符編碼之前不可以獲取到任何一個(gè)參數(shù)!如果你先讓其它的處理規(guī)則先執(zhí)行,那么這些請(qǐng)求規(guī)則就可能會(huì)帶有參數(shù),一旦帶有參數(shù),就會(huì)導(dǎo)致我們所設(shè)置的字符編碼失效(簡(jiǎn)單來(lái)說(shuō),就是即使我們?cè)O(shè)置了字符編碼,拿到的數(shù)據(jù)也還是亂碼?。郧f(wàn)要注意?。。?/p>
Ps:web.xml 文件基本上的配置就是這些,兩個(gè)過(guò)濾器,一個(gè) Servlet,只要是使用 SpringMVC,這幾個(gè)配置就不能少!
配置完之后還需要將提交方式修改為 POST,并且傳一個(gè)參數(shù) _method,這個(gè)參數(shù)的值就是我們最終的提交方式,HiddenHttpMethodFilter 會(huì)根據(jù)這個(gè)參數(shù)進(jìn)行處理
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>使用RESTFul模擬操作用戶資源(增刪改查)</title>
</head>
<body>
<h1>使用RESTFul模擬操作用戶資源(增刪改查)</h1>
<form method="post" th:action="@{/user}">
<!-- 因?yàn)檫@個(gè)參數(shù)只是給過(guò)濾器進(jìn)行處理的,所以我們使用隱藏域來(lái)傳,這樣就不會(huì)影響到用戶使用了 -->
<input type="hidden" name="_method" value="PUT">
用戶名:<input type="text" name="username"><br/>
密碼:<input type="text" name="password"><br/>
<input type="submit" value="根據(jù)用戶ID修改用戶信息">
</form>
<form method="post" th:action="@{/user}">
<input type="hidden" name="_method" value="DELETE">
用戶ID:<input type="text" name="id"><br/>
<input type="submit" value="根據(jù)用戶ID刪除對(duì)應(yīng)用戶信息">
</form>
</body>
</html>
再次測(cè)試

這個(gè)時(shí)候在看控制臺(tái),就是打印我們修改方法和刪除方法中的數(shù)據(jù)了
HiddenHttpMethodFilter 解析
為什么要使用 HiddenHttpMethodFilter
由于瀏覽器只支持發(fā)送 get 和 post 方式的請(qǐng)求,所以我們需要配置這個(gè)過(guò)濾器來(lái)讓瀏覽器能夠使用我們指定的方式進(jìn)行處理,那么該如何發(fā)送 put 和 delete 請(qǐng)求呢?
- SpringMVC 提供了 HiddenHttpMethodFilter 幫助我們將 POST 請(qǐng)求轉(zhuǎn)換為 DELETE 或 PUT 請(qǐng)求 HiddenHttpMethodFilter 處理put和delete請(qǐng)求的條件:
- 當(dāng)前請(qǐng)求的請(qǐng)求方式必須為post
- 當(dāng)前請(qǐng)求必須傳輸請(qǐng)求參數(shù)
_method,并且該參數(shù)的值必須是可兼容的(PUT、DELETE、PATCH,如有改動(dòng)可自行查看源碼)
滿足以上條件,HiddenHttpMethodFilter 過(guò)濾器就會(huì)將當(dāng)前請(qǐng)求的請(qǐng)求方式轉(zhuǎn)換為請(qǐng)求參數(shù)
_method的值,因此請(qǐng)求參數(shù)_method的值才是最終的請(qǐng)求方式
部分源碼 大家可根據(jù)我在源碼上標(biāo)注的注釋進(jìn)行理解
public class HiddenHttpMethodFilter extends OncePerRequestFilter {
/**
* request 和 response 是我們攔截的請(qǐng)求和響應(yīng)
*/
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
HttpServletRequest requestToUse = request;
/*
request.getMethod():獲取當(dāng)前所攔截的請(qǐng)求的請(qǐng)求方式
理解:如果當(dāng)前的請(qǐng)求方式為 POST,并且沒(méi)有任何錯(cuò)誤信息,則進(jìn)行相關(guān)的操作
*/
if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {
// 獲取當(dāng)前請(qǐng)求的請(qǐng)求參數(shù)(默認(rèn)為:_method)
String paramValue = request.getParameter(this.methodParam);
// 如果該值的長(zhǎng)度不為0,則進(jìn)行相關(guān)的操作
if (StringUtils.hasLength(paramValue)) {
// 將請(qǐng)求參數(shù)的值轉(zhuǎn)換為大寫(xiě)
String method = paramValue.toUpperCase(Locale.ENGLISH);
/*
如果轉(zhuǎn)換為大寫(xiě)之后的請(qǐng)求參數(shù)是ALLOWED_METHODS中的某一個(gè),那么就可以進(jìn)行使用(PUT、DELETE、PATCH)
如果不是ALLOWED_METHODS中的值,則無(wú)法實(shí)現(xiàn)我們想要的效果
> 比如我們提交方式為QWE,因?yàn)锳LLOWED_METHODS中并沒(méi)有QWE,所以就無(wú)法以QWE方式發(fā)送請(qǐng)求
*/
if (ALLOWED_METHODS.contains(method)) {
// 將當(dāng)前請(qǐng)求的請(qǐng)求方式替換成我們需要的那種(比如把POST替換成PUT,然后在以PUT方式發(fā)送請(qǐng)求)
requestToUse = new HttpMethodRequestWrapper(request, method);
}
}
}
// 給當(dāng)前請(qǐng)求放行
filterChain.doFilter(requestToUse, response);
}
}
SpringMVC 過(guò)濾器說(shuō)明
- 目前為止,SpringMVC中提供了兩個(gè)過(guò)濾器:
CharacterEncodingFilter和HiddenHttpMethodFilter - 在 web.xml 中注冊(cè)時(shí),必須先注冊(cè) CharacterEncodingFilter,再注冊(cè)HiddenHttpMethodFilter
原因:
- 在 CharacterEncodingFilter 中是通過(guò)
request.setCharacterEncoding(encoding)方法設(shè)置字符集的; request.setCharacterEncoding(encoding) 方法要求前面不能有任何獲取請(qǐng)求參數(shù)的操作 - 而 HiddenHttpMethodFilter 恰恰有一個(gè)獲取請(qǐng)求參數(shù)的操作:
String paramValue = request.getParameter(this.methodParam);
HttpMessageConverter
- 學(xué)習(xí)前可先創(chuàng)建一個(gè)新的項(xiàng)目工程,用來(lái)測(cè)試對(duì)應(yīng)的案例代碼,我這里的工程名為:
springmvc-demo4
web.xml 和 pom.xml 文件里面的內(nèi)容復(fù)制過(guò)來(lái)就行
說(shuō)明
- HttpMessageConverter:
報(bào)文信息轉(zhuǎn)換器,將請(qǐng)求報(bào)文轉(zhuǎn)換為 Java 對(duì)象,或?qū)?Java 對(duì)象轉(zhuǎn)換為響應(yīng)報(bào)文。 - HttpMessageConverter 提供了兩個(gè)注解和兩個(gè)類型:
@RequestBody,@ResponseBody,RequestEntity,ResponseEntity
@RequestBoyd
@RequestBody 可以獲取請(qǐng)求體,需要在控制器方法設(shè)置一個(gè)形參,使用 @RequestBody 進(jìn)行標(biāo)識(shí),當(dāng)前請(qǐng)求的請(qǐng)求體就會(huì)為當(dāng)前注解所標(biāo)識(shí)的形參賦值。
案例
編寫(xiě)web.xml
<?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">
<!-- 配置編碼過(guò)濾器 -->
<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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 配置 PUT 和 DELETE 請(qǐng)求方式的過(guò)濾器 -->
<filter>
<filter-name>hiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--注冊(cè)SpringMVC前端控制器-->
<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>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
編寫(xiě)spring-mvc.xml
<?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">
<!-- 開(kāi)啟組件掃描 -->
<context:component-scan base-package="com.laoyang.mvc" />
<!-- 配置 Thymeleaf 視圖解析器 -->
<bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<!-- 優(yōu)先級(jí) -->
<property name="order" value="1"/>
<!-- 字符編碼 -->
<property name="characterEncoding" value="UTF-8"/>
<!-- 模板 -->
<property name="templateEngine">
<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver">
<bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<!-- 視圖前綴 -->
<property name="prefix" value="/WEB-INF/templates/" />
<!-- 視圖后綴 -->
<property name="suffix" value=".html"/>
<!-- 模板模型 -->
<property name="templateMode" value="HTML5"/>
<!-- 頁(yè)面編碼格式 -->
<property name="characterEncoding" value="UTF-8"/>
</bean>
</property>
</bean>
</property>
</bean>
<!-- 配置視圖控制器 -->
<mvc:view-controller path="/" view-name="index" />
<!-- 開(kāi)放對(duì)靜態(tài)資源的訪問(wèn) -->
<mvc:default-servlet-handler />
<!-- 開(kāi)啟mvc注解驅(qū)動(dòng) -->
<mvc:annotation-driven />
</beans>
編寫(xiě) index.html 頁(yè)面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首頁(yè)</title>
</head>
<body>
<h1>首頁(yè)</h1>
<form method="post" th:action="@{/testRequestBody}">
用戶名:<input type="text" name="username"><br/>
密碼:<input type="text" name="password"><br/>
<input type="submit" value="測(cè)試@RequestBody注解">
</form>
</body>
</html>
編寫(xiě) success.html 頁(yè)面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>主頁(yè)面</title>
</head>
<body>
<h1>主頁(yè)面</h1>
</body>
</html>
編寫(xiě)對(duì)應(yīng)的控制器方法
package com.laoyang.mvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @ClassName HttpController
* @Description: 測(cè)試 @RequestBody 注解和 RequestEntity 類型
* @Author Laoyang
* @Date 2022/1/15 15:52
*/
@Controller
public class RequestController {
/**
* 測(cè)試 @RequestBody 注解
*/
@RequestMapping(value = "/testRequestBody")
public String testRequestBody(@RequestBody String requestBody) {
// 因?yàn)槭褂昧?@RequestBody 注解,所以這里的 requestBody 就可以獲取到頁(yè)面兩個(gè)文本框的值
System.out.println("------>" + requestBody);
return "success";
}
}
啟動(dòng)Tomcat進(jìn)行測(cè)試
- 頁(yè)面效果:成功跳轉(zhuǎn)到了 success.html 頁(yè)面
- 控制臺(tái)效果:成功獲取到了我們?cè)跒g覽器文本框中輸入的值 RequestEntity
RequestEntity
封裝請(qǐng)求報(bào)文的一種類型,需要在控制器方法的形參中設(shè)置該類型的形參,當(dāng)前請(qǐng)求的請(qǐng)求報(bào)文就會(huì)賦值給該形參,可以通過(guò) getHeaders() 獲取請(qǐng)求頭信息,通過(guò) getBody() 獲取請(qǐng)求體信息。
案例
在 index.html 中編寫(xiě)表單
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首頁(yè)</title>
</head>
<body>
<h1>首頁(yè)</h1>
<form method="post" th:action="@{/testRequestEntity}">
用戶名:<input type="text" name="username"><br/>
密碼:<input type="text" name="password"><br/>
<input type="submit" value="測(cè)試RequestEntity類型">
</form>
</body>
</html>
編寫(xiě)對(duì)應(yīng)的控制器方法
package com.laoyang.mvc.controller;
import org.springframework.http.RequestEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @ClassName HttpController
* @Description: 測(cè)試 @RequestBody 注解和 RequestEntity 類型
* @Author Laoyang
* @Date 2022/1/15 15:52
*/
@Controller
public class RequestController {
/**
* 測(cè)試 RequestEntity 類型
*/
@RequestMapping(value = "/testRequestEntity")
public String testRequestEntity(RequestEntity<String> requestEntity) {
// 請(qǐng)求頭獲取的就是瀏覽器(F12)中看到的
System.out.println("請(qǐng)求頭 --->" + requestEntity.getHeaders());
// 請(qǐng)求體獲取的就是瀏覽器發(fā)送請(qǐng)求時(shí)帶的參數(shù)
System.out.println("請(qǐng)求體 --->" + requestEntity.getBody());
return "success";
}
}
啟動(dòng)Tomcat進(jìn)行測(cè)試
- 請(qǐng)求頭獲取的就是瀏覽器(F12)中看到的,具體大家可看瀏覽器,或控制臺(tái)打印的數(shù)據(jù)

@ResponseBody
@ResponseBody 用于標(biāo)識(shí)一個(gè)控制器方法,可以將該方法的返回值直接作為響應(yīng)報(bào)文的響應(yīng)體響應(yīng)到瀏覽器。
使用ServletAPI的response對(duì)象響應(yīng)瀏覽器數(shù)據(jù)
在 index.html 中編寫(xiě)超鏈接
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首頁(yè)</title>
</head>
<body>
<h1>首頁(yè)</h1>
<a th:href="@{/testResponse}" rel="external nofollow" >通過(guò)ServletAPI的response對(duì)象響應(yīng)瀏覽器數(shù)據(jù)</a><br/>
</body>
</html>
編寫(xiě)對(duì)應(yīng)控制器方法
package com.laoyang.mvc.controller;
import com.laoyang.mvc.pojo.User;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @ClassName ResponseController
* @Description: 測(cè)試 @ResponseBody 注解和 ResponseEntity 類型
* @Author Laoyang
* @Date 2022/1/15 17:10
*/
@Controller
public class ResponseController {
/**
* 通過(guò)ServletAPI的response對(duì)象響應(yīng)瀏覽器數(shù)據(jù)
*/
@RequestMapping("/testResponse")
public void testResponse(HttpServletResponse response) {
try {
// 設(shè)置編碼格式
response.setContentType("text/html;charset=utf-8");
// 響應(yīng)給瀏覽器的數(shù)據(jù)
response.getWriter().print("Hello 原生ServletAPI的response");
} catch (IOException e) {
e.printStackTrace();
}
}
}
啟動(dòng)Tomcat查看效果

通過(guò)@ResponseBody注解響應(yīng)瀏覽器數(shù)據(jù)(響應(yīng)String類型的數(shù)據(jù))
在 index.html 中編寫(xiě)超鏈接
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首頁(yè)</title>
</head>
<body>
<h1>首頁(yè)</h1>
<a th:href="@{/testResponseBody}" rel="external nofollow" >通過(guò)@ResponseBody注解響應(yīng)瀏覽器數(shù)據(jù)(String)</a><br/>
</body>
</html>
編寫(xiě)對(duì)應(yīng)控制器方法
package com.laoyang.mvc.controller;
import com.laoyang.mvc.pojo.User;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @ClassName ResponseController
* @Description: 測(cè)試 @ResponseBody 注解和 ResponseEntity 類型
* @Author Laoyang
* @Date 2022/1/15 17:10
*/
@Controller
public class ResponseController {
/**
* 通過(guò)@ResponseBody注解響應(yīng)瀏覽器數(shù)據(jù) - String數(shù)據(jù)
*/
@RequestMapping("/testResponseBody")
@ResponseBody
public String testResponseBody() {
/*
不加 @ResponseBody 注解就表示跳轉(zhuǎn)到 success 頁(yè)面
加上 @ResponseBody 注解則表示將該返回值響應(yīng)給瀏覽器
*/
return "success";
}
}
啟動(dòng)Tomcat查看效果

使用 @ResponseBody 注解處理 json 數(shù)據(jù)
在 index.html 中編寫(xiě)超鏈接
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首頁(yè)</title>
</head>
<body>
<h1>首頁(yè)</h1
<a th:href="@{/testResponseUser}" rel="external nofollow" >通過(guò)@ResponseBody注解響應(yīng)瀏覽器數(shù)據(jù)(User)</a><br/>
</body>
</html>
編寫(xiě)一個(gè)實(shí)體類用來(lái)配合測(cè)試
package com.laoyang.mvc.pojo;
public class User {
private Integer id;
private String username;
private String password;
private Integer age;
private String sex;
// 創(chuàng)建對(duì)應(yīng)的get/set 方法、有參構(gòu)造器、全參構(gòu)造器
}
編寫(xiě)對(duì)應(yīng)控制器方法
package com.laoyang.mvc.controller;
import com.laoyang.mvc.pojo.User;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @ClassName ResponseController
* @Description: 測(cè)試 @ResponseBody 注解和 ResponseEntity 類型
* @Author Laoyang
* @Date 2022/1/15 17:10
*/
@Controller
public class ResponseController {
/**
* 通過(guò)@ResponseBody注解響應(yīng)瀏覽器數(shù)據(jù) - User對(duì)象數(shù)據(jù)
*/
@RequestMapping("/testResponseUser")
@ResponseBody
public User testResponseUser() {
return new User(1001, "admin", "12345", 18, "男");
}
}
啟動(dòng)Tomcat查看效果

報(bào)錯(cuò)原因:瀏覽器只能處理字符串類型的數(shù)據(jù)
解決方案:引入 json 相關(guān)依賴,并進(jìn)行相關(guān)配置
解決方案的實(shí)現(xiàn)步驟
導(dǎo)入jackson 的依賴
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.5</version>
</dependency>
在 SpringMVC 的核心配置文件(spring-mvc.xml)中開(kāi)啟 mvc 的注解驅(qū)動(dòng),此時(shí)在HandlerAdaptor 中會(huì)自動(dòng)裝配一個(gè)消息轉(zhuǎn)換器:MappingJackson2HttpMessageConverter,可以將響應(yīng)到瀏覽器的 Java 對(duì)象轉(zhuǎn)換為 Json 格式的字符串
<mvc:annotation-driven />
在最開(kāi)始的時(shí)候我們已經(jīng)配好了,這里就可以不配了;如果沒(méi)有配置,那么一定要加上
在處理器方法上使用 @ResponseBody 注解進(jìn)行標(biāo)識(shí)
package com.laoyang.mvc.controller;
import com.laoyang.mvc.pojo.User;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @ClassName ResponseController
* @Description: 測(cè)試 @ResponseBody 注解和 ResponseEntity 類型
* @Author Laoyang
* @Date 2022/1/15 17:10
*/
@Controller
public class ResponseController {
/**
* 通過(guò)@ResponseBody注解響應(yīng)瀏覽器數(shù)據(jù) - User對(duì)象數(shù)據(jù)
*/
@RequestMapping("/testResponseUser")
@ResponseBody
public User testResponseUser() {
return null;
}
}
將 Java 對(duì)象直接作為控制器方法的返回值進(jìn)行返回,就會(huì)自動(dòng)轉(zhuǎn)換為 Json 格式的字符串
package com.laoyang.mvc.controller;
import com.laoyang.mvc.pojo.User;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @ClassName ResponseController
* @Description: 測(cè)試 @ResponseBody 注解和 ResponseEntity 類型
* @Author Laoyang
* @Date 2022/1/15 17:10
*/
@Controller
public class ResponseController {
/**
* 通過(guò)@ResponseBody注解響應(yīng)瀏覽器數(shù)據(jù) - User對(duì)象數(shù)據(jù)
*/
@RequestMapping("/testResponseUser")
@ResponseBody
public User testResponseUser() {
return new User(1001, "admin", "12345", 18, "男");
}
}
啟動(dòng)Tomcat查看效果

使用 @ResponseBody 注解處理 ajax 請(qǐng)求
在 index.html 中編寫(xiě)超鏈接
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首頁(yè)</title>
</head>
<body>
<h1>首頁(yè)</h1>
<div id="app">
<a th:href="@{testAxios}" rel="external nofollow" @click="testAxios">SpringMVC處理ajax</a>
</div>
</body>
</html>
通過(guò)vue和axios處理點(diǎn)擊事件
需要先導(dǎo)入 vue.js 和 axios.min.js

然后使用代碼進(jìn)行引用
<script type="text/javascript" th:src="@{/static/js/vue.js}"></script>
<script type="text/javascript" th:src="@{/static/js/axios.min.js}"></script>
<script type="text/javascript">
var vue = new Vue({
el:"#app",
methods:{
testAxios:function (event) {
axios({
method:"post",
url:event.target.href,
params:{
username:"admin",
password:"123456"
}
}).then(function (response) {
alert(response.data);
});
event.preventDefault();
}
}
});
</script>
編寫(xiě)對(duì)應(yīng)控制器方法
package com.laoyang.mvc.controller;
import com.laoyang.mvc.pojo.User;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @ClassName ResponseController
* @Description: 測(cè)試 @ResponseBody 注解和 ResponseEntity 類型
* @Author Laoyang
* @Date 2022/1/15 17:10
*/
@Controller
public class ResponseController {
/**
* 使用 @ResponseBody 注解處理 ajax 請(qǐng)求
*/
@RequestMapping("/testAxios")
@ResponseBody
public String testAxios(String username, String password) {
System.out.println(username + "--->" + password);
return "Hello Axios";
}
}
啟動(dòng)Tomcat查看效果

點(diǎn)擊鏈接后就可以獲取到控制器方法響應(yīng)到瀏覽器的數(shù)據(jù)了,控制臺(tái)中也可以看到 username 和 password 的數(shù)據(jù)了。
@RestController 注解
@RestController 注解是 SpringMVC 提供的一個(gè)復(fù)合注解,標(biāo)識(shí)在控制器的類上,就相當(dāng)于為類添加了 @Controller 注解,并且為其中的每個(gè)方法添加了 @ResponseBody 注解。
@RestController
public class ResponseController {
}
效果就相當(dāng)于:
@Controller
public class ResponseController {
@ResponseBody
public String testAxios(String username, String password) {
System.out.println(username + "--->" + password);
return "Hello";
}
}
簡(jiǎn)單理解:@RestController 就相當(dāng)于是 @Controller 和 @ResponseBody 的效果的結(jié)合
> 使用這一個(gè)注解,就可以實(shí)現(xiàn)這兩個(gè)注解的效果
Ps:因?yàn)樽饔檬且粯拥?,所以這里就不演示了
ResponseEntity
- ResponseEntity 用于控制器方法的返回值類型,該控制器方法的返回值就是響應(yīng)到瀏覽器的響應(yīng)報(bào)文。
- 通過(guò) ResponseEntity 可以實(shí)現(xiàn)文件的上傳和下載
文件下載
在 static 目錄下創(chuàng)建 img 文件夾,然后導(dǎo)入一些文件

創(chuàng)建 file.html,編寫(xiě)超鏈接
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>文件上傳與下載</title>
</head>
<body>
<h1>文件上傳與下載</h1>
<a th:href="@{/download}" rel="external nofollow" >下載文件</a><br/>
</body>
</html>
編寫(xiě)對(duì)應(yīng)控制器方法
package com.laoyang.mvc.controller;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import java.io.FileInputStream;
import java.io.InputStream;
/**
* @ClassName FileAndDownController
* @Description: 文件上傳和下載
* @Author Laoyang
* @Date 2022/1/16 16:36
*/
@Controller
public class FileAndDownController {
/**
* 文件下載
*/
@RequestMapping("/download")
public ResponseEntity<byte[]> download(HttpSession session) throws Exception {
//獲取ServletContext對(duì)象
ServletContext servletContext = session.getServletContext();
//獲取服務(wù)器中文件的真實(shí)路徑
String realPath = servletContext.getRealPath("/static/img/21.jpg");
//創(chuàng)建輸入流
InputStream is = new FileInputStream(realPath);
//創(chuàng)建字節(jié)數(shù)組(is.available():獲取當(dāng)前文件的字節(jié)數(shù))
byte[] bytes = new byte[is.available()];
//將流讀到字節(jié)數(shù)組中
is.read(bytes);
//創(chuàng)建HttpHeaders對(duì)象設(shè)置響應(yīng)頭信息
MultiValueMap<String, String> headers = new HttpHeaders();
//設(shè)置要下載方式以及下載文件的名字
headers.add("Content-Disposition", "attachment;filename=Digimon.jpg");
//設(shè)置響應(yīng)狀態(tài)碼
HttpStatus statusCode = HttpStatus.OK;
//創(chuàng)建ResponseEntity對(duì)象(參數(shù)分別是:請(qǐng)求體、請(qǐng)求頭、響應(yīng)狀態(tài)碼)
ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers, statusCode);
//關(guān)閉輸入流
is.close();
return responseEntity;
}
}
啟動(dòng)Tomcat查看效果

點(diǎn)擊瀏覽器頁(yè)面中的超鏈接,即可下載我們配置好的文件
文件上傳
文件上傳要求 form 表單的請(qǐng)求方式必須為 post,并且添加屬性 enctype="multipart/form-data"
SpringMVC 中將上傳的文件封裝到 MultipartFile 對(duì)象中,通過(guò)此對(duì)象可以獲取文件相關(guān)信息。
導(dǎo)入相關(guān)依賴
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
在 file.html 中編寫(xiě)表單進(jìn)行文件上傳
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>文件上傳與下載</title>
</head>
<body>
<h1>文件上傳與下載</h1>
<form th:action="@{/upload}" method="post" enctype="multipart/form-data">
<input type="file" name="photo">
<input type="submit" value="上傳文件">
</form>
</body>
</html>
在spring-mvc.xml 文件中配置文件上傳解析器
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
編寫(xiě)對(duì)應(yīng)的控制器方法
package com.laoyang.mvc.controller;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* @ClassName FileAndDownController
* @Description: 文件上傳和下載
* @Author Laoyang
* @Date 2022/1/16 16:36
*/
@Controller
public class FileAndDownController {
/**
* 文件上傳
*/
@RequestMapping("/upload")
public String upload(MultipartFile photo, HttpSession session) throws IOException {
// 獲取上傳的文件名
String fileName = photo.getOriginalFilename();
System.out.println(fileName);
// 獲取當(dāng)前工程的上下文路徑
ServletContext servletContext = session.getServletContext();
// 給定一個(gè) URI,返回文件系統(tǒng)中 URI對(duì)應(yīng)的絕對(duì)路徑
String photoPath = servletContext.getRealPath("photo");
File file = new File(photoPath);
// 判斷 photoPath 所對(duì)應(yīng)的路徑是否存在
if (!file.exists()) {
// 如果不存在,則創(chuàng)建對(duì)應(yīng)目錄
file.mkdirs();
}
// 最終的上傳地址
String finalPath = photoPath + File.separator + fileName;
// 將文件上傳到指定的地址下
photo.transferTo(new File(finalPath));
return "success";
}
}
這里上傳的最終目錄設(shè)置在
springmvc-demo4\target\springmvc-demo4-1.0-SNAPSHOT目錄下
啟動(dòng)Tomcat查看效果

上傳成功后可在自己項(xiàng)目的
target\springmvc-demo4-1.0-SNAPSHOT目錄下查看效果

文件上傳的重名問(wèn)題
- 如果指定的目錄中有一個(gè)和我們即將要上傳的文件名稱一樣的文件,那么就會(huì)導(dǎo)致新上傳的文件覆蓋原來(lái)的文件,從而導(dǎo)致一些不必要的問(wèn)題(詳細(xì)可了解 IO 流)。 使用 UUID 解決文件重名問(wèn)題
package com.laoyang.mvc.controller;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
/**
* @ClassName FileAndDownController
* @Description: 文件上傳和下載
* @Author Laoyang
* @Date 2022/1/16 16:36
*/
@Controller
public class FileAndDownController {
/**
* 文件上傳
*/
@RequestMapping("/upload")
public String upload(MultipartFile photo, HttpSession session) throws IOException {
// 獲取上傳的文件名
String fileName = photo.getOriginalFilename();
// 截取文件后綴名(lastIndexOf:獲取字符串中最后一個(gè) . 的位置)
String suffix = fileName.substring(fileName.lastIndexOf("."));
// 將 UUID 作為文件名,保證唯一性
String uuid = UUID.randomUUID().toString();
// 將 UUID 和后綴名進(jìn)行拼接,得到完整的文件名
String fullName = uuid + suffix;
// 獲取當(dāng)前工程的上下文路徑
ServletContext servletContext = session.getServletContext();
// 給定一個(gè) URI,返回文件系統(tǒng)中 URI對(duì)應(yīng)的絕對(duì)路徑
String photoPath = servletContext.getRealPath("photo");
File file = new File(photoPath);
// 判斷 photoPath 所對(duì)應(yīng)的路徑是否存在
if (!file.exists()) {
// 如果不存在,則創(chuàng)建對(duì)應(yīng)目錄
file.mkdirs();
}
// 最終的上傳地址
String finalPath = photoPath + File.separator + fullName;
// 將文件上傳到指定的目錄
photo.transferTo(new File(finalPath));
return "success";
}
}
一般來(lái)說(shuō),UUID是不會(huì)重名的
以上就是SpringMVC將請(qǐng)求和響應(yīng)的數(shù)據(jù)轉(zhuǎn)換為JSON格式的幾種方式的詳細(xì)內(nèi)容,更多關(guān)于SpringMVC數(shù)據(jù)轉(zhuǎn)換為JSON格式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Mybatis-Plus使用ID_WORKER生成主鍵id重復(fù)的解決方法
本文主要介紹了Mybatis-Plus使用ID_WORKER生成主鍵id重復(fù)的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07
java中對(duì)象和JSON格式的轉(zhuǎn)換方法代碼
JSON格式可以輕松地以面向?qū)ο蟮姆绞睫D(zhuǎn)換為Java對(duì)象,下面這篇文章主要給大家介紹了關(guān)于java中對(duì)象和JSON格式的轉(zhuǎn)換方法,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12
Java下載文件中文文件名亂碼的解決方案(文件名包含很多%)
Java下載文件時(shí),文件名中文亂碼問(wèn)題通常是由于編碼不正確導(dǎo)致的,使用`URLEncoder.encode(filepath, "UTF-8")`可以解決在提示下載框中正確顯示漢字文件名的問(wèn)題,但在選擇直接打開(kāi)時(shí),文件名會(huì)變成亂碼,解決這個(gè)問(wèn)題的方法2025-02-02
引入mybatis-plus報(bào) Invalid bound statement錯(cuò)誤問(wèn)題的解決方法
這篇文章主要介紹了引入mybatis-plus報(bào) Invalid bound statement錯(cuò)誤問(wèn)題的解決方法,需要的朋友可以參考下2020-05-05
Spring?Boot應(yīng)用打WAR包后無(wú)法注冊(cè)到Nacos的問(wèn)題及解決方法
當(dāng)我們將?Spring?Boot?應(yīng)用打包成?WAR?并部署到外部?Tomcat?服務(wù)器時(shí),可能會(huì)遇到服務(wù)無(wú)法注冊(cè)到?Nacos?的情況,其原因主要是應(yīng)用獲取不到正確的服務(wù)器端口,下面給大家介紹Spring?Boot?應(yīng)用打?WAR?包后無(wú)法注冊(cè)到?Nacos的問(wèn)題及解決方法,感興趣的朋友跟隨小編一起看看吧2024-06-06
Spring MVC 中 AJAX請(qǐng)求并返回JSON的示例
本篇文章主要介紹了Spring MVC 中 AJAX請(qǐng)求并返回JSON,具有一定的參考價(jià)值,有興趣的可以了解一下。2017-01-01
解決springboot集成swagger碰到的坑(報(bào)404)
這篇文章主要介紹了解決springboot集成swagger碰到的坑(報(bào)404),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
JAVA讀取文件流,設(shè)置瀏覽器下載或直接預(yù)覽操作
這篇文章主要介紹了JAVA讀取文件流,設(shè)置瀏覽器下載或直接預(yù)覽操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10
在IDEA中安裝MyBatis Log Plugin插件,執(zhí)行mybatis的sql語(yǔ)句(推薦)
這篇文章主要介紹了在IDEA中安裝MyBatis Log Plugin插件,執(zhí)行mybatis的sql語(yǔ)句,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07

