Skip to content

04-Request 与 Response

对应原始资料:day06-Request+Response

一、HttpServletRequest

代表一次 HTTP 请求,由 Tomcat 创建并传入 Servlet。

1. 获取请求行 / 头 / 参数

java
// 请求行
req.getMethod();            // GET / POST
req.getRequestURI();        // /demo/hello
req.getRequestURL();        // http://localhost:8080/demo/hello
req.getQueryString();       // id=1&name=zs
req.getProtocol();

// 请求头
req.getHeader("User-Agent");
req.getHeaderNames();

// 请求参数(GET 的 query string 和 POST 的 body 都可用)
String name = req.getParameter("name");
String[] hobbies = req.getParameterValues("hobby");
Map<String, String[]> map = req.getParameterMap();

2. 中文乱码问题

  • GET:Tomcat 8+ 已自动处理 UTF-8。
  • POST:必须手动设置:
java
req.setCharacterEncoding("UTF-8");   // 必须在 getParameter 之前
  • 响应resp.setContentType("text/html;charset=UTF-8");

3. 请求转发(forward)

java
req.setAttribute("msg", "hello");
req.getRequestDispatcher("/result.jsp").forward(req, resp);

特点:

  • 一次请求,地址栏不变。
  • 转发的资源共享同一个 request
  • 只能转发到服务器内部资源。

4. BeanUtils 封装参数

java
User u = new User();
BeanUtils.populate(u, req.getParameterMap());   // 把 map 自动赋给对象属性

二、HttpServletResponse

代表一次 HTTP 响应。

1. 输出内容

java
// 字符流(输出文本)
resp.setContentType("text/html;charset=UTF-8");
PrintWriter w = resp.getWriter();
w.write("<h1>hello</h1>");

// 字节流(输出二进制,如文件下载、图片)
ServletOutputStream os = resp.getOutputStream();

2. 重定向(redirect)

java
resp.sendRedirect("/demo/index.html");

特点:

  • 两次请求,地址栏变化。
  • 不共享 request 域。
  • 可重定向到外部网站。

3. 转发 vs 重定向

维度转发 forward重定向 redirect
请求次数12
地址栏不变
域对象共享不共享
目标范围服务器内任意 URL

三、文件下载

java
@WebServlet("/download")
public class DownloadServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        String filename = "a.jpg";
        String path = getServletContext().getRealPath("/img/" + filename);
        FileInputStream fis = new FileInputStream(path);

        // 设置响应头,告诉浏览器以下载方式打开
        resp.setHeader("Content-Disposition", "attachment;filename=" + filename);

        ServletOutputStream os = resp.getOutputStream();
        byte[] buf = new byte[8192];
        int len;
        while ((len = fis.read(buf)) != -1) os.write(buf, 0, len);
        fis.close();
    }
}

中文文件名乱码(IE/Chrome)

java
filename = URLEncoder.encode(filename, "UTF-8");

四、文件上传

1. 前端

html
<form action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file">
    <input type="submit">
</form>

2. 后端(Servlet 3.0 注解)

java
@MultipartConfig
@WebServlet("/upload")
public class UploadServlet extends HttpServlet {
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        req.setCharacterEncoding("UTF-8");
        Part part = req.getPart("file");
        String name = part.getSubmittedFileName();
        part.write(getServletContext().getRealPath("/upload/") + name);
    }
}

五、JSON 响应

后端常用 Jackson 或 Fastjson 把对象转成 JSON 返回:

java
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(user);
resp.setContentType("application/json;charset=UTF-8");
resp.getWriter().write(json);

六、综合思路:原生 Servlet + Vue

  1. 前端 Vue + axios 调用 /api/user
  2. 后端 Servlet 用 getPart / getParameter 取参数。
  3. 业务层调用 JDBC。
  4. 用 Jackson 把结果转 JSON 写回。
  5. 前端 axios 拿到 JSON 后渲染。

这就是 SpringMVC 在背后做的事——Servlet 是底层引擎,框架帮你做了参数提取、JSON 转换、路由分发。

练习建议

  1. 用 Servlet 接收表单参数并输出到页面。
  2. 实现转发到 success.jsp,对比重定向。
  3. 实现图片下载(带中文文件名)。
  4. @MultipartConfig 实现文件上传,把文件保存到 /upload
  5. 用 Jackson 返回一个对象,前端用 axios 接收。