ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

JavaWeb保姆级教程:HttpServletRequest 一把梭!请求行/请求头/请求体三连击(附完整代码+运行截图)

JavaWeb保姆级教程:HttpServletRequest 一把梭!请求行/请求头/请求体三连击(附完整代码+运行截图)


🎬 博主名称:一鸣

🔥 个人专栏: 《苍穹外卖》《喜喜》
⛺️生活的理想,就是为了理想的生活!

文章目录

    • 今日实验目标(老师划的重点)
    • 一、先搞懂:HTTP 请求到底分几块?
    • 二、RequestDemo1:获取请求行 + 请求头
      • 2.1 在 myServlet 包下新建 RequestDemo1
      • 2.2 完整代码(直接抄)
      • 2.3 启动服务器,浏览器访问
      • 2.4 请求头:拿到浏览器版本
    • 三、RequestDemo2:获取请求体(POST 才有!)
      • ⚠️ 一个重要的坑
      • 3.1 整体思路
      • 3.2 第一步:在 web 目录下新建 register.html
      • 3.3 第二步:新建 RequestDemo2,在 doPost 里读请求体
      • 3.4 启动服务器,访问测试
    • 四、今日 API 速查表(建议截图保存)
    • 五、今日踩坑提醒(老师反复强调)
    • 六、写在最后

哈喽各位小伙伴,今天是我学 JavaWeb 的第 N 天,跟着老师把Request 对象从头到尾捋了一遍。
这玩意儿说简单也简单,说坑也真坑——GET 没请求体、POST 中文乱码、URI 和 URL 傻傻分不清楚……
这篇文章把我今天上课敲的所有代码、控制台截图、老师强调的重点全给你们整理出来了,看完直接能跑,建议先收藏再看!


今日实验目标(老师划的重点)

序号目标是否重点
1学会通过继承HttpServlet创建自己的 Servlet 类⭐
2知道doGet和doPost方法什么时候被调用⭐⭐
3知道如何在 Servlet 中获取 HTTP 请求参数、如何向用户发回响应⭐⭐
4解决请求和响应中的中文乱码问题⭐⭐⭐ 重点/难点
5知道如何把表单提交给一个 Servlet 处理⭐⭐
6知道如何在HttpServlet子类中获取ServletContext对象⭐

本次实验不用新建工程,直接在已经创建好的servletApp工程里搞就行。


一、先搞懂:HTTP 请求到底分几块?

浏览器给服务器发请求,本质上就是发了一坨文本。这坨文本一共分三部分:

┌─────────────────────────────────────────────┐ │ ① 请求行 (Request Line) │ ← GET /servletApp/RequestDemo1 HTTP/1.1 ├─────────────────────────────────────────────┤ │ ② 请求头 (Request Headers) │ ← User-Agent、Host、Accept... ├─────────────────────────────────────────────┤ │ ③ 请求体 (Request Body) │ ← 只有 POST 才有,GET 没有! │ username=xp&password=123 │ └─────────────────────────────────────────────┘

而HttpServletRequest对象,就是 Tomcat 把这坨文本封装好塞给你的一个 Java 对象——你想拿什么,调对应的方法就行。


二、RequestDemo1:获取请求行 + 请求头

2.1 在 myServlet 包下新建 RequestDemo1

操作步骤:

  1. 在myServlet文件夹上右键 → New → Servlet
  2. 类名输入:RequestDemo1
  3. 父类选HttpServlet,其他默认

2.2 完整代码(直接抄)

