杰瑞科技汇

java response方法

封装服务器要发送给客户端的所有信息,包括 HTTP 状态码、响应头、响应体(内容)等。

在 Java Web 开发中,主要有两种主流的 API 来处理 response

  1. Servlet API (最传统、最基础)
  2. Spring MVC (目前最流行、最高效)

下面我们分别对这两种 API 进行详细说明。


Servlet API 中的 response

在标准的 Java Web 开发中,response 是一个 javax.servlet.http.HttpServletResponse 对象,它由 Servlet 容器(如 Tomcat)创建,并通过 service 方法传递给我们的 Servlet。

核心功能

HttpServletResponse 提供了一系列方法来构建响应。

常用方法详解

1 设置响应状态码

状态码是一个三位数的数字,用于表示响应的结果,最常见的是 200(成功)、404(未找到)、500(服务器内部错误)等。

// 设置状态码为 200 (OK),这是默认值,通常不需要显式设置
response.setStatus(HttpServletResponse.SC_OK); // 或者 response.setStatus(200);
// 设置状态码为 404 (Not Found)
response.setStatus(HttpServletResponse.SC_NOT_FOUND); // 或者 response.setStatus(404);
// 设置状态码为 302 (Found),用于重定向
response.setStatus(HttpServletResponse.SC_FOUND); // 或者 response.setStatus(302);

2 设置响应头

响应头是服务器发送给客户端的附加信息,如内容类型、内容长度、缓存控制等。

// text/html 表示 HTML 文本
// charset=UTF-8 指定字符编码为 UTF-8,防止中文乱码
response.setContentType("text/html;charset=UTF-8");
// 设置自定义响应头
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // 禁止缓存
response.setHeader("Custom-Header", "This is a custom value");
// 更便捷的方法设置常用头
response.setCharacterEncoding("UTF-8"); // 设置字符编码

3 获取输出流并写入响应体

响应体就是客户端实际看到或接收到的内容,我们需要通过获取输出流来写入这些内容。

有两种输出流:

  • getOutputStream(): 用于输出二进制数据(如图片、PDF、视频等)。
  • getWriter(): 用于输出文本数据(如 HTML、JSON、XML 等)。

注意: 在同一个响应中,不能同时调用 getOutputStream()getWriter(),否则会抛出 IllegalStateException

示例:输出简单的 HTML

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("<html>");
    out.println("<head><title>Hello Servlet</title></head>");
    out.println("<body>");
    out.println("<h1>你好,世界!</h1>");
    out.println("<p>这是通过 Servlet 输出的响应。</p>");
    out.println("</body>");
    out.println("</html>");
    // 4. 关闭流 (虽然 Tomcat 会自动回收,但显式关闭是好习惯)
    out.close();
}

示例:输出 JSON

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 1. 设置响应头为 JSON 格式
    response.setContentType("application/json;charset=UTF-8");
    // 2. 获取 PrintWriter 输出流
    PrintWriter out = response.getWriter();
    // 3. 构建一个简单的 JSON 字符串
    String jsonResponse = "{\"name\": \"张三\", \"age\": 30, \"city\": \"北京\"}";
    // 4. 写入 JSON 数据
    out.print(jsonResponse);
    // 5. 关闭流
    out.close();
}

4 重定向

重定向是服务器告诉客户端去访问另一个 URL,客户端会自动发起一个新的请求到新的 URL。

实现方式:

// 方式一:设置状态码和响应头
response.setStatus(HttpServletResponse.SC_FOUND); // 302
response.setHeader("Location", "https://www.example.com/new-location");
// 方式二:更便捷的方法
response.sendRedirect("https://www.example.com/new-location");
// 或者重定向到当前项目内的其他路径
response.sendRedirect("login.jsp"); 

重定向 vs. 转发:

  • 重定向 (sendRedirect): 客户端行为,会产生两次请求,浏览器的地址栏会改变。
  • 转发 (RequestDispatcher.forward): 服务器行为,只产生一次请求,浏览器地址栏不变。

Spring MVC 中的 response

在 Spring MVC 框架中,我们通常不直接操作原始的 HttpServletResponse 对象,框架为我们提供了更现代、更灵活的方式来处理响应,这使得代码更简洁、更易于维护。

Spring MVC 的核心思想是:控制器方法返回什么,框架就把它渲染成什么

核心处理方式

1 返回 String(视图名)

这是最常见的方式,返回的字符串会被 Spring 的视图解析器解析成一个具体的视图(如 JSP、Thymeleaf 模板等)。

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MyController {
    @GetMapping("/hello")
    public String sayHello() {
        // 返回 "hello" 字符串
        // 假设视图解析器配置为前缀 /WEB-INF/views/ 和后缀 .jsp
        // Spring 会尝试去 /WEB-INF/views/hello.jsp 寻找并渲染这个页面
        return "hello";
    }
}

