目录
HttpServletRequest基本概述
javax.servlet.http.HttpServletRequest是SUN制定的Servlet规范,是一个接口,表示请求, 其父接口是 javax.servlet.ServletRequest。“ HTTP 请求协议”的完整内容都被封装到 request对象中。
程序员只需要面向 HttpServletRequest 接口调用方法即可。
请求的生命周期
HttpServletRequest 实例对象是什么时候创建和销毁的呢?
当客户端浏览器将请求(字符序列)发送到服务器后,服务器会根据 HTTP 请求协议的 格式对请求进行解析。同时,服务器会创建 HttpServletRequest 的实现类 RequestFacade 的对 象,即请求对象。然后再调用相应的 set 方法,将解析出的数据封装到请求对象中。此时 HttpServletRequest 实例就创建并初始化完毕了。也就是说,请求对象是由服务器创建。
当服务器向客户端发送响应结束后,HttpServletRequest 实例对象被服务器销毁。
一次请求对应一个请求对象,另外一次请求对应另外一个请求对象,与之前的请求对象 没有任何关系。
HttpServletRequest 实例的生命周期很短暂。
中文乱码解决方法
解决POST提交方式的乱码问题
解决GET提交方式的乱码问题(缺点:tomcat同时运行多个项目的话,中途添加URIEncoding,项目需重启)
在tomcat的serve.xml中,添加URIEncoding
同时解决GET和POST提交方式的乱码问题(缺点:中文参数个数多的话,代码也会随之增多)
请求参数的4个常用方法
HttpServletRequest对于请求中所携带的参数是以Map的形式接收的,并且该Map的key 为 String,value 为 String 数组。为什么是String数组而不是String呢?因为Http请求协议允许一个请求参数具有多个值 的情况出现。例如表单中的复选框 hobby 的值就可能是多个。
Map<String,String[]> getParameterMap() 获取包含所有请求参数及值的 Map 对象。需要注意,该 Map 的 value 为 String[],即个参数所对应的值为一个数组。说明一个参数可以对应多个值。
Enumeration<String> getParameterNames() 获取请求参数 Map 的所有 key,即获取所有请求参数名 name。
String[] getParameterValues(String name) 根据指定的请求参数名称,获取其对应的所有值。这个方法一般用于获取复选框数据。
String getParameter(String name) 根据指定的请求参数名称,获取其对应的值。若该参数名称对应的是多个值,则该方法 获取到的是第一个值。这个方法是最常用的方法。
register.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="register" method="post">
姓名:<input type="text" name="uname"/><br/>
年龄:<input type="text" name="uage"/><br/>
爱好:<input type="checkbox" name="hobby" value="sing">唱
<input type="checkbox" name="hobby" value="dancing">跳
<input type="checkbox" name="hobby" value="rap">rap
<input type="checkbox" name="hobby" value="basketball">篮球<br/>
<input type="submit" value="注册">
</form>
</body>
</html>
RegisterServlet.java
package com.orbit.servlet;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class RegisterServlet
*/
@WebServlet("/register")
public class RegisterServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//使用request.getParameter(String)获取单个请求参数
//request.getParameter(String),本质上等同于request.getParameterValues(String)[0]
String uname = request.getParameter("uname");
String uageStr = request.getParameter("uage");
String uname1 = request.getParameterValues("uname")[0];
Integer uage = Integer.valueOf(uageStr);
System.out.println("uname="+uname);
System.out.println("uage="+uage);
System.out.println("=====================");
//使用request.getParameterNames()获取所有请求参数
//获取所有请求参数名称
Enumeration<String> names = request.getParameterNames();
while(names.hasMoreElements()) {
//获取参数名
String name = names.nextElement();
//获取参数值
String value = request.getParameter(name);
System.out.println(name + "=" + value);
}
System.out.println("=====================");
//获取指定参数的所有参数值
String[] hobbys = request.getParameterValues("hobby");
System.out.print("hobby=");
for(String hobby:hobbys) {
System.out.print(hobby+ " ");
}
System.out.println();
System.out.println("=====================");
//获取存放请求参数的Map
Map<String, String[]> map = request.getParameterMap();
for (String key : map.keySet()) {
String kvalue = request.getParameter(key);
System.out.println(key + "=" + kvalue);
}
}
}
域属性的4个常用方法
在 Request 中也存在域属性空间,用于存放有名称的数据。该数据只在当前Request请求中可以进行访问。
void setAttribute(String name, Object object): 在 Request 域属性空间中放入数据。其生命周期与 Request 的生命周期相同。
Object getAttribute(String name): 从 Request 的域属性空间中获取指定名称的数据。
Enumeration<String> getAttributeNames():返回包含此请求可用属性的名称的枚举。如果请求没有可用的属性,则此方法返回空枚举。
void removeAttribute(String name): 从 Request 的域属性空间中删除指定名称的数据。
RequestDispatcher getRequestDispatcher(String path); 该方法用于创建请求转发器,而该请求转发器有一个方法 forward(),用于完成将请求对 象转发给下一个资源。
forward()方法的原型如下: void forward(HttpServletRequest request, HttpServletResponse response);
SomeServlet.java
package com.orbit.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class SomeServlet
*/
@WebServlet("/some")
public class SomeServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//在请求的域属性空间中放入数据
request.setAttribute("scene", "故宫");
request.setAttribute("place", "北京");
request.setAttribute("time", "2019");
//删除请求的域属性空间中指定域属性的数据
request.removeAttribute("time");
//将请求转发给OtherServlet,实现了跨Servlet的数据通信
request.getRequestDispatcher("/other").forward(request, response);
}
}
OtherServlet.java
package com.orbit.servlet;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class OtherServlet
*/
@WebServlet("/other")
public class OtherServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//从请求的域属性空间中获取指定域属性的数据
String scene = (String) request.getAttribute("scene");
String place = (String) request.getAttribute("place");
String time = (String) request.getAttribute("time");
System.out.println("scene:"+scene);
System.out.println("place:"+place);
System.out.println("time:"+time);
//获取请求的域属性空间中所有的域属性名
Enumeration<String> names = request.getAttributeNames();
while(names.hasMoreElements()) {
String name = names.nextElement();
System.out.println( name+" = "+ request.getAttribute(name));
}
}
}
控制台结果:
其他常用方法
StringBuffer getRequestURL(): 获取请求的 URL。即从请求协议开始的绝对路径。
String getRequestURI(): 获取请求的 URI,即从项目名称开始的请求路径。(URL去掉请求协议和主机后的剩余部分)
String getContextPath(): 获取上下文路径,即当前应用在 Web 容器中的名称
String getServletPath() :获取url-Pattern的精确部分
String getPathInfo():获取url-Pattern的非精确部分
String getMethod(): 获取请求方式,是 GET 请求,还是 POST 请求
String getRemoteAddr(): 获取远程地址,即客户端浏览器的 IP
FirstServlet.java
package com.orbit.HttpRequestServlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(urlPatterns={"/first","/first/test/*"}) //可用多个映射访问该Servlet
public class FirstServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//获取远程地址(客户端IP)
String clientIP = request.getRemoteAddr();
System.out.println("clientIP = " + clientIP);
//获取该请求的URL
StringBuffer requestURL = request.getRequestURL();
System.out.println("requestURL = "+ requestURL);
//获取该请求的URI(即URL去掉请求协议和主机后的剩余部分)
String requestURI = request.getRequestURI();
System.out.println("requestURI = " + requestURI);
//获取当前Web应用的根路径
String contextPath = request.getContextPath();
System.out.println("contextPath = " + contextPath);
//获取url-Pattern的精确部分
String servletPath = request.getServletPath();
System.out.println("servletPath = " + servletPath);
//获取url-Pattern的非精确部分
String pathInfo = request.getPathInfo();
System.out.println("pathInfo = " + pathInfo);
}
}
测试结果