HTTP请求信息数据-Request

接着上篇博文 《HTTP:超文本传输协议》 的学习。

现在,来学习两个对象:Request & Response。

request对象和response对象的原理

  1. request和response对象是由服务器创建的。接着我们来使用它们
  2. request对象是来获取请求消息,response对象是来设置响应消息
  3. 其基本原理,如下图????

HTTP请求信息数据-Request

request对象继承体系结构

ServletRequest – interface,接口

↓|继承

HttpServletRequest – interface,接口

↓|实现

org.apache.catalina.connector.RequestFacade – 类,Tomcat编写的

Tomcat 是用纯Java语言编写

request功能

  1. 基础功能
    • 获取请求消息数据
  2. 其他功能:
    • 1.获取请求参数通用方式
    • 2.请求转发
    • 3.共享数据
    • 4.获取ServletContext

获取请求消息数据

  1. 获取请求行数据
  2. 获取请求头数据
  3. 获取请求体数据
  1. 获取请求消息数据的字符串格式 ????
1
2
3
4
5
6
7
8
9
10
11
POST /login.html	HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://localhost/login.html
Connection: keep-alive
Upgrade-Insecure-Requests: 1

username=zhangsan

一.获取请求行数据

1
GET  /day14/demo1?name=zhangsan  HTTP/1.1

调用方法(★★重点掌握):

  1. 获取请求方式:GET
  • String getMethod()
  1. ★★获取虚拟目录:/day14
  • String getContextPath()
  1. 获取Servlet路径:/demo1
  • String getServletPath()
  1. 获取get方式请求参数:name=zhangsan
  • String getQueryString()
  • 不用这个,以后会用更高级的方式
  • 多个参数之间用&连接
  1. ★★获取请求URI:/day14/demo1
  • String getRequestURI():/day14/demo1

  • StringBuffer getRequestURL()http://localhost/day14/demo1

    • URL:统一资源定位符http://localhost/day14/demo1 其地位相当于”*”

    • URI:统一资源标识符,其表示范围更大 :/day14/demo1 其地位相当于”*”

  1. 获取协议及版本:HTTP/1.1
  • String getProtocol()

  • 该方法在Interface ServletRequest

  1. 获取客户机的IP地址:
  • String getRemoteAddr()

  • 该方法在Interface ServletRequest

示例

新建RequestDemo1.java,输入代码????

可以在新建时候选择创建Servlet,IDEA自动生成相应模板。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
* 演示Request对象获取请求行数据
*/

@WebServlet("/RequestDemo1")
public class RequestDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
1. 获取请求方式 :GET
* String getMethod()
2. (*)获取虚拟目录:/Servlet
* String getContextPath()
3. 获取Servlet路径: /requestDemo1
* String getServletPath()
4. 获取get方式请求参数:name=zhangsan
* String getQueryString()
5. (*)获取请求URI:/Servlet/requestDemo1
* String getRequestURI(): /day14/requestDemo1
* StringBuffer getRequestURL() :http://localhost/Servlet/requestDemo1
6. 获取协议及版本:HTTP/1.1
* String getProtocol()

7. 获取客户机的IP地址:
* String getRemoteAddr()

*/
//1. 获取请求方式 :GET
String method = request.getMethod();
System.out.println(method);
//2.(*)获取虚拟目录:/day14
String contextPath = request.getContextPath();
System.out.println(contextPath);
//3. 获取Servlet路径: /demo1
String servletPath = request.getServletPath();
System.out.println(servletPath);
//4. 获取get方式请求参数:name=zhangsan
String queryString = request.getQueryString();
System.out.println(queryString);
//5.(*)获取请求URI:/day14/demo1
String requestURI = request.getRequestURI();
StringBuffer requestURL = request.getRequestURL();
System.out.println(requestURI);
System.out.println(requestURL);
//6. 获取协议及版本:HTTP/1.1
String protocol = request.getProtocol();
System.out.println(protocol);
//7. 获取客户机的IP地址:
String remoteAddr = request.getRemoteAddr();
System.out.println(remoteAddr);
}
}

演示????

浏览器访问:http://localhost/Servlet/RequestDemo1?name=zhangsan

IDEA控制台输出:

HTTP请求信息数据-Request

二.获取请求头数据

1
2
3
4
5
6
7
8
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://localhost/login.html
Connection: keep-alive
Upgrade-Insecure-Requests: 1

调用方法(★★重点掌握):

  1. ★★String getHeader(String name)
  • 通过请求头的名称获取请求头的值
  • 参数不分大小写,只要单词拼写的对即可
  1. Enumeration<String> getHeaderNames()
  • 获取所有的请求头名称
  • 封装成 Enumeration<String>

注意:从JDK1.0开始,该接口的功能由Iterator(迭代器)接口 复制。此外,Iterator还添加了一个可选的删除操作,并且有较短的方法名称。新的实现应该考虑使用迭代器优选于枚举。——JDK 8 文档

示例

一、调用Enumeration<String> getHeaderNames(),演示获取所有请求头数据

  1. 新建一个Servlet,名为RequestDemo2.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;

