Servlet-获取请求参数

Servlet-获取请求参数

classDiagram
ServletRequest <|-- HttpServletRequest : 继承
HttpServletRequest <|.. RequestFacade : 实现
note for ServletRequest "Java提供的请求对象根接口"
note for HttpServletRequest "Java提供的对Http协议封装的请求对象接口"
note for RequestFacade "Tomcat定义的实现类"

Tomcat 会把一条 HTTP 请求解析成 HttpServletRequest 对象,并把它传给 service/doGet/doPost。你在 Servlet 里做的“获取请求参数/请求头/请求体”,本质上都是从这个对象读取解析后的结果(对应 HTTP请求报文)。

先分清:请求参数 vs 其它请求数据

如果请求体是 JSON(application/json),getParameter 往往拿不到数据,需要你读取请求体并解析(见 Ajax / Request & Response)。

Request 获取请求数据功能的介绍

Request获取请求数据功能的介绍

请求数据的格式:HTTP请求报文

  1. 请求行:GET/request-demo/req1?username=zhangsan HTTP/1.1
    1. String getMethod(): 获取请求方式:GET
    2. String getContextPath(): 获取虚拟目录(项目访问路径):/request-demo
    3. StringBuffer getRequestURL(): 获取URL(统一资源定位符): http://localhost:8080/request-demo/req1
    4. String getRequestURI(): 获取URL(统一资源标识符): /request-demo/req1
    5. String getQueryString(): 获取请求参数(GET方式): usename=zhangsan&password=13
  2. 请求头:User-Agent: Mozilla/5.0 Chrome/91.0.4472.106
    1. String getHeader(String name): 根据请求头名称,获取值
  3. 请求体:username=superbaby&password=123
    1. BufferedReader getReader(): 获取字符输入流
    2. ServletInputStream getInputStream(): 获取字节输入流

参数获取的“推荐入口”

对于大多数表单提交(GET/POST),优先使用下面三组 API:

这些方法统一了 GET QueryString 与 application/x-www-form-urlencoded 的 POST 表单读取逻辑,通常不需要你手动读取请求体。

@WebServlet("/req1")
public class RequestDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // String getMethod(): 获取请求方式:GET
        String method = req.getMethod();
        System.out.println(method); //GET
        // String getContextPath(): 获取虚拟目录(项目访问路径):/request-demo
        String contextPath = req.getContextPath();
        System.out.println(contextPath);
        // StringBuffer getRequestURL(): 获取URL(统一资源定位符): http://localhost:8080/request-demo/req1
        StringBuffer url = req.getRequestURL();
        System.out.println(url.toString());
        // String getRequestURI(): 获取URI(统一资源标识符): /request-demo/req1
        String uri = req.getRequestURI();
        System.out.println(uri);
        // String getQueryString(): 获取请求参数(GET方式): usename=zhangsan&password=13
        String queryString = req.getQueryString();
        System.out.println(queryString);

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

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取post请求体: 请求参数
        // 1. 获取字符输入流
        BufferedReader br = req.getReader();
        // 2. 读取数据
        String line = br.readLine();
        System.out.println(line);
    }
}

常见坑与边界

  1. 读取请求体是“一次性”的:你调用了 getReader/getInputStream 自己读完 Body 后,再去调用 getParameter,可能已经没有可解析的内容
  2. 处理 POST 中文乱码:必须在第一次读取参数/请求体之前设置 request.setCharacterEncoding("UTF-8")(见 Servlet-请求参数中文乱码解决方式
  3. 文件上传(multipart/form-data)不是普通参数:不能用 getParameter 当作通用方案,需要用 Multipart 的方式解析(关联:资源的上传与下载
  4. 路径与参数不要混用:路由信息优先用 getRequestURI/getContextPath 处理,业务入参用 getParameter 处理(关联:请求路径的问题