[Request对象] 笔记

发布时间 2023-03-29 18:21:16作者: 李八御

Servlet 的继承体系

Tomcat需要解析请求数据,封装为request对象,并且创建request对象传递到service方法中

使用request对象,查阅JavaEE API文档的HttpServletRequest接口

img

request 获取请求数据

请求行

// 获取请求方式
String method = req.getMethod();
System.out.println("请求方法:" + method);

// 获取虚拟目录
String contextPath = req.getContextPath();
System.out.println("虚拟目录:" + contextPath);

// 获取 URL 统一资源定位器
StringBuffer requestURL = req.getRequestURL();
System.out.println("URL: " + requestURL.toString());

// 获取 URI 统一资源标识符
String requestURI = req.getRequestURI();
System.out.println("URI :" + requestURI);

// 获取请求参数
String queryString = req.getQueryString();
System.out.println("queryString: " + queryString);

img

img

请求头

// 获取请求头中的 user-agent
String userAgent = req.getHeader("user-agent");
System.out.println("user-agent = " + userAgent);

请求体

  • ServletInputStream getInputStream():获取字节输入流
  • BufferedReader getReader():获取字符输入流
// 字符形式 获取请求体中的参数
BufferedReader reqBody = req.getReader();
String reqPara = reqBody.readLine();
System.out.println(reqPara);

GET 使用 request.getQueryString() 方式
POST 使用 request.getReader() 方式

如果 doGet() 和 doPost() 方法中的业务代码相同,就需要写两份相同的代码,其中只有获取参数那一行不同。

所以提倡使用通用的方式获取参数,好在 HttpServletRequest 为我们做了这件事情

getParameterMap()
getParameterValues()
getParameter();
// 获取参数集合
Map<String, String[]> parameterMap = req.getParameterMap();
for (String key : parameterMap.keySet()) {
    System.out.print(key + ": ");

    String[] strings = parameterMap.get(key);
    for (String value : strings) {
        System.out.print(value + " ");
    }

    System.out.println();
}

// 获取参数数组
String[] hobbies = req.getParameterValues("hobby");
for (String hobby : hobbies) {
    System.out.print(hobby + " ");
}
System.out.println();

// 获取单个参数
String username = req.getParameter("username");
String password = req.getParameter("password");

System.out.println(username);
System.out.println(password);

用以上方法在 doGet() 和 doPost() 的效果是一样的

所以可以在 doGet 中写好代码在 doPost 中直接使用 this.doGet(); 即可


IDEA 配置自己的 Servlet 模板

img


request 参数中文乱码

POST 解决

// 解决 POST 中文乱码
// POST 底层是用 getReader() 读取的,所以设置流为 utf-8
request.setCharacterEncoding("UTF-8");
String username2 = request.getParameter("username");
System.out.println("username:" + username2);

GET 解决

乱码原因分析:

  • Browser 不支持中文,会把中文参数转换为 URL 编码如:%E5%36
  • 但是 Tomcat 解码 URL 使用 ISO-8859-1 方式解码
// 乱码产生并解决过程模拟
// 1. Browser URL 编码
String encode = URLEncoder.encode(username, "utf-8");
System.out.println(encode);

// 2. Tomcat 用 ISO-8859-1 解码
String isoDecode = URLDecoder.decode(encode, StandardCharsets.ISO_8859_1);
System.out.println(isoDecode);

// 3. 转化为字节数组
byte[] bytes = isoDecode.getBytes(StandardCharsets.ISO_8859_1);
for (byte aByte : bytes) {
    System.out.print(aByte + " ");
}
System.out.println();

// 4. 将字节数组转化为字符串
String byteString = new String(bytes, "utf-8");
System.out.println("byteString: " + byteString);

常用便捷方式

// 这一句即可替换上边的 3、4 步
username = new String(username.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);

学了半天,可惜:Tomcat8 会自动解决这个问题...

Tomcat8 将默认解码方式设置为了 UTF-8


request 转发请求

request.getRequestDispatcher("/target").forward(request, response);
void setAttribute("msg", "Hello"); // 存储数据
Object getAttribute("msg"); // 获取数据

转发请求的特点:

  • 浏览器地址栏路径不发生变化
  • 只能转发到当前服务器的内部资源
  • 一次请求,可以在转发的资源间使用request共享数据
// org.example.Servlet1 发起“请求转发”的Servlet
// 逻辑处理、存储数据
request.setAttribute("msg", "Hello");

// 请求转发, msg:Hello 会随着 request 对象被送到 sendtarget 对应的的Servlet
request.getRequestDispatcher("/sendtarget").forward(request, response);
// org.example.Servlet2 请求转发的目的 servlet
// 获取从servlet1那里设置好的参数
Object msg = request.getAttribute("msg"); 

response.setContentType("text/html");
response.getWriter().write("<h1>Hello Resend target!</h1>");
response.getWriter().write("<h1>msg:</h1>" + msg.toString());