Request详解
...大约 6 分钟
1. request对象和response对象的基本理解
- request和response对象是由服务器创建的。我们只是来使用它们;
- request对象的作用是获取请求消息,response对象的作用是设置响应消息。
2. request对象和response对象的原理
3. request对象继承体系结构
ServletRequest -- 接口
| 继承
HttpServletRequest -- 接口
| 实现
org.apache.catalina.connector.RequestFacade//该位置是实现HttpServletRequest接口中的request方法的位置。
tomcat源码下的实现类,打开看源码可以发现继承了HttpServletRequest接口。
4. request功能
主要可以获取请求消息数据,包括请求行、请求头、请求体的数据。
4.1. 获取请求行数据
此处示例的请求行的数据内容为GET /today/demo1?name=zhangsan HTTP/1.1
。
- 方法:
- 获取请求方式 :GET String getMethod()
- (重点)获取虚拟目录:/today String getContextPath()
- 获取Servlet路径: /demo1 String getServletPath()
经常在表单
action
的路径中用该方法,这样修改servlet路径后,会跟着变化,不用再去修改。
- 获取get方式请求参数:name=zhangsan String getQueryString()
- (重点)获取请求URI:/today/demo1 String getRequestURI():
/today/demo1
StringBuffer getRequestURL() :http://localhost/today/demo1
URL:统一资源定位符 :http://localhost/today/demo1
中华人民共和国 URI:统一资源标识符 :/today/demo1
共和国
URL和URI的区别:URL是全路径包含HTTP协议、IP地址、资源路径, URI是资源路径。
- 获取协议及版本:HTTP/1.1 String getProtocol()
- 获取客户机的IP地址: String getRemoteAddr()
重点掌握获取虚拟目录:/today 和获取请求URI:/today/demo1的方法。
4.2. 获取请求头数据
- 方法:
- (重点)
String getHeader(String name)
:通过请求头的名称获取请求头的值 Enumeration<String> getHeaderNames()
:获取所有的请求头名称
- (重点)
- 常用的请求头
User-Agent
浏览器告诉服务器,我访问你使用的浏览器版本信息。可以在服务器端获取该头的信息,解决浏览器的兼容性问题。
- Referer:
http://localhost:8080/today/login.html
告诉服务器,我(当前请求)从哪里来。 - 作用:- 防盗链,比如防止盗版网站直接使用正版链接作为外链;
- 统计工作,比如统计访问量。
4.3. 获取请求体数据
只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数。
- 步骤:
- 获取流对象; - BufferedReader getReader():获取字符输入流,只能操作字符数据; - ServletInputStream getInputStream():获取字节输入流,可以操作所有类型数据。
获取字节输入流,在后续学习文件上传知识点中讲解。
- 再从流对象中拿数据;
这里还需要创建一个login.html的表单页面将数据提交到RequestDemo5的虚拟路径/demo5中。
5. 其他功能
该部分介绍的功能都是很常用的方法。
5.1. 获取请求参数通用方式
不论get还是post请求方式都可以使用下列方法来获取请求参数,非常重要。
- 通用方式:
String getParameter(String name)
:根据参数名称获取参数值。username=zs&password=123
String[] getParameterValues(String name)
:根据参数名称获取参数值的数组,比如复选框的值。hobby=game&hobby=study
Enumeration<String> getParameterNames()
:获取所有请求的参数名称。Map<String,String[]> getParameterMap()
:获取所有参数的map集合。
- 代码部分:
<!--login.html-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>login</title>
</head>
<body>
<form action="/today/demo6" method="post">
<input type="text" name="username"><br>
<input type="text" name="password"><br>
<input type="checkbox" name="hobby" value="game">游戏
<input type="checkbox" name="hobby" value="study">学习<br>
<input type="submit" value="提交">
</form>
</body>
</html>
//RequestDemo6.java,其中去除了导包的代码
@WebServlet("/demo6")
public class RequestDemo6 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置编码
request.setCharacterEncoding("utf-8");
//post 获取请求参数
//1. 根据参数名称获取参数值
String username = request.getParameter("username");
System.out.println("1. post请求方式:"+username);//1. post请求方式:zhangsan
//2. 根据参数名称获取参数值大的数组
String[] hobbies = request.getParameterValues("hobby");
for (String hobby : hobbies) {
System.out.println("2. "+hobby);//2. game 2. study
}
//3. 获取所有请求的参数名称
Enumeration<String> parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements()){
String name = parameterNames.nextElement();
String value = request.getParameter(name);
System.out.println("3. "+name +":"+value);
//3. username:zhangsan 3. password:1234 3. hobby:game
//此处存在问题是复选框的值只打印了一个。
}
//4. 获取所有参数的map集合
Map<String, String[]> parameterMap = request.getParameterMap();
for (String key : parameterMap.keySet()) {
String name = key;
String[] values = parameterMap.get(name);
System.out.println("4. "+name+":"+ Arrays.toString(values));
//4. username:[zhangsan] 4. password:[1234] 4. hobby:[game, study]
//完美解决了复选框只打印一个值的问题
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
//get 获取请求参数
//根据参数名称获取参数值
String username = request.getParameter("username");
System.out.println("get请求方式:"+username);
*/
this.doPost(request,response);
}
}
- 中文乱码问题 tomcat 8 已经将get方式乱码问题解决了,但post方式还会乱码。
- 解决方法 在获取参数前,设置request的编码
request.setCharacterEncoding("utf-8");
。
- 解决方法 在获取参数前,设置request的编码
5.2. 请求转发
一种在服务器内部的资源跳转方式。
- 步骤:
- 通过request对象获取请求转发器对象:
RequestDispatcher getRequestDispatcher(String path)
; - 使用RequestDispatcher对象来进行转发:
forward(ServletRequest request, ServletResponse response)
。
- 通过request对象获取请求转发器对象:
- 特点:
- 浏览器地址栏路径不发生变化,状态码为200;
- 只能转发到当前服务器内部资源中,服务器外部的资源会报404;
- 转发只有一次请求,使用的只有demo7。
5.3. 共享数据
- 相关概念:
- 域对象:一个有作用范围的对象,可以在范围内共享数据;
- request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据。
- 方法:
- void setAttribute(String name,Object obj):存储数据;
- Object getAttitude(String name):通过键获取值;
- void removeAttribute(String name):通过键移除键值对。
一般只能用于请求转发中共享数据。
- 代码部分
@WebServlet("/demo7")
public class RequestDemo7 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("msg","hello");
System.out.println("demo7...");
request.getRequestDispatcher("/demo8").forward(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
@WebServlet("/demo8")
public class RequestDemo8 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Object msg = request.getAttribute("msg");
System.out.println("demo8...");
System.out.println(msg);//hello
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
ServletContext
5.4. 获取@WebServlet("/demo9")
public class RequestDemo9 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext servletContext = request.getServletContext();
System.out.println(servletContext);//这里只需了解获取servletContext
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
主要有获取MIME类型、域对象和获取文件的真实(服务器)路径。该部分功能放到后面部分详细讲解。