@WebServlet("/RequestDemo2")
public class RequestDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 演示获取请求头数据

// 1.获取所有请求头数据
Enumeration<String> headerNames = request.getHeaderNames();
// 2.遍历
while(headerNames.hasMoreElements()){
String name = headerNames.nextElement();
// 根据名称获取请求头的值
String value = request.getHeader(name);
System.out.println(name + "--" + value);
}

}
}
  1. 浏览器访问:http://localhost/Servlet/RequestDemo2
  2. IDEA控制台输出:

HTTP请求信息数据-Request

二、调用String getHeader(String name),user-agent、referer

  1. 新建一个Servlet,名为RequestDemo3.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/RequestDemo3")
public class RequestDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 演示获取请求头数据:user-agent(客户端版本)

// 获取请求头数据:user-agent
String agent = request.getHeader("user-agent");
// 判断agent的浏览器版本,可以解决浏览器兼容问题
if(agent.contains("Chrome")) {
// 谷歌浏览器
System.out.println("谷歌来了。。。");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
System.out.println("火狐来了。。。");
}

}
}
  1. 浏览器访问:http://localhost/Servlet/RequestDemo3
  2. IDEA控制台输出:

HTTP请求信息数据-Request

注意:

获取请求头数据:user-agent(客户端版本)

判断agent的浏览器版本,可以解决浏览器兼容问题

  1. 新建一个Servlet,名为RequestDemo4.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/RequestDemo4")
public class RequestDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 演示请求头数据:referer
String referer = request.getHeader("referer");
System.out.println(referer); // http://localhost/Servlet/login.html

//防盗链
if(referer != null) {
if(referer.contains("/Servlet")) {
// 正常访问
System.out.println("播放电影。。。");
/* 等同于,只不过不再是输出到控制台,而是直接打印在页面上
response.setContentType("text/html;charset=utf-8");
response.getWriter.writer("播放电影。。。")
*/
} else {
// 盗链
System.out.println("想看电影吗?来优酷吧。。。");
/* 等同于,只不过不再是输出到控制台,而是直接打印在页面上
response.setContentType("text/html;charset=utf-8");
response.getWriter.writer("想看电影吗?来优酷吧。。。")
*/
}
}
}
}
  1. 新建一个html文件,名为login.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>表单</title>
</head>
<body>
<form action="/Servlet/Demo3" method="get">
<input name="username">
<input type="submit" value="提交">
</form>

<!--加入超链接-->
<a href="http://localhost/Servlet/RequestDemo4">RequestDemo3</a>

</body>
</html>
  1. 演示????获取请求头数据:referer

HTTP请求信息数据-Request

  1. 关于获取referer来防盗链,观看 视频(进度条【10:56】)

三.获取请求体数据

1
username=zhangsan
  • 请求体:只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数

  • 步骤:

    1. 获取流对象
      • 获取字符输入流:文字等字符数据
      • 获取字节输入流:上传图片、文件等字节数据
    2. 再从流对象中获取数据

调用方法:

  1. BufferedReader getReader()
  • 获取字符输入流,只能操作字符数据

  • 返回值是BufferedReader高效的、带有缓冲区的

  • 该方法在Interface ServletRequest

  1. ServletInputStream getInputStream()
  • 获取字节输入流,可以操作所有类型数据

  • 但是获取字符时不方便,更推荐用第一个调用方法

  • 返回值是ServletInputStream继承了InputStream

  • 涉及到文件上传等知识

  • 该方法在Interface ServletRequest

示例

  1. 新建html文件,名为regist.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册页面</title>
</head>
<body>

<form action="/Servlet/RequestDemo5" method="post">
<input type="text" placeholder="请输入用户名" name="username"><br>
<input type="text" placeholder="请输入密码" name="password"><br>
<input type="submit" value="注册">

</form>

</body>
</html>
  1. 新建一个Servlet,名为RequestDemo5.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;

@WebServlet("/RequestDemo5")
public class RequestDemo5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求消息体--请求参数

//1.获取字符流
BufferedReader br = request.getReader();
//2.读取数据
String line = null;
while((line = br.readLine()) != null){
System.out.println(line);
}
br.close();
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
  1. 浏览器访问:http://localhost/Servlet/regist.html
  2. 控制台输出:

HTTP请求信息数据-Request

注意:多个参数之间用&连接。

其他功能

  1. 获取请求参数通用方式

  2. 请求转发

  3. 共享数据

一、获取请求参数通用方式

  • 不论GET还是POST请求方式都可以使用下列方法来获取请求参数
  • 上述即,doGet()doPost() 的方法体代码完全一样
  • 因此,为了简化,只需要选择在doPost() 的方法体中写代码,之后在doGet()调用 this.doPost(request,response);

