1 处理 JSON-@ResponseBody
说明: 项目开发中,我们往往需要服务器返回的数据格式是按照 json 来返回的
下面通过一个案例来演示SpringMVC 是如何处理的
(1) 在web/WEB-INF/lib 目录下引入处理 json 需要的 jar 包,注意 spring5.x 需要使用 jackson-2.9.x.jar 的包(所需jar包以附在文章顶部)
(2) 创建json.jsp,在前端发送一个ajax请求
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>json提交</title>
<!-- 引入jquery -->
<script type="text/javascript" src="script/jquery-3.6.0.min.js"></script>
<!-- 编写jquery代码和ajax请求 -->
<script type="text/javascript">
$(function () {
//给id="getJson"绑定点击事件
$("#getJson").click(function () {
//console.log("ok ....")
var url = this.href;
var args = {"time": new Date};//这是要发送数据,为了防止页面缓存
$.post(
url,
args,
function (data) {//data 就是返回的数据,是json格式=>如果是多个json数据,可以遍历
console.log("dataa= ", data);
console.log("dog.name=", data.name)
console.log("dog.addresss=", data.address)
},
"json"
);
return false;//这里我们返回false,就不使用href默认机制,即不会跳转
})
})
</script>
</head>
<body>
<h1>请求一个json数据</h1>
<%--
1.当用户点击超链接时,我们发出一个ajax请求
2. 接收到请求后,我们查看这个数据
--%>
<a href="<%=request.getContextPath()%>/json/dog" id="getJson">点击获取json数据</a>
</body>
</html>
(3)创建JavaBean类 Dog.java
package com.web.json.entity;
public class Dog {
private String name;
private String address;
public Dog(String name, String address) {
this.name = name;
this.address = address;
}
public Dog() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
(4)创建 JsonHandler.java
package com.web.json;
import com.web.json.entity.Dog;
import com.web.json.entity.User;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpSession;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
@Controller
public class JsonHandler {
/**
* 1. 目标方法 @ResponseBody,表示返回的数据是json格式
* 2. springmvc底层根据目标方法上的注解@ResponseBody, 返回指定格式, 根据的http请求来进行处理
* 3. 这里springmvc底层使用的是转换器HttpMessageConverter
*/
@RequestMapping(value = "/json/dog")
@ResponseBody
public Dog getJson() {
//返回对象
//springmvc会根据你的设置,转成json格式数据返回
Dog dog = new Dog();
dog.setName("大黄狗");
dog.setAddress("小新的家");
return dog;
}
}
(5)测试
也可以通过列表返回多个 Json 数据,在 JsonHandler.java 类中添加如下方法
//编写方法,以json格式返回多个Dog
@RequestMapping(value = "/json/dogs")
@ResponseBody
public List<Dog> getJsons() {
List<Dog> dogs = new ArrayList<>();
dogs.add(new Dog("大黄狗", "小新的家"));
dogs.add(new Dog("大黄狗2", "小新2的家"));
dogs.add(new Dog("大黄狗3", "小新3的家"));
return dogs;
}
使用postman测试:
2 处理 JSON-@RequestBody
说明:客户端发送 json 字符串数据给后端, 这时候可以使用 SpringMVC 的 @RequestBody 将客户端提交的 json 数据,封装成 JavaBean 对象
使用案例:
(1)创建javabean类 User.java
package com.web.json.entity;
public class User {
private String userName;
private Integer age;
public User(String userName, Integer age) {
this.userName = userName;
this.age = age;
}
public User() {
}
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)在 JsonHandler.java 类中添加如下方法
/**
* 1. @RequestBody User user 在形参指定了 @RequestBody
* 2. springmvc就会将提交的json字符串数据填充给指定Javabean
*/
@RequestMapping(value = "/save2")
@ResponseBody
public User save2(@RequestBody User user) {
//将前台传过来的数据 以json的格式返回浏览器
System.out.println("user~= " + user);
return user;
}
(3)创建jsp页面发送请求,发送json数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>json提交</title>
<!-- 引入jquery -->
<script type="text/javascript" src="script/jquery-3.6.0.min.js"></script>
<!-- 编写jquery代码和ajax请求 -->
<script type="text/javascript">
$(function () {
//绑定按钮点击事件, 提交json数据
//springmvc 可以在在台将json数据转成对象
$("button[name='butt1']").click(function () {
//目标:将userName 和 age 封装成json字符串,发送给目标方法
var url = "/springmvc/save2";
var userName = $("#userName").val();
var age = $("#age").val();
//将json对象转成json格式字符串
var args = JSON.stringify({"userName": userName, "age": age});
$.ajax({
url: url,
data: args,
type: "POST",
success: function (data) {
console.log("返回的data= ", data);
},
//下面这个contentType参数,是指定发送数据的编码和格式
contentType: "application/json;charset=utf-8"
})
})
})
</script>
</head>
<body>
<h1>发出一个json数据</h1>
u:<input id="userName" type="text"><br/>
a:<input id="age" type="text"><br/>
<button name="butt1">添加用户</button>
</body>
</html>
(4)测试效果
3 处理 JSON-注意事项和细节
(1)@ResponseBody 可以直接写在 controller 上 即hanler类上,这样对所有方法生效 ,相当于所有方法都添加了这个注解
(2)@ResponseBody + @Controller 可以直接写成 @RestController。这里看一下@RestController注解的源码就知道了,源码如下
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
@AliasFor(
annotation = Controller.class
)
String value() default "";
}
4 HttpMessageConverter<T>
基本说明:SpringMVC 处理 JSON 底层实现是依靠 HttpMessageConverter<T>来进行转换的
工作机制简图
- 使用 @RequestBody / @ResponseBody 对目标方法进行标注
- 使用 HttpEntity<T> / ResponseEntity<T> 作为目标方法的入参或返回值
匹配 的 HttpMessageConverter, 进而根据参数类型或泛型类型的过滤得到匹配的 HttpMessageConverter, 若找不到可用的 HttpMessageConverter 将报错
5 文件下载-ResponseEntity<T>
说明: 在 SpringMVC 中,通过返回 ResponseEntity<T>的类型,可以实现文件下载的功能
应用案例:
(1)编写前端页面发送请求
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>json提交</title>
</head>
<body>
<h1>下载文件的测试 </h1>
<a href="<%=request.getContextPath()%>/downFile">点击下载文件</a>
</body>
</html>
(2)把图片复制到web/img目录下
(3)在 JsonHandler.java 类中添加如下方法
//响应用户下载文件的请求
@RequestMapping(value = "/downFile")
public ResponseEntity<byte[]> downFile(HttpSession session)
throws Exception {
//1. 先获取到下载文件的inputStream
InputStream resourceAsStream =
session.getServletContext().getResourceAsStream("/img/2.png");
//2. 开辟一个存放文件的byte数组, 这里使用byte[] 是为了可以支持二进制数据(图片,视频。)
byte[] bytes = new byte[resourceAsStream.available()];
//3. 将下载文件的数据,读入到byte[]
resourceAsStream.read(bytes);
// ResponseEntity构造器
//public ResponseEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers, HttpStatus status) {}
//4. 创建返回的HttpStatus
HttpStatus httpStatus = HttpStatus.OK;
//5. 创建 headers
HttpHeaders headers = new HttpHeaders();
//指定返回的数据,客户端应当以附件形式处理
headers.add("Content-Disposition", "attchment;filename=2.png");
//构建一个ResponseEntity 对象 1. http响应头headers 2. http响应状态 3. 下载的文件数据
ResponseEntity<byte[]> responseEntity =
new ResponseEntity<>(bytes, headers, httpStatus);
//如果出现找不到文件,解决方法 rebuild project -> 重启tomcat
return responseEntity;
}
文件下载响应头的设置 :
content-type 指示响应内容的格式
content-disposition 指示如何处理响应内容。
content-disposition一般有两种方式:
inline:直接在页面显示
attchment:以附件形式下载
(4)启动服务器,测试效果如下
6 文件上传
6.1 基本介绍
(1)Spring MVC 为 文 件 上 传 提 供 了 直 接 的 支 持 , 这 种 支 持 是 通 过 即 插 即 用 的 MultipartResolver 实 现 的 。 Spring 用 Jakarta Commons FileUpload 技 术 实 现 了 一 个 MultipartResolver 实现类:CommonsMultipartResovler
(2)Spring MVC 上下文中默认没有装配 MultipartResovler,因此默认情况下不能处理文件的 上传工作,如果想使用 Spring 的文件上传功能,需要在上下文中配置 MultipartResolver
<!--配置文件上传需要的bean-->
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
id="multipartResolver"/>
6.2 应用实例
(1)引入 springmvc 文件上传需要的 jar 包(已附在文章顶部)
(2)创建前端页面 fileUpload.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>文件上传</title>
</head>
<body>
<h1>文件上传的演示</h1>
<%--
1.enctype编码类型,默认是application/x-www-irlencoded 即url编码 这种编码不适用二进制文件数据的提交
一般适用于文本
2.如果要进行二进制文件的提交 enctype 要指定 multipart/form-data 表示提交的数据是由多个部分组成,
也就是可以提交二进制数据和文本数据
--%>
<form action="<%=request.getContextPath()%>/fileUpload" method="post" enctype="multipart/form-data">
文件介绍:<input type="text" name="introduce"><br>
选择文件:<input type="file" name="file"><br>
<input type="submit" value="上传文件">
</form>
</body>
</html>
(3) 在spring配置文件xml文件中配置文件上传解析器
<!--配置文件上传需要的bean-->
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
id="multipartResolver"/>
(4)创建 FileUploadHandler.java 类
package com.web.fileupload;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
@Controller
public class FileUploadHandler {
//编写方法,处理文件上传的请求
@RequestMapping(value = "/fileUpload")
public String fileUpload(@RequestParam(value = "file") MultipartFile file,
HttpServletRequest request, String introduce) throws IOException {
//接收到提交的文件名
String originalFilename = file.getOriginalFilename();
System.out.println("你上传的文件名= " + originalFilename);
System.out.println("introduce=" + introduce);
//得到要把上传文件保存到哪个路径[全路径:包括文件名]
String fileFullPath =
request.getServletContext().getRealPath("/img/" + originalFilename);
//创建文件
File saveToFile = new File(fileFullPath);
//将上传的文件,转存到saveToFile
file.transferTo(saveToFile);
return "success";
}
}
(5)启动服务器,测试效果
文件上传成功!