packagemyServlet;importjavax.servlet.ServletException;importjavax.servlet.annotation.WebServlet;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.io.IOException;/** * 使用 Request 获取请求行数据(GET 方式) * HttpServletRequest 对象用于封装客户端的请求信息 */@WebServlet("/RequestDemo1")publicclassRequestDemo1extendsHttpServlet{@OverrideprotectedvoiddoGet(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{System.out.println("访问 RequestDemo1");// 1. 获取请求行中的请求方法,例如 GET 或 POSTStringmethod=req.getMethod();System.out.println("Request Method: "+method);// 2. 获取虚拟目录(项目访问路径,在 Tomcat 里设置):例如 /servletAppStringcontextPath=req.getContextPath();System.out.println("Context Path: "+contextPath);// 3. 获取 Servlet 路径:/RequestDemo1StringservletPath=req.getServletPath();System.out.println("Servlet Path: "+servletPath);// 4. 获取请求行中的参数(GET 方式):?username=zhangsanStringqueryString=req.getQueryString();System.out.println("Query String: "+queryString);// 5. 获取请求 URL(统一资源定位符):// http://localhost:8080/servletApp/RequestDemo1StringrequestURL=req.getRequestURL().toString();System.out.println("Request URL: "+requestURL);// 6. 获取请求 URI(统一资源标识符):/servletApp/RequestDemo1StringrequestURI=req.getRequestURI();System.out.println("Request URI: "+requestURI);// 7. 获取请求头 user-agent:浏览器的版本信息Stringagent=req.getHeader("user-agent");System.out.println(agent);}@OverrideprotectedvoiddoPost(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{doGet(req,resp);}}

代码截图长这样(就是老师上课敲的版本)👇

2.3 启动服务器,浏览器访问

在浏览器地址栏输入:

http://localhost:8080/servletApp/RequestDemo1?username=zhangsan

控制台输出结果👇

我们来对着结果一行行读:

Request Method: GET ← 我是 GET 请求 Context Path: /servletApp ← 项目的虚拟目录 Servlet Path: /RequestDemo1 ← 我这个 Servlet 的路径 Request URL: http://localhost:8080/servletApp/RequestDemo1 ← 完整 URL Request URI: /servletApp/RequestDemo1 ← URI(没有协议和主机) Query String: username=zhangsan ← 问号后面那一串

URL 和 URI 的区别(面试必问):

  • URL= 协议 + 主机 + 端口 + 路径(能定位到一台具体的服务器资源)
  • URI= 路径部分(不包含协议、主机、端口),范围更大
  • 一句话:URL 是 URI 的子集,能当网址点的那个就是 URL。

2.4 请求头:拿到浏览器版本

// 获取请求头 user-agent:浏览器的版本信息Stringagent=req.getHeader("user-agent");System.out.println(agent);

重启服务后控制台会打印出类似这一串:

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36

这玩意儿有啥用?可以用来判断用户用的是 Chrome、Edge 还是手机浏览器,然后给不同的页面做适配。


三、RequestDemo2:获取请求体(POST 才有!)

⚠️ 一个重要的坑

GET 请求是没有请求体的!参数直接拼在 URL 后面(就是getQueryString()拿到的那串)。
想拿请求体,必须把请求方式改成POST。

3.1 整体思路

  1. 准备一个 HTML 页面,里面放一个<form>表单,用来发 POST 请求;
  2. 在 Servlet 的doPost方法里获取请求体数据;
  3. 用request.getReader()或者request.getInputStream()读出来;
  4. 启动服务器访问测试。

3.2 第一步:在 web 目录下新建 register.html

路径:WebContent/register.html(或者 Maven 工程里的webapp/register.html)

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>注册页面</title></head><body><!-- action: form 表单提交的请求地址 method: 请求方式,指定为 post --><formaction="/servletApp/RequestDemo2"method="post"><inputtype="text"name="username"><inputtype="password"name="password"><inputtype="submit"></form></body></html>

💡 划重点:

  • action里写的是Servlet 的访问路径,要跟@WebServlet里的一模一样;
  • method="post"一定要写,不写默认就是 GET;
  • 每个 input 的name属性就是后端拿到的参数名。

3.3 第二步:新建 RequestDemo2,在 doPost 里读请求体

packagemyServlet;importjavax.servlet.ServletException;importjavax.servlet.annotation.WebServlet;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.io.BufferedReader;importjava.io.IOException;/** * 使用 Request 获取请求体数据 * HttpServletRequest 对象用于封装客户端的请求信息 */@WebServlet("/RequestDemo2")publicclassRequestDemo2extendsHttpServlet{@OverrideprotectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{// 获取 post 请求体:请求参数// 1. 获取字符输入流BufferedReaderbr=request.getReader();// 2. 读取数据Stringline=br.readLine();System.out.println(line);}@OverrideprotectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{doPost(request,response);}}

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=images%2Fimage4.png&pos_id=img-N3tjipwk

🤔 为什么用getReader()而不是getInputStream()?

  • getReader():拿字符流,适合读文本(比如表单提交的username=xp&password=123);
  • getInputStream():拿字节流,适合读文件上传这种二进制数据。
    我们现在传的是纯文本,所以用getReader()就够了。

3.4 启动服务器,访问测试

浏览器打开:

http://localhost:8080/servletApp/register.html

在表单里随便输入(比如用户名xp、密码123),点提交。

控制台就会打印出:

username=xp&password=123

这就是请求体的原始模样——一行字符串,&分隔多个参数,=连接键值。


四、今日 API 速查表(建议截图保存)

方法作用示例返回值
req.getMethod()获取请求方式GET/POST
req.getContextPath()获取虚拟目录(项目路径)/servletApp
req.getServletPath()获取 Servlet 路径/RequestDemo1
req.getQueryString()获取 GET 请求参数串username=zhangsan
req.getRequestURL()获取完整 URL(StringBuffer)http://localhost:8080/servletApp/RequestDemo1
req.getRequestURI()获取 URI(不含协议主机)/servletApp/RequestDemo1
req.getHeader("User-Agent")获取指定请求头浏览器版本字符串
req.getReader()获取字符输入流(读请求体)BufferedReader
req.getInputStream()获取字节输入流(读文件等)ServletInputStream

五、今日踩坑提醒(老师反复强调)

  1. GET 没有请求体,getReader()/getInputStream()只能在 POST 里用;

  2. getRequestURL()返回的是StringBuffer,想打印一定要.toString();

  3. getQueryString()在没有参数时返回null,不是空字符串,判空要注意;

  4. 中文乱码是重难点:POST 提交中文参数时,记得在doPost第一行加:

    request.setCharacterEncoding("UTF-8");

    否则控制台拿到的可能是一坨???";

  5. 表单的action路径写错,404 找不到 Servlet,检查一下是不是少写了虚拟目录/servletApp。


六、写在最后

今天这节课其实就是一句话:浏览器发过来的所有东西,Tomcat 都封装进了request对象,你想拿啥就调啥方法。

  • 请求行 →getMethod / getContextPath / getRequestURI / getQueryString
  • 请求头 →getHeader("xxx")
  • 请求体 →getReader() / getInputStream()(POST 专属)

下节课老师要讲请求参数的通用获取方式(getParameter、getParameterMap),还有请求转发和响应重定向,咱们到时候继续肝!

如果这篇文章帮到你了,麻烦点赞 + 收藏 + 关注走一波,咱们下节课见 👋


标签:JavaWebServletHttpServletRequestRequestJava后端学习笔记乱码

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进