HTTP
概念
hyper text transfer Protocol 超文本传输协议(传输协议定义了客户端和服务器端通信时,发送数据的规则)
特点
- 基于TCP/IP的高级协议(安全)
- 默认端口80
- 基于请求/响应模型:一次请求对应一次响应
- 无状态:每次请求之间相互独立,不能交互数据
历史版本
- 1.0:每一次请求都会建立连接(F12 network查看请求)
- 1.1:复用链接
请求消息(客户端发送给服务器端的数据)的数据格式
请求行(请求方式 请求url 请求协议/版本)
请求方式有7种,常用2种。
GET:(1.请求参数在请求行中的url后,不安全 2.请求的url有长度限制 )
POST:(1.请求参数在请求体中,相对安全 2.请求的url没有长度限制)
请求头(请求头名称:请求头值)键值对
常见的请求头:
- user-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息(可以在服务器端获取该头的信息,解决浏览器的兼容性问题)
- Referer:告诉服务器,我(当前的请求)从哪里来?
作用:1. 防盗链 2.统计工作
请求空行(空行)
用于分隔post请求的请求头和请求体
请求体(正文)
封装post请求消息的请求参数
响应消息(服务器端发送给客户端的数据)
数据格式
响应行
- 组成:协议/版本 响应状态码 状态码描述
- 响应状态码:服务器告诉客户端浏览器本次响应的一个状态。
- 响应状态码分类:
A:1xx:服务器接收客户端消息,但没有接收完成,等待一段时间后,发送1xx的状态码
B:2xx:成功。代表有:200
C:3xx:重定向。代表有:302重定向,304(访问缓存)
D:4xx:客户端错误。代表有:404(请求路径没有对应的资源) 405(请求方式没有对应的doXxx方法)
E:5xx:服务器端错误。代表:500(服务器内部出现异常)
响应头
- 格式:头名称:值
- 常见的响应头:
Content-Type:服务器告诉客户端本次响应体数据格式以及编码
Content-disposition:服务器告诉客户端以什么格式打开响应体数据(in-line:默认值,在当前页面内打开。attachment;filename=xxx:以附件形式打开响应体,文件下载)
响应空行
响应体
传输的数据
响应的字符串格式:
HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
Content-Length: 90
Date: Wed, 03 Nov 2021 15:08:59 GMT
Keep-Alive: timeout=20
Connection: keep-alive
<html>
<head>
<title>$Title$< /title>
</head>
<body>
$END$
</body>
<html>
request和response对象
原理
- request和response对象是由服务器创建的,我们来使用它们
- request对象是来获取请求消息的
- response对象是我们来设置响应消息的
一.request
request对象继承体系
ServletRequest(父接口)
HttpServletRequest(子接口)
实现类(tomcat提供的)org.apache.catalina.connector.RequestFacade
request对象的功能
1.获取请求消息数据
获取请求行数据
GET /Demo/ request ? username=zhansan HTTP/1.1
- 获取请求方式(GET)
String getMethod() - 获取虚拟目录(/Demo)
String getContextPath() - 获取资源路径,也就是Servlet路径(/request )
String getServletPath() - 获取get方式请求参数(username=zhansan)
String getQueryString() - 获取请求URI(/Demo/ request)
String getRequestURI() - 获取请求URL(http://localhost/Demo/ request)
String getRequestURL() - 获取客户机的ip地址
String getRemoteAddr() - 获取协议版本(HTTP/1.1)
String getProtocol()
URL和URI的区别
URL:统一资源定位符。中华人民共和国
URI:统一资源标识符。共和国
获取请求头数据
- 通过请求头的名称获取请求头:
String getHeader(String name); - 获取所有请求头名称
Enumeration< String> getHeaderNames()
枚举(内部为迭代器 hasMoreElements() nextElement())
user-Agent案例
referer案例(告诉服务器,当前的请求从哪里来?)
- 用当前Servlet打开浏览器返回null
- 测试这个需要打开两个tomcat服务器(端口号不能冲突)
- 一个虚拟路径为Demo,是我们指定的合法的途径。一个指定任意的(盗链)。
获取请求体数据
请求体:只有post请求才有请求体,在请求体重封装了post请求的请求参数。
- 获取流对象
BufferedReader getReader() 获取字符流
ServletInputStream getInputStream()获取字节流 - 从流对象中获取数据
拿到数据:username=123&password=456
2.其他功能
1. 获取请求参数通用方式(无论get还是post请求方式都能使用下列方法获取请求参数)
- String getParameter(String s)获取参数s的值(只获取一个)
- String[] getParameterValues(String s)获取参数s所有的值(多用于复选框,获取所有的)
- Enumeration< String> getParameterNames()获取所有参数的名字
- Map< String,String[]> getParameterMap()获取所有参数键值对
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name=request.getParameter("username");
System.out.println(name);
System.out.println("==========");
String[] ss=request.getParameterValues("hobby");
for(String s:ss){
System.out.print(s+'\t');
}
System.out.println();
System.out.println("==========");
Enumeration<String> pn = request.getParameterNames();
while (pn.hasMoreElements()){
System.out.println(pn.nextElement());
}
System.out.println("==========");
Map<String, String[]> pm = request.getParameterMap();
Set<String> keys = pm.keySet();
for (String key:keys){
String[] values = pm.get(key);
System.out.print(key+"=");
for (String s:values){
System.out.print(s+'\t');
}
System.out.println();
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册页面</title>
</head>
<body>
<form action="RequestDemo4" method="post">
<input name="username" placeholder="请输入用户名"><br>
<input name="password" placeholder="请输入密码"><br>
<input name="hobby" type="checkbox" value="shopping">购物
<input name="hobby" type="checkbox" value="java">java<br>
<input type="submit" value="注册">
</form>
</body>
</html>
中文乱码问题
get:tomcat 8已经将乱码问题解决了
post:会乱码(在获取参数前,设置request的编码request.setCharacterEncoding("utf-8 "))
2.请求转发(一种在服务器内部的资源跳转方式)
- 步骤
A. 通过request对象获取请求转发器对象:RequeatDispatcher getResquestDispatcher(String path)
B.通过RequestDispatcher转发器对象转发:forward(ServletRequest request,ServletResponse response) - 特点
A.浏览器地址栏路径不发生变化
B.只能跳转到当前服务器内部的资源
C.转发是一次请求
3.共享数据
- 域对象:一个有作用范围的对象那个,可以在作用范围内起作用
- request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
- 方法:
A.void setAttribute(String name,Object obj)给name存储数据obj
B.Object getAttribute(String name)通过键获取值
C.void removeAttribute(String name)通过键移除键值对
4.获取ServletContext
ServletContext getServletContext()
二.response
功能
设置响应消息
设置响应行
- 格式:http/1.1 200 ok
- 设置状态码:setStatus(int sc)
设置响应头
setHeader(String name,String value)
设置响应体
步骤:
- 获取输出流
字符输出流:PrintWriter getWriter()
字节输出流:ServletOutputStream getOutputStream() - 使用输出流,将数据输出到客户端浏览器。
案例
完成重定向
代码1(设置状态码为302,设置响应头:location)
成功跳转!!!
代码2(response中自带的方法:sendRedirect)
跳转成功!!!
重定向
重定向与请求转发的区别
重定向:
- 地址栏改变
- 可访问其他站点(服务器)的资源
成功跳转到百度首页。 - 两次请求
转发: - 转发地址栏不变
- 转发只能访问当前服务器下的资源
- 转发是一次请求
路径的写法(重定向有虚拟目录)
- 相对路径:通过相对路径不可以确定唯一资源
不以/开头,以.开头:./login.html
规则:
找到当前资源和目标资源之间的相对位置关系(./表示当前目录 …/表示后退一级目录,也就是到上一级目录) - 绝对路径:通过绝对路径可以确定唯一资源
以/开头的路径
规则:
判断定义的路径是给谁用的?判断请求将来从哪发出。- 给客户端浏览器使用:需要加虚拟目录(如: < a>< form>重定向)
建议使用动态获取虚拟目录:request.getContextPath() - 给服务器端使用:不需要加虚拟目录(如存储请求转发)
- 给客户端浏览器使用:需要加虚拟目录(如: < a>< form>重定向)
服务器输出字符数据到浏览器
1.设置流的默认编码,获取字符输出流
2. 输出数据(write/pringln)
注意:乱码问题
设置输出流(流是从tomcat中获取出来的)的默认编码: 拉丁编码ISO-8859-1 设置为 GBK(浏览器默认编码格式与操作系统有关:windows默认:国标扩展码–中国码表)
response.setCharacterEncoding(“”)
告诉浏览器,服务器发送的消息体数据使用的编码,并建议浏览器使用该编码解码:
response.setHeader(“content-type”,“html/test;charset=utf-8”)
response.setContentType(“html/test;charset=utf-8”);
服务器输出字节数据(一般为图片,视频等)到浏览器
1.设置流的默认编码,获取字节输出流
2. 输出数据(write/pringln)
3. getBytes()默认GBK
验证码(本质为图片)
- 验证码存在的目的:防止恶意的表单注册。
- 验证码图片是怎样生成的:
- 提前存很多图片在文件夹
- 动态生成验证码
过程
- 创建一对象,能在内存中画图(验证码图片对象)
- 美化图片
- 将图片输出到页面展示
@WebServlet("/RespDemo5")
public class RespDemo5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int width=100;
int height=50;
//1.创建一对象,在内存中画图(验证码图片对象)
BufferedImage image=new BufferedImage(width,height,BufferedImage.TYPE_3BYTE_BGR);
//2.美化图片
//2.1填充背景色
Graphics g = image.getGraphics();
g.setColor(Color.pink);
g.fill3DRect(0,0,width,height,true);
//2.2画边框
g.setColor(Color.BLACK);
g.draw3DRect(0,0,width-1,height-1,true);
String str="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
//生成随机角标
Random random=new Random();
g.setColor(Color.BLACK);
for (int i=1;i<=4;i++){
int index=random.nextInt(str.length());
char ch=str.charAt(index);
g.drawString(ch+"",width/5*i,height/2);
}
//2.4画干扰线
g.setColor(Color.green);
//随机生成坐标点
for (int i=0;i<10;i++){
int x1=random.nextInt(width);
int x2=random.nextInt(width);
int y1=random.nextInt(height);
int y2=random.nextInt(height);
g.drawLine(x1,y1,x2,y2);
}
//3将图片输出页面展示
ImageIO.write(image,"jpg",response.getOutputStream());
}
ServletContext对象
- 概念:代表整个Web应用,可以和程序的容器(服务器)来通信。
- 获取:
- request对象:request.getServletContext();
- HttpServlet: this.getServletContext();
- 功能:
-
获取MIME类型:
MIME类型:在互联网通信过程中定义的一种文件数据类型。
格式:大类型/小类型 text/html image/jpeg
获取:getMimeType(String file)
-
域对象:共享数据(servletContext对象范围:所有用户所有请求的数据 ->也就是用一个浏览器访问ContextDemo2存储,另一个浏览器访问3->相当于另一个用户,可以读出前一个用户在2存的数据)
- setAttribute(String name,Object value)
- getAttribute(String name)
- removeAttribute(String name)
-
获取文件的真实(服务器)路径(方法:String getRealPath(String path))
- web目录下资源直接访问
- WEB-INF目录下的资源访问要带上WEB-INF/
- src目录下的资源访问带上WEB-INF/classes/(src中的文件将来会全部放在WEB-INF的classses文件夹中)
-