2 返回 ModelAndView 对象

这是最传统、最灵活的 Spring MVC 方式。ModelAndView 对象可以同时携带数据和视图信息。

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class ModelAndViewController {
    @GetMapping("/user")
    public ModelAndView getUser() {
        ModelAndView mav = new ModelAndView();
        // 1. 设置视图名
        mav.setViewName("userProfile"); // 对应 userProfile.jsp
        // 2. 向模型中添加数据,这些数据可以在视图中访问
        mav.addObject("username", "李四");
        mav.addObject("email", "lisi@example.com");
        return mav;
    }
}

userProfile.jsp 中,你可以通过 ${username}${email} 来访问这些数据。

3 返回对象或集合(如 @ResponseBody

当我们想直接返回数据(如 JSON 或 XML)而不是渲染一个页面时,可以使用 @ResponseBody 注解,Spring 会自动将返回的对象序列化成 JSON 格式,并写入响应体。

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class JsonController {
    @GetMapping("/api/user")
    @ResponseBody // 告诉 Spring,这个方法的返回值直接写入响应体,不进行视图解析
    public User getUserAsJson() {
        User user = new User();
        user.setName("王五");
        user.setAge(25);
        return user;
    }
}

当访问 /api/user 时,浏览器会收到类似 {"name":"王五","age":25} 的 JSON 响应。

4 使用 ResponseEntity

ResponseEntity 是 Spring 提供的一个更强大的类,它允许你完全控制响应的状态码、头信息和体,这相当于对原始 HttpServletResponse 的高级封装。

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController // @RestController = @Controller + @ResponseBody
public class ResponseEntityController {
    @GetMapping("/api/custom-response")
    public ResponseEntity<String> getCustomResponse() {
        // 1. 设置响应体
        String body = "这是一个自定义的响应";
        // 2. 设置响应头
        org.springframework.http.HttpHeaders headers = new org.springframework.http.HttpHeaders();
        headers.add("Custom-Header", "MyValue");
        // 3. 创建 ResponseEntity,指定状态码、头信息和体
        // 返回 200 OK 状态码
        return new ResponseEntity<>(body, headers, HttpStatus.OK);
    }
    @GetMapping("/api/not-found")
    public ResponseEntity<String> getNotFoundResponse() {
        return new ResponseEntity<>("资源未找到", HttpStatus.NOT_FOUND);
    }
}

5 在方法参数中注入 HttpServletResponse

如果你确实需要直接操作原始的 response 对象(写入文件流),你也可以将其作为方法参数注入。

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Controller
public class DirectResponseController {
    @GetMapping("/download")
    @ResponseBody
    public void downloadFile(HttpServletResponse response) throws IOException {
        // 设置响应头,告诉浏览器这是一个文件下载
        response.setContentType("application/octet-stream");
        String headerKey = "Content-Disposition";
        String headerValue = "attachment; filename=\"example.txt\"";
        response.setHeader(headerKey, headerValue);
        // 写入文件内容
        response.getOutputStream().write("这是一个下载文件的内容".getBytes());
    }
}

总结与对比

特性 Servlet API (HttpServletResponse) Spring MVC
核心对象 javax.servlet.http.HttpServletResponse 无直接对象,通过返回值或 ModelAndViewResponseEntity 等控制
操作方式 命令式:response.setStatus(), response.setHeader(), response.getWriter().write() 声明式:通过方法的返回值、@ResponseBodyResponseEntity 来定义响应
响应体写入 直接获取 OutputStreamWriter 并写入 返回 POJO,框架自动序列化为 JSON/XML;或返回视图名,框架渲染页面
状态码/头信息 手动调用 setStatus()setHeader() ResponseEntity 中集中设置;或通过 @ResponseStatus 注解
重定向 response.sendRedirect() return "redirect:/new-url" (视图前缀)
适用场景 学习 Servlet 原理、简单项目、需要直接操作底层流的场景 几乎所有现代 Java Web 项目,特别是 RESTful API 和复杂应用
代码风格 较为繁琐,需要手动管理每个细节 更简洁、更面向对象,符合框架设计理念

  • Servlet API底层的、手动的构建响应的方式,你需要告诉服务器“一步一步该做什么”。
  • Spring MVC高层的、声明的构建响应的方式,你只需要告诉服务器“你想要什么结果”,框架会帮你处理好所有细节。

在现代开发中,除非你正在学习 Servlet 原理或处理一些非常特殊的底层需求,否则强烈推荐使用 Spring MVC 的方式,因为它能极大地提高开发效率和代码质量。

分享:
扫描分享到社交APP
上一篇
下一篇