接着上篇博文 《HTTP:超文本传输协议》 的学习。
现在,来学习两个对象:Request & Response。
request对象和response对象的原理
-
request和response对象是由服务器创建的。接着我们来使用它们
- request对象是来获取请求消息,response对象是来设置响应消息
- 其基本原理,如下图????
request对象继承体系结构
ServletRequest
– interface,接口
↓|继承
HttpServletRequest
– interface,接口
↓|实现
org.apache.catalina.connector.RequestFacade
– 类,Tomcat编写的
Tomcat 是用纯Java语言编写的
request功能
- 基础功能
- 其他功能:
- 1.获取请求参数通用方式
- 2.请求转发
- 3.共享数据
- 4.获取ServletContext
获取请求消息数据
- 获取请求行数据
- 获取请求头数据
- 获取请求体数据
- 获取请求消息数据的字符串格式 ????
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
|
调用方法(★★重点掌握):
- 获取请求方式:GET
- ★★获取虚拟目录:/day14
- 获取Servlet路径:/demo1
- 获取get方式请求参数:name=zhangsan
String getQueryString()
- 不用这个,以后会用更高级的方式
- 多个参数之间用
&
连接
- ★★获取请求URI:/day14/demo1
- 获取协议及版本:HTTP/1.1
-
String getProtocol()
-
该方法在Interface ServletRequest
中
- 获取客户机的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控制台输出:
二.获取请求头数据
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
|
调用方法(★★重点掌握):
- ★★
String getHeader(String name)
- 通过请求头的名称获取请求头的值
- 参数不分大小写,只要单词拼写的对即可
Enumeration<String> getHeaderNames()
- 获取所有的请求头名称
- 封装成
Enumeration<String>
注意:从JDK1.0开始,该接口的功能由Iterator(迭代器)接口 复制。此外,Iterator还添加了一个可选的删除操作,并且有较短的方法名称。新的实现应该考虑使用迭代器优选于枚举。——JDK 8 文档
示例
一、调用Enumeration<String> getHeaderNames()
,演示获取所有请求头数据
- 新建一个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); }
} }
|
- 浏览器访问:http://localhost/Servlet/RequestDemo2
- IDEA控制台输出:
二、调用String getHeader(String name)
,user-agent、referer
- 新建一个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("火狐来了。。。"); } } }
|
- 浏览器访问:http://localhost/Servlet/RequestDemo3
- IDEA控制台输出:
注意:
获取请求头数据:user-agent(客户端版本)
判断agent的浏览器版本,可以解决浏览器兼容问题
- 新建一个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("想看电影吗?来优酷吧。。。") */ } } } }
|
- 新建一个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>
|
- 演示????获取请求头数据:referer
- 关于获取referer来防盗链,观看 视频(进度条【10:56】)
三.获取请求体数据
调用方法:
BufferedReader getReader()
ServletInputStream getInputStream()
示例
- 新建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>
|
- 新建一个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 { } }
|
- 浏览器访问:http://localhost/Servlet/regist.html
- 控制台输出:
注意:多个参数之间用&
连接。
其他功能
-
获取请求参数通用方式
-
请求转发
-
共享数据
一、获取请求参数通用方式
-
不论GET还是POST请求方式都可以使用下列方法来获取请求参数
- 上述即,
doGet()
和 doPost()
的方法体代码完全一样
- 因此,为了简化,只需要选择在
doPost()
的方法体中写代码,之后在doGet()
中调用 this.doPost(request,response);
调用方法:
String getParameter(String name)
-
根据参数名称获取参数值: username=zs&password=123
String[] getParameterValues(String name)
-
根据参数名称获取参数值的数组:hobby=xuexi&hobby=game
- 将键值对,按一个键来封装不同的值并封装成一个数组
- 多用于复选框
Enumeration<String> getParameterNames()
Map<String,String[]> getParameterMap()
示例
- 新建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>
|
- 新建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); } }
|
-
浏览器访问:http://localhost/Servlet/regist2.html
-
控制台输出:
中文乱码问题
- GET方式:tomcat 8 已经将 GET方式乱码问题解决了
- POST方式:会乱码
- 解决:在获取参数前,设置request的编码
request.setCharacterEncoding("utf-8");
。对应着html页面的编码。
二、请求转发
特点
-
浏览器地址栏路径不发生变化
-
只能转发到当前服务器内部资源中
-
转发就是一次请求。像上图的AServlet和BServlet两种资源使用的是同一次请求。
步骤
- 通过request对象获取请求转发器对象
RequestDispatcher getRequestDispatcher(String path)
- 使用RequestDispatcher对象来进行转发
forward(ServletRequest request, ServletResponse response)
示例
- 新建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); } }
|
- 新建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); } }
|
- 浏览器访问:http://localhost/Servlet/RequestDemo8
- 控制台输出:
三、共享数据
-
域对象:一个有作用范围的对象,可以在范围内共享数据
-
request域:代表一次请求的范围,一般用于请求转发的多个资源*享数据
调用方法:
void setAttribute(String name,Object obj)
Object getAttitude(String n
ame)
void removeAttribute(String name)
????视频 的【03:15】,详细说到 如何共享数据。
示例
示例放在 __ 请求转发 的示例 __ 中。
详细见代码文件中的两个注释:
RequestDemo8的【// 存储数据到request域中】
RequestDemo9的【// 获取数据】
四、获取ServletContext
调用方法:
ServletContext getServletContext()
示例
- 新建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); } }
|
- 浏览器访问:http://localhost/Servlet/RequestDemo10
- 控制台输出:
下篇博客 《HTTP响应信息数据 - Response》 中,详细学习响应信息数据 - Response。