Servlet如何接收JSON数据:完整指南
在现代Web开发中,JSON(JavaScript Object Notation)因其轻量级、易读性和与JavaScript的天然兼容性,已成为前后端数据交互的主流格式,Servlet作为Java EE中处理HTTP请求的核心组件,需要高效接收和处理JSON数据,本文将详细介绍Servlet接收JSON数据的完整流程,包括环境准备、数据接收、解析及常见问题处理。
环境准备:添加JSON处理依赖
Servlet本身不直接提供JSON解析功能,需借助第三方库将JSON字符串转换为Java对象,常用的JSON解析库有 Gson(Google)、Jackson(Spring生态默认)和 Fastjson(阿里),本文以 Gson 和 Jackson 为例,说明依赖添加方式。
Maven项目依赖
在pom.xml中添加对应依赖(以Jackson为例,Gson类似):
<!-- Jackson核心依赖 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
<!-- 如果使用Servlet API,需添加servlet依赖(如未在项目中配置) -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
Gradle项目依赖
在build.gradle中添加:
implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2' providedCompile 'javax.servlet:javax.servlet-api:4.0.1'
接收JSON数据的核心步骤
Servlet接收JSON数据的核心流程分为三步:
- 获取请求体:通过
HttpServletRequest获取客户端发送的原始JSON字符串。 - 解析JSON:使用JSON库将字符串转换为Java对象(如POJO、List或Map)。
- 处理业务逻辑:基于解析后的数据执行业务操作(如数据库存储、计算等)。
步骤1:获取请求体中的JSON字符串
客户端通常通过POST请求发送JSON数据,并设置Content-Type: application/json,Servlet中需通过HttpServletRequest的getInputStream()或getReader()读取请求体内容。
示例代码:
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
public class JsonReceiverServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// 1. 获取请求体中的JSON字符串
StringBuilder jsonStr = new StringBuilder();
BufferedReader reader = req.getReader();
String line;
while ((line = reader.readLine()) != null) {
jsonStr.append(line);
}
System.out.println("接收到的原始JSON: " + jsonStr);
}
}
注意:
- 使用
getReader()而非getInputStream(),因为JSON是文本数据,Reader能更好地处理字符编码(避免乱码)。 - 确保客户端请求的
Content-Type正确设置为application/json,否则可能导致服务器无法正确解析请求体。
步骤2:使用JSON库解析字符串为Java对象
获取JSON字符串后,需将其转换为Java对象以便业务逻辑处理,以下分别用Jackson和Gson实现解析。
方案1:使用Jackson解析(推荐)
Jackson是Spring Boot等框架的默认JSON库,性能高且功能完善,假设客户端发送的JSON如下:
{
"name": "张三",
"age": 25,
"email": "zhangsan@example.com"
}
首先定义对应的Java实体类(POJO):
public class User {
private String name;
private int age;
private String email;
// 必须提供无参构造方法(Jackson反射需要)
public User() {}
// getter和setter方法
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
@Override
public String toString() {
return "User{name='" + name + "', age=" + age + ", email='" + email + "'}";
}
}
在Servlet中使用Jackson解析:
import com.fasterxml.jackson.databind.ObjectMapper; // Jackson核心类
public class JsonReceiverServlet extends HttpServlet {
private ObjectMapper objectMapper = new ObjectMapper(); // 复用实例,避免重复创建
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// 1. 读取JSON字符串
String jsonStr = req.getReader().lines().reduce("", (accumulator, actual) -> accumulator + actual);
try {
// 2. 将JSON字符串转换为User对象
User user = objectMapper.readValue(jsonStr, User.class);
System.out.println("解析后的User对象: " + user);
// 3. 业务逻辑处理(如保存到数据库)
// saveToDatabase(user);
} catch (Exception e) {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "JSON格式错误: " + e.getMessage());
e.printStackTrace();
}
}
}
方案2:使用Gson解析
Gson是Google推出的JSON库,使用简单,同样以上面的User类为例,解析代码如下:
import com.google.gson.Gson; // Gson核心类
public class JsonReceiverServlet extends HttpServlet {
private Gson gson = new Gson(); // 复用实例
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// 1. 读取JSON字符串
String jsonStr = req.getReader().lines().collect(Collectors.joining());
try {
// 2. 将JSON字符串转换为User对象
User user = gson.fromJson(jsonStr, User.class);
System.out.println("解析后的User对象: " + user);
} catch (Exception e) {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "JSON格式错误: " + e.getMessage());
e.printStackTrace();
}
}
}
步骤3:处理复杂JSON结构
如果JSON数据是嵌套对象或数组,只需调整Java实体类结构即可,接收包含用户列表的JSON:
{
"users": [
{"name": "李四", "age": 30},
{"name": "王五", "age": 28}
]
}
定义对应的Java类:
import java.util.List;
public class UserListWrapper {
private List<User> users;
// getter和setter
public List<User> getUsers() { return users; }
public void setUsers(List<User> users) { this.users = users; }
}
解析时直接转换为目标类型:
// Jackson解析 UserListWrapper userListWrapper = objectMapper.readValue(jsonStr, UserListWrapper.class); List<User> users = userListWrapper.getUsers(); // Gson解析 UserListWrapper userListWrapper = gson.fromJson(jsonStr, UserListWrapper.class); List<User> users = userListWrapper.getUsers();
常见问题与解决方案
中文乱码问题
现象:JSON中的中文字符解析后显示为或乱码(如)。
原因:请求体编码与解析编码不一致,默认情况下,HttpServletRequest的getReader()使用ISO-8859-1编码,而JSON通常为UTF-8编码。
解决:在读取请求体前设置字符编码:
req.setCharacterEncoding("UTF-8"); // 必须在getReader()之前调用
BufferedReader reader = req.getReader();
JSON格式错误
现象:客户端发送的JSON格式不正确(如缺少引号、逗号等),导致解析失败。
解决:捕获JSON库抛出的异常,并返回友好的错误提示:
try {
User user = objectMapper.readValue(jsonStr, User.class);
} catch (JsonParseException e) {
resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
resp.getWriter().write("JSON格式错误:" + e.getMessage());
}
大数据量请求处理
现象:请求体较大时(如上传文件元数据),getReader()读取可能内存溢出。
解决:使用getInputStream()直接读取字节流,或结合缓冲流逐步处理:
// 使用字节流(适合二进制+JSON混合数据)
ServletInputStream inputStream = req.getInputStream();
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
// 处理字节数据(如写入临时文件)
}
跨域请求问题
现象:前端跨域请求被浏览器拦截,提示“



还没有评论,来说两句吧...