在 Java Web 开发中,主要有两种技术栈来处理 HTTP 响应:

- Servlet API (原生 Java Web 技术)
- Spring Framework (现代主流框架)
下面我将分别介绍在这两种技术栈中如何进行 response 输出。
Servlet API (原生方式)
在 Servlet 中,javax.servlet.http.HttpServletResponse 对象代表了服务器的响应,我们通过操作这个对象来向客户端返回数据。
核心方法
response.getWriter(): 获取一个PrintWriter对象,用于输出字符文本(如 HTML, JSON, XML 字符串)。response.getOutputStream(): 获取一个ServletOutputStream对象,用于输出二进制数据(如图片、文件、PDF)。response.setContentType(String type): 设置响应的内容类型(MIME Type),告诉浏览器我返回的是什么数据。text/html,application/json,image/jpeg。response.setCharacterEncoding(String charset): 设置响应的字符编码,防止中文乱码,通常与setContentType结合使用。response.setStatus(int sc): 设置 HTTP 状态码,如200(OK),404(Not Found),500(Server Error)。
输出纯文本
这是最简单的场景,直接向浏览器输出一段文本。
示例代码:

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 java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/text-output")
public class TextOutputServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 设置响应内容类型和字符编码
// 告诉浏览器这是HTML内容,并使用UTF-8编码
response.setContentType("text/html;charset=UTF-8");
// 2. 获取PrintWriter对象
PrintWriter out = response.getWriter();
// 3. 输出内容
out.println("<h1>Hello, Servlet World!</h1>");
out.println("<p>当前时间: " + new java.util.Date() + "</p>");
// 4. 关闭流 (虽然不关Tomcat也会关,但最好手动关闭)
out.close();
}
}
访问 http://yourserver:8080/your-app/text-output,浏览器会显示:
Hello, Servlet World!
当前时间: Wed Oct 26 10:30:00 CST 2025
输出 JSON 数据
这是现代 Web 开发中最常见的场景,后端向前端提供 JSON 格式的数据。

