Servlet 返回数据的核心是 HttpServletResponse 对象,当请求到达时,Servlet 容器(如 Tomcat)会创建一个 HttpServletRequest 对象(包含请求信息)和一个 HttpServletResponse 对象(用于构建响应),然后将它们作为参数传递给 service() 方法。

HttpServletResponse 提供了多种方法来设置响应的内容、状态码和头信息。
返回数据的几种主要方式
根据客户端的需求(浏览器、App、其他服务等),Servlet 可以返回不同类型的数据,最常见的是以下三种:
- 返回 HTML 页面:用于传统的 Web 应用,直接渲染一个完整的 HTML 页面。
- 返回 JSON 数据:现代 Web 应用和移动 App 的首选,前后端分离架构的核心。
- 返回纯文本或 XML:相对简单,用于特定场景。
返回 HTML 页面
这是最基础的方式,Servlet 会生成一个完整的 HTML 文档,然后将其写入响应输出流。
关键步骤:
- 设置响应内容类型:
response.setContentType("text/html;charset=UTF-8");text/html:告诉浏览器这是一个 HTML 文件。charset=UTF-8:指定字符编码为 UTF-8,防止中文等非英文字符乱码。
- 获取输出流:
PrintWriter out = response.getWriter();PrintWriter是一个字符流,方便写入文本内容。
- 写入 HTML 内容:使用
out.println()方法将 HTML 标签和内容写入流中。
示例代码:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/helloHtml")
public class HelloHtmlServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 设置响应内容类型和字符编码
response.setContentType("text/html;charset=UTF-8");
// 2. 获取PrintWriter输出流
PrintWriter out = response.getWriter();
// 3. 写入HTML内容
out.println("<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println("<meta charset=\"UTF-8\">");
out.println("<title>Servlet HTML Response</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>你好,世界!</h1>");
out.println("<p>这是由Servlet动态生成的HTML页面。</p>");
out.println("</body>");
out.println("</html>");
// 4. 关闭流(可选,但推荐)
out.close();
}
}
如何访问:将项目部署到 Tomcat 后,在浏览器中访问 http://localhost:8080/你的项目名/helloHtml,就会看到一个标题为 "Servlet HTML Response" 的页面。

返回 JSON 数据(最常用)
在前后端分离的架构中,Servlet 通常作为后端 API,返回 JSON 格式的数据供前端(如 Vue, React, Angular)或移动 App 消费。
关键步骤:
- 设置响应内容类型:
response.setContentType("application/json;charset=UTF-8");application/json:这是标准的 JSON 内容类型,告诉客户端返回的是 JSON 数据。
- 禁用缓存(可选,但推荐):
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");对于 API 接口,通常不希望浏览器或代理服务器缓存结果,确保每次请求都获取最新数据。
- 构造 JSON 字符串:
- 手动拼接:对于简单的 JSON,可以直接用 或
StringBuilder拼接字符串。不推荐,容易出错且难以维护。 - 使用 JSON 库:强烈推荐使用如
Jackson,Gson或Fastjson等库来将 Java 对象序列化为 JSON 字符串,这是最标准、最安全、最方便的方式。
- 手动拼接:对于简单的 JSON,可以直接用 或
- 获取输出流并写入:同样使用
PrintWriter将 JSON 字符串写入响应流。
示例代码(使用 Jackson 库):
确保你的项目中包含了 Jackson 的依赖(在 Maven 的 pom.xml 中):
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version> <!-- 使用较新版本 -->
</dependency>
Servlet 代码:

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.fasterxml.jackson.databind.ObjectMapper; // Jackson 核心类
@WebServlet("/getUserInfo")
public class UserJsonServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
// 使用 Jackson 的 ObjectMapper,推荐声明为静态 final,避免重复创建
private static final ObjectMapper objectMapper = new ObjectMapper();
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 设置响应内容类型为 JSON
response.setContentType("application/json;charset=UTF-8");
// 2. 禁用缓存
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
// 3. 准备要返回的 Java 对象
User user = new User();
user.setId(101);
user.setName("张三");
user.setEmail("zhangsan@example.com");
// 4. 将 Java 对象转换为 JSON 字符串
// objectMapper.writeValueAsString() 会自动完成序列化
String jsonString = objectMapper.writeValueAsString(user);
// 5. 获取输出流并写入 JSON 字符串
PrintWriter out = response.getWriter();
out.print(jsonString); // 使用 print 而不是 println,避免末尾多一个换行符
out.flush(); // 刷新流,确保数据被写出
// out.close(); // 在 try-with-resources 或 finally 块中关闭
}
}
// 一个简单的 POJO (Plain Old Java Object)
class User {
private int id;
private String name;
private String email;
// Getters and Setters (必须要有,Jackson 需要通过反射访问)
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
}
如何访问:在浏览器或 Postman 中访问 http://localhost:8080/你的项目名/getUserInfo,你会得到如下 JSON 响应:
{
"id": 101,
"name": "张三",
"email": "zhangsan@example.com"
}
返回纯文本
这种方式非常简单,适用于返回简单的状态信息、配置内容等。
关键步骤:
- 设置响应内容类型:
response.setContentType("text/plain;charset=UTF-8");text/plain:告诉浏览器这是纯文本,不会尝试解析为 HTML。
- 获取输出流并写入:使用
PrintWriter写入文本。
示例代码:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/textResponse")
public class TextResponseServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置内容类型为纯文本
response.setContentType("text/plain;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("这是一个纯文本响应。");
out.println("当前时间戳: " + System.currentTimeMillis());
}
}
其他重要的响应控制
HttpServletResponse 还可以控制响应的方方面面。
设置响应状态码
默认状态码是 200 OK,你可以手动设置其他状态码,
// 请求的资源不存在 (404 Not Found)
response.sendError(HttpServletResponse.SC_NOT_FOUND, "用户ID不存在");
// 服务器内部错误 (500 Internal Server Error)
// response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
// 重定向 (302 Found)
// response.sendRedirect("http://www.example.com");
设置响应头
除了 Content-Type,你还可以设置其他头信息,
// 设置自定义头
response.setHeader("X-Custom-Header", "MyCustomValue");
// 设置允许跨域 (CORS)
response.setHeader("Access-Control-Allow-Origin", "*"); // * 表示允许所有域名,生产环境请指定具体域名
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
response.setHeader("Access-Control-Allow-Headers", "Content-Type");
-
使用
try-with-resources:PrintWriter和ServletOutputStream都实现了AutoCloseable接口,使用try-with-resources可以自动关闭流,即使发生异常,也能确保资源被释放,避免内存泄漏。try (PrintWriter out = response.getWriter()) { out.println("安全的资源写入"); } catch (IOException e) { // 处理异常 } -
优先使用 JSON 库:永远不要手动拼接复杂的 JSON 字符串,使用 Jackson 或 Gson 等成熟的库,它们能正确处理转义符、日期、复杂对象等,代码更健壮、可读性更高。
-
统一字符编码:始终在设置
Content-Type时明确指定charset=UTF-8,这是处理中文和多语言内容的基本要求。 -
清晰的 URL 映射:使用
@WebServlet注解或web.xml配置清晰的 URL 模式,便于维护和理解 API 的功能。 -
处理异常:在
catch块中,记录错误日志,并向客户端返回一个友好的错误信息或适当的 HTTP 状态码。
