http协议:Hyper Text Transfer Protocol
超文本传输协议,他的底层是依附于TCP/IP传输协议,所以也是数据的传输也是比较安全的。因为从TCP/IP的层面来说,数据会建立三次握手,然后才会传输数据啊,非常严谨。
最直观来说,输入网址,就是调用什么,http协议,然后进行一个客户端与服务器之间的一个通信。
那么具体的http协议是啥?
从目前来看,分为三个版本,一个是1.0,一个是1.1,一个是2.0,现在用的最多的就是1.1,那么现在https基本就是基于1.1的版本,那么1.1的好处?好处就是链接一个复用,就是说他不会立刻就把一个TCP/IP连接给关闭,就是我等你一会啊,你要是不在用了,那我就关闭了啊。特点就是快嘛,但是相对于2.0还是有点慢。
简单说一下这三个版本,1.0呢,特点是每一次传输开一个TCP/IP,那么也就是说有一百个请求,我就要开一百次传输连接,我去,你说慢不慢,每一次又要带一些请求头部数据过去,数据又会变大,传输自然也会变慢。
1.1呢,特点就是我整个过程只开一次TCP/IP连接,换句话说,有一百个请求,那我也只会开一个TCP连接用来传输,也就是长连接,特点就是快嘛,但是这里有个问题就是,每次新的传输发生之前,会在头部添加一些信息,比如说,表明我是复用之前的连接来传输数据,所以,这个时候,头部数据就会增加,数据包含量就会比较大,但是它有一个缺点就是,数据传输必须一个一个传输,一个传输完成才能进行下一个传输
2.0,这个牛逼了,长连接是必须的,并且,数据包比较小,不用去声明,另外就是并发性比较好,一次可以传输多个文件,而1.1只能一个文件传输完成才能传输另外一个。虽然一次可以传输多个文件,但是最后在客户端展示的时候,依然会按照我们的请求顺序来展示图片内容。
那么这里延伸出一个问题,什么是一次互联网请求?
简单就说,你访问一个网站的页面,这个页面涉及了很多数据,比如图片,视频,文档,等等,那么每一个访问,都是一次请求。展示一下这些请求
建议采用火狐浏览器浏览。下面访问百度产生的一些列请求
下面就是说,具体说一下http1.1的这个内容:
上面就是请求头部数据
上面组成如下:
第一行请求行-》数据传输方式
后面连续的数据就是请求头
请求头简单来说,就是告诉服务器,我是谁,我能接收什么类型数据,我的一些信息是什么。
比如
User-Agent:我用的是哪一个 浏览器
Rferer:告诉服务器我来自哪里
Connection: keep-alive保持TCP连接不断开
然后有一个空行
空行下面就是请求体数据
用一个图就是:
上面就是http协议一些简单的内容。
下面说一下我们怎么在服务器端处理这些请求数据。
当然了,服务器开发者怎么会想不到这些,javaee规范早就定义好了,所以,肯定会给我们一个接口去调用方法获取这些信息。
直接上这些接口的依附关系
我们要用到的就是HttpServletRequest这个接口, 通过上面的依附关系很明显就可以看到Tomcat帮我们做了一个实现类,其实我们调用的就是实现类里面的方法:
doGet里面帮我们传递了请求对象,它的本质就是:
HttpServletRequest resquest = new RequestFacade();
然后去调用子类的方法:
下面说几个常见的Request方法:
1.getMethod()获取资源请求方式
2.getConTextPath()获得虚拟目录
3.统一资源标识符与统一资源定位符,特别是URI定位符,用的比较多
4.getRemoteAddr()获得远程主机地址
关于请求头的一些操作:
代码:
package web.request;
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("/ServletDemo2")
public class ServletDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//下面来获取所有请求头名称
Enumeration<String> headerNames = request.getHeaderNames();
//下面来遍历请求头信息
while(headerNames.hasMoreElements()){
String name = headerNames.nextElement();
String value = request.getHeader(name);
System.out.println(name + ":" + value);
}
System.out.println("新行来了");
System.out.println("又来了新的一行");
System.out.println("-------------");
//得到你来的路径
String referer = request.getHeader("referer");
System.out.println("N你的访问路径:" + referer);
}
}
获取请求体的数据,这个数据也就是我们传输的数据
注意上面获取的是请求体中的数据,就是通过post或者get提交过来的数据
话不多说,上代码:
ServletDemo3:
package web.request;
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("/ServletDemo3")
public class ServletDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求体信息
//post获取参数可能会出现中文乱码问题
request.setCharacterEncoding("utf-8");
//1.获取字符流
BufferedReader br = request.getReader();
//读取数据,获取post里面传来的数据
String line = null;
while((line = br.readLine()) != null) {
System.out.println(line);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
我又写了一个html页面去访问它:
regist.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/request/ServletDemo3" method = "post">
<input type="text" name="username"/><br/>
<input type="text" name="password"/><br/>
<input type="submit" value="注册"/>
</form>
</body>
</html>
打印了如下信息:
这个信息很明显,名字是经过了加密处理的
下面我采用字节流来读取一下数据:
这字节流是javaee帮我们做了一个实现,说到底还是调用了字节流里面的方法
还是同一个文件,替换成字节流读取代码就行
//当然,我们还可以采用字节流来读取数据
InputStream is = request.getInputStream();//用父类做了一个接收
//循环读取数据
byte[] buff = new byte[1024];
int len = 0;
while((len = is.read(buff)) != -1) {
System.out.println(new String(buff,0,len));
}
结果:
获取其他请求参数方式:
话不多说,直接上代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/request/ServletDemo4" method = "get">
<input type="text" name="username" placeholder="请输入用户名"/><br/>
<input type="text" name="password" placeholder="请输入密码"/><br/>
<input type="checkbox" name="hobby" value ="name"/>游戏
<input type="checkbox" name="hobby" value ="football"/>足球
<input type="checkbox" name="hobby" value ="name"/>游戏
<input type="submit" value="注册"/>
</form>
</body>
</html>
上面做了一个静态页面去向访问服务器的ServletDemo4页面
package web.request;
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;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
@WebServlet("/ServletDemo4")
public class ServletDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//得到所有请求,然后迭代
Enumeration<String> enumeration = request.getParameterNames();
//上面就是返回一个迭代器对象
while(enumeration.hasMoreElements()) {
//参数名字拿出来
String name = enumeration.nextElement();
//把这些数据变成数组
System.out.println(name);//得到属性名,来取属性值
String[] value = request.getParameterValues(name);
for(String data : value) {
System.out.println(data);
}
System.out.println("-----");
}
System.out.println("----------------------");
//获取所有参数的map集合,属性-值名,前者是属性,后者是值的一个数组集合
Map<String,String[]> parameterMap = request.getParameterMap();
//开始迭代
Set<String> set = parameterMap.keySet();
//获取键值对
Iterator<String> it = set.iterator();
while(it.hasNext()){
String name = it.next();//这个就是每一个元素
//然后取出值
System.out.println(name + ":");
//这里每一个值都是一个数组
String[] value = parameterMap.get(name);
//再来遍历
for(String data : value) {
System.out.println(data);
}
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
上面用了两种方式获取数据
这是我提交的数据
上面打印的乱码,和文件保存编码有关系,通过记事本打开,另存修改编码就不是乱码了。
下面在多说一嘴,获取请求体-》两种输入流操作-》可以得到post请求的数据,也是请求参数
上面的方法,是一种通用的方法,post请求参数与get请求参数都可以获取
下面说一下服务器内部的一个资源跳转,这个跳转其实也很简单,就是我服务器内部带着requestd对象还有response对象去找我的兄弟页面。自然,内部跳转,浏览器地址不会改变,转发就是一次请求,只能到服务器内部。
在转发的过程中,resquest之间可以共享
话不多说,直接上代码
ServletDemo5.java
package web.request;
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("/ServletDemo5")
public class ServletDemo5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("我是deom5,我要跳转到Demo6....");
//设置一个属性传过去
request.setAttribute("msg","我爱你demo6");
//开始定向
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/ServletDemo6");
requestDispatcher.forward(request,response);//定向到Demo6
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
上面demo5就带着自己的数据去找Demo6了
ServletDemo6.java
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("/ServletDemo6")
public class ServletDemo6 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取数据
Object msg = request.getAttribute("msg");
System.out.println("我是Demo9,传递过来的信息是:" + msg);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
Demo6就去获取了一下数据
是不是就死说两边数据都可以打印,但是如果Demo7想要获取Demo5的数据,那是不可能的,因为数据的共享是在一次请求范围之间。
好了,resquest大致就说到这。