关键点:
Content-Type必须设置为application/json。- 字符编码建议统一使用
UTF-8。
示例代码:
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 java.io.IOException;
import java.io.PrintWriter;
import com.google.gson.Gson; // 使用 Gson 库来方便地转成 JSON
@WebServlet("/json-output")
public class JsonOutputServlet extends HttpServlet {
// 创建一个 Gson 实例
private Gson gson = new Gson();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 设置响应内容类型为 JSON,字符编码为 UTF-8
response.setContentType("application/json;charset=UTF-8");
// 2. 准备要返回的 Java 对象
User user = new User("张三", 30, "zhangsan@example.com");
// 3. 将 Java 对象转换为 JSON 字符串
String jsonString = gson.toJson(user);
// 4. 获取 PrintWriter 并输出 JSON 字符串
PrintWriter out = response.getWriter();
out.print(jsonString); // 使用 print 或 println 都可以
out.flush(); // 刷新缓冲区,确保数据被写出
}
}
// 一个简单的 User 类
class User {
private String name;
private int age;
private String email;
public User(String name, int age, String email) {
this.name = name;
this.age = age;
this.email = email;
}
// Getters are required by Gson to serialize the object
public String getName() { return name; }
public int getAge() { return age; }
public String getEmail() { return email; }
}
访问 http://yourserver:8080/your-app/json-output,浏览器会显示(或开发者工具 Network 面板中看到):
{"name":"张三","age":30,"email":"zhangsan@example.com"}
下载文件
当需要让用户下载文件时,需要设置 Content-Type 和 Content-Disposition。
关键点:
Content-Type设置为文件的 MIME 类型(如application/octet-stream表示二进制流,浏览器会触发下载)。Content-Disposition设置为attachment; filename="...",告诉浏览器这是一个附件,并指定下载时的文件名。
示例代码:
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 java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
@WebServlet("/download-file")
public class FileDownloadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 要下载的文件路径(假设项目根目录下有一个 test.txt)
String filePath = getServletContext().getRealPath("/test.txt");
// 2. 设置响应头,触发下载
response.setContentType("application/octet-stream");
// URLEncoder.encode 用于处理文件名中可能包含的中文或特殊字符
response.setHeader("Content-Disposition", "attachment; filename=\"" + java.net.URLEncoder.encode("测试文件.txt", "UTF-8") + "\"");
// 3. 使用 OutputStream 输出二进制文件内容
try (FileInputStream fis = new FileInputStream(filePath);
OutputStream os = response.getOutputStream()) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
}
}
}
Spring Framework (现代方式)
Spring MVC 封装了底层的 Servlet API,提供了更简洁、更强大的方式来处理响应,我们通常通过在 Controller 方法的返回值或直接操作 HttpServletResponse 对象来实现。
返回字符串或对象(最常用)
Spring 会自动处理序列化和响应头的设置。
Controller 示例:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController // @RestController = @Controller + @ResponseBody,默认所有方法都返回响应体
public class MySpringController {
// 1. 直接返回字符串,Spring 会自动将其作为 text/plain 返回
@GetMapping("/hello-spring")
public String sayHello() {
return "Hello from Spring Boot!";
}
// 2. 返回一个 Map 或自定义对象,Spring 会自动将其转换为 JSON 并设置 Content-Type 为 application/json
@GetMapping("/user-json")
public Map<String, Object> getUserJson() {
Map<String, Object> user = new HashMap<>();
user.put("name", "李四");
user.put("age", 25);
return user;
}
// 3. 返回一个自定义对象,效果和返回 Map 一样
@GetMapping("/user-object")
public User getUserObject() {
return new User("王五", 28, "wangwu@example.com");
}
}
说明:
@RestController注解告诉 Spring 这个类中的所有方法都返回响应体(ResponseBody),而不是视图名称。- Spring Boot 默认会使用 Jackson 库(在
spring-boot-starter-web中包含)来将对象序列化为 JSON。
手动操作 HttpServletResponse
有时候我们需要更精细的控制,比如设置自定义的响应头或下载文件。
Controller 示例:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@RestController
public class ManualResponseController {
@GetMapping("/manual-json")
public void getManualJson(HttpServletResponse response) throws IOException {
// 手动设置响应头
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
// 手动向响应中写入内容
PrintWriter out = response.getWriter();
out.print("{\"status\": \"ok\", \"message\": \"This is manually set JSON.\"}");
out.flush();
}
@GetMapping("/download-spring")
public void downloadFile(HttpServletResponse response) throws IOException {
// 文件路径
String filePath = getServletContext().getRealPath("/test.txt");
// 设置响应头
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=\"" + java.net.URLEncoder.encode("Spring测试文件.txt", "UTF-8") + "\"");
// 使用 Spring 提供的 ResourceUtils 或直接使用 Java IO 流
try (java.io.FileInputStream fis = new java.io.FileInputStream(filePath);
java.io.OutputStream os = response.getOutputStream()) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
}
}
}
总结与对比
| 特性 | Servlet API | Spring MVC |
|---|---|---|
| 核心对象 | HttpServletResponse |
HttpServletResponse (作为参数注入) 或直接返回值 |
| 输出文本 | response.getWriter().println() |
直接返回 String 或对象,由框架自动处理 |
| 输出JSON | 手动设置 Content-Type,并用 Gson/Jackson 转换后 print |
直接返回对象,框架自动用 Jackson/Gson 转换并设置 Content-Type |
| 下载文件 | 手动设置 Content-Type 和 Content-Disposition,用 OutputStream 写入 |
手动设置响应头,用 OutputStream 写入 |
| 易用性 | 较繁琐,需要手动处理很多细节 | 非常简洁,约定大于配置,开发效率高 |
| 适用场景 | 学习 Servlet 原理、维护老旧项目 | 现代所有 Java Web 项目开发 |
核心建议:
- 如果你在学习 Java Web 的基础原理,务必掌握 Servlet API 的用法,这是根基。
- 如果你在进行任何实际的项目开发,请直接使用 Spring Boot 或其他现代框架,它们能让你从繁琐的底层细节中解放出来,更专注于业务逻辑。