调用方法:

  1. String getParameter(String name)
  • 根据参数名称获取参数值: username=zs&password=123
  1. String[] getParameterValues(String name)
  • 根据参数名称获取参数值的数组:hobby=xuexi&hobby=game
  • 将键值对,按一个来封装不同的值并封装成一个数组
  • 多用于复选框
  1. Enumeration<String> getParameterNames()
  • 获取所有请求的参数名称
  1. Map<String,String[]> getParameterMap()
  • 获取所有参数的Map集合

示例

  1. 新建regist2.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册页面</title>
</head>
<body>

<form action="/Servlet/RequestDemo6" method="post">
<input type="text" placeholder="请输入用户名" name="username"><br>
<input type="text" placeholder="请输入密码" 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>
  1. 新建RequestDemo6.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;

@WebServlet("/RequestDemo6")
public class RequestDemo6 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//post 获取请求参数

//根据参数名称获取参数值
String username = request.getParameter("username");
/* System.out.println("post");
System.out.println(username);*/

//根据参数名称获取参数值的数组
String[] hobbies = request.getParameterValues("hobby");
/*for (String hobby : hobbies) {
System.out.println(hobby);
}*/

//获取所有请求的参数名称

Enumeration<String> parameterNames = request.getParameterNames();
/*while(parameterNames.hasMoreElements()){
String name = parameterNames.nextElement();
System.out.println(name);
String value = request.getParameter(name);
System.out.println(value);
System.out.println("----------------");
}*/

// 获取所有参数的map集合
Map<String, String[]> parameterMap = request.getParameterMap();
//遍历
Set<String> keyset = parameterMap.keySet();
for (String name : keyset) {

//获取键获取值
String[] values = parameterMap.get(name);
System.out.println(name);
for (String value : values) {
System.out.println(value);
}

System.out.println("-----------------");
}

}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//get 获取请求参数
/*
//根据参数名称获取参数值
String username = request.getParameter("username");
System.out.println("get");
System.out.println(username);*/

this.doPost(request,response);
}
}
  1. 浏览器访问:http://localhost/Servlet/regist2.html

  2. 控制台输出:

HTTP请求信息数据-Request

中文乱码问题

  1. GET方式:tomcat 8 已经将 GET方式乱码问题解决了
  2. POST方式:会乱码
  • 解决:在获取参数前,设置request的编码request.setCharacterEncoding("utf-8"); 。对应着html页面的编码。

二、请求转发

  • 一种在服务器内部的资源跳转方式

HTTP请求信息数据-Request

特点

  1. 浏览器地址栏路径不发生变化

  2. 只能转发到当前服务器内部资源中

  3. 转发就是一次请求。像上图的AServlet和BServlet两种资源使用的是同一次请求。

步骤

  1. 通过request对象获取请求转发器对象
  • RequestDispatcher getRequestDispatcher(String path)
  1. 使用RequestDispatcher对象来进行转发
  • forward(ServletRequest request, ServletResponse response)

示例

  1. 新建RequestDemo8.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/RequestDemo8")
public class RequestDemo8 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Demo8888被访问了。。。");
//转发到Demo9资源
/*
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/RequestDemo9");
requestDispatcher.forward(request,response);
// 一般不这么写,直接写成:
request.getRequestDispatcher("/RequestDemo9").forward(request,response);
*/

//存储数据到request域中
request.setAttribute("msg","hello");

request.getRequestDispatcher("/RequestDemo9").forward(request,response);
//没法跳转到外部资源,比如下面这个是不行的
//request.getRequestDispatcher("http://www.itcast.cn").forward(request,response);

}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doPost(request,response);
}
}
  1. 新建RequestDemo9.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/RequestDemo9")
public class RequestDemo9 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//获取数据
Object msg = request.getAttribute("msg");
System.out.println(msg);

System.out.println("Demo9999也被访问了。。。");

}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doPost(request,response);
}
}
  1. 浏览器访问:http://localhost/Servlet/RequestDemo8
  2. 控制台输出:

HTTP请求信息数据-Request

三、共享数据

  • 域对象:一个有作用范围的对象,可以在范围内共享数据
  • request域:代表一次请求的范围,一般用于请求转发的多个资源*享数据

调用方法:

  1. void setAttribute(String name,Object obj)
  • 存储数据
  1. Object getAttitude(String n
  2. ame)
  • 通过获取
  1. void removeAttribute(String name)
  • 通过移除键值对

????视频 的【03:15】,详细说到 如何共享数据

示例

示例放在 __ 请求转发 的示例 __ 中。

详细见代码文件中的两个注释:

RequestDemo8的【// 存储数据到request域中】

RequestDemo9的【// 获取数据】

HTTP请求信息数据-Request

四、获取ServletContext

调用方法:

  • ServletContext getServletContext()

示例

  1. 新建RequestDemo10.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/RequestDemo10")
public class RequestDemo10 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {


ServletContext servletContext = request.getServletContext();

System.out.println(servletContext);

}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doPost(request,response);
}
}
  1. 浏览器访问:http://localhost/Servlet/RequestDemo10
  2. 控制台输出:

HTTP请求信息数据-Request


下篇博客 《HTTP响应信息数据 - Response》 中,详细学习响应信息数据 - Response