好记性不如烂笔头,记录学习的过程和内容,望与君共勉!
HTTP
1、概述:Hyper Text Transfer Protocol 超文本传输协议,定义了客户端和服务器端通信时发送数据的格式。
2、特点:
① 基于 TCP/IP 的高级协议
② 默认端口号为 80
③ 基于请求/响应模型的:一次请求对应一次响应
④ 无状态的:每次请求之间相互独立,不能交互数据
3、请求消息的数据格式:
① 请求行:
格式→请求方式 请求url 请求协议/版本
请求方式:HTTP 协议有 7 种请求方式,常用的有 2 种,GET 和 POST。
GET:请求参数在请求行中,在 url 后,请求的 url 长度是有限制的。
POST:请求参数在请求体中,请求的 url 长度是没有限制的。
② 请求头:
客户端浏览器告诉服务器的一些信息
格式→请求头名称 : 请求头值
常见请求头:
1、User-Agent:浏览器告诉服务器,浏览器的版本信息。可以在服务器端获取该头的信息,解决浏览器的兼容性问题。
2、Accept:告诉服务器浏览器可以解析的响应的格式。
3、Referer:告诉服务器,当前请求从哪里来。
③ 请求空行:
一个空行,分割 POST请求 的请求头和请求体
④ 请求体(正文):
如果是 GET 方式的请求,没有请求体;如果是 POST 方式请求,实际上就是封装 POST 请求的一些请求参数。如 username=zhangsan
Request
Request对象 和 Response对象 的原理
request对象 的继承体系结构
ServletRequest 是一个接口,HttpServletRequest 是 ServletRequest 的子接口,RequestFacade类实现了 HttpServletRequest 接口,由 tomcat 创建该类的对象。
request 的功能
1、获取请求消息
① 获取请求行数据
获取请求方式:String getMethod()
获取虚拟目录:String getContextPath()
获取 Servlet 路径:String getServletPath()
获取 get 方式请求参数:String getQueryPath()
获取请求 URL:getRequestURI()
和 StringBuffer getRequestURL()
获取协议及版本:String getProtocol()
获取客户机的 IP 地址:String getRemoteAddr()
@WebServlet("/ServletDemo5")
public class ServletDemo5 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1 获取请求方式
String method = req.getMethod();
System.out.println(method);
// 2 获取虚拟目录
String contextPath = req.getContextPath();
System.out.println(contextPath);
// 3 获取 Servlet 路径
String path = req.getServletPath();
System.out.println(path);
// 4 获取 get 方式请求参数
String queryString = req.getQueryString();
System.out.println(queryString);
// 5 获取请求 URL
String URI = req.getRequestURI();
System.out.println(URI);
StringBuffer URL = req.getRequestURL();
System.out.println(URL);
// 6 获取协议及版本
String protocol = req.getProtocol();
System.out.println(protocol);
// 7 获取客户机的 IP 地址
String addr = req.getRemoteAddr();
System.out.println(addr);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
注:
URL:统一资源定位符 http://localhost:8080/xnlj/ServletDemo5
URI:统一资源标识符 /day15/ServletDemo5
② 获取请求头数据
String getHeader(String name)
:通过请求头的名称获取请求头的值
Enumeration<String> getHeaderNames()
:获取所有的请求头名称
@WebServlet("/RequestDemo1")
public class RequestDemo1 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求头
String agent = req.getHeader("User-Agent");
if (agent.contains("Chrome")) {
System.out.println("google Chrome");
} else if (agent.contains("Firefox")) {
System.out.println("Firefox");
} else {
System.out.println("others");
}
// 获取所有的头信息
Enumeration<String> headerNames = req.getHeaderNames();
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
// 根据名称获取请求头的值
String value = req.getHeader(name);
System.out.println(name + ":" + value);
}
// 获取referer信息
String referer = req.getHeader("referer");
System.out.println(referer);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
③ 获取请求体数据
只有 POST 请求方式才有请求体,在请求体中封装了 POST 请求的请求参数。
步骤:
a:获取流对象
BufferedReader getReader()
:获取字符输入流,只能操作字符数据
ServletInputStream getInputStream()
:获取字节输入流,可以
b:再从流对象中拿数据
写一个登录页面,以 post 方式提交表单:
<body>
<form action="/day15/RequestDemo2" method="post">
<input type="text" placeholder="请输入用户名" name="username">
<input type="text" placeholder="请输入密码" name="pwd">
<button type="submit">登录</button>
</form>
</body>
Java 代码:
@WebServlet("/RequestDemo2")
public class RequestDemo2 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);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
访问上面的登录页面,输入用户名和密码之后提交表单,可以看到在控制台打印出 username=zhangsan&pwd=123 的信息
2、其他功能
① 获取请求参数通用方式(GET 和 POST 请求方式都可用)
String getParameter(String name)
:根据参数名称获取参数值
String[] getParameterValues(String name)
:根据参数名称获取参数值的数组(通常用来获取复选框的参数值)
Enumeration<String> getParameterNames()
:获取所有请求的参数名称
Map<String, String[]> getParameterMap()
:获取所有参数的 map 集合
页面代码:
<body>
<form action="/day15/RequestDemo3" method="post">
<input type="text" placeholder="请输入用户名" name="username"><br>
<input type="text" placeholder="请输入密码" name="pwd"><br>
<input type="checkbox" name="hobby" value="study">学习
<input type="checkbox" name="hobby" value="play">游戏
<br>
<button type="submit">提交</button>
</form>
</body>
Java 代码:
@WebServlet("/RequestDemo3")
public class RequestDemo3 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求参数
String username = req.getParameter("username");
System.out.println(username);
System.out.println("---------------------------------");
// 根据参数名称获取参数值的数组
String[] hobbies = req.getParameterValues("hobby");
for (String hobby : hobbies) {
System.out.println(hobby);
}
System.out.println("---------------------------------");
// 获取所有请求的参数名称
Enumeration<String> enumeration = req.getParameterNames();
while (enumeration.hasMoreElements()) {
String name = enumeration.nextElement();
System.out.println(name);
String value = req.getParameter(name);
System.out.println(value);
}
System.out.println("---------------------------------");
// 获取所有参数的 map 集合
Map<String, String[]> map = req.getParameterMap();
Set<String> set = map.keySet();
for (String name : set) {
System.out.println(name);
// 根据键获取值
String[] values = map.get(name);
for (String value : values) {
System.out.println(value);
}
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
中文乱码问题:
tomcat 8 已经将 get 方式的乱码问题解决了
而 post 方式如果输入中文或非法问题就会出现乱码问题,为了解决该问题,我们需要在获取参数之前,设置 request 的编码:
request.setCharacterEncoding("utf-8");
② 请求转发
一种在 服务器内部 的资源跳转方式。
步骤:
a:通过 request 对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
b:使用 RequestDispatcher 对象进行转发:forward(ServletRequest request, ServletResponse response)
特点:
a:浏览器地址栏路径不发生变化
b:只能转发到当前服务器内部资源中
c:转发是一次请求
@WebServlet("/RequestDemo4")
public class RequestDemo4 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("RequestDemo4 被访问了~~~");
// 转发资源到 RequestDemo5
req.getRequestDispatcher("/RequestDemo5").forward(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
}
@WebServlet("/RequestDemo5")
public class RequestDemo5 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("RequestDemo5 被访问了~~~");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
}
创建两个 Servlet 对象,当通过浏览器访问 RequestDemo4 这个资源时,会在控制台打印出
RequestDemo4 被访问了~~~
和RequestDemo5 被访问了~~~
这两句话,也就是浏览器通过一次请求间接的访问了两个资源。
③ 共享数据
域对象:一个有作用范围的对象,可以在范围内共享数据
request 域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
方法:
a:void setAttribute(String name, Object obj)
:存储数据
b:Object getAttitude(String name)
:通过键获取值
c:void removeAttribute(String name)
:通过键移除键值对
@WebServlet("/RequestDemo4")
public class RequestDemo4 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("RequestDemo4 被访问了~~~");
// 存储数据到 request 域中
req.setAttribute("name", "zhangsan");
// 转发资源到 RequestDemo5
req.getRequestDispatcher("/RequestDemo5").forward(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
}
@WebServlet("/RequestDemo5")
public class RequestDemo5 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Object obj = req.getAttribute("name");
System.out.println(obj);
System.out.println("RequestDemo5 被访问了~~~");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
}
④ 获取 ServletContext
ServletContext getServletContext()
@WebServlet("/RequestDemo6")
public class RequestDemo6 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = req.getServletContext();
System.out.println(context); // org.apache.catalina.core.ApplicationContextFacade@51f99c81
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
}
我是快斗,请多多指教!下篇不见不散!