(一)网页前端构造HTTP请求
一、直接在浏览器输入URL(构造GET)
二、使用form表单(可以构造GET和POST)
HTML里面有一个form标签,可以通过这个标签来构造。能够把用户输入的内容提交到服务器上。
通过Fiddler抓包可以可以看到,form表单构造了一个GET请求:
input标签的name属性,就成为了 query string 的key。input标签输入的内容,就成了query string 的value。
那么form表单如何构造POST请求呢?
在标签里面增加一个method方法:method="post"
通过抓包可以看到:
三、使用ajax(可以构造各种请求)
(当下比较主流的给服务器提交数据的方式)
ajax 全称 Asynchronous Javascript And XML, 是 2005 年提出的一种 JavaScript 给服务器发送 HTTP 请求的方式。特点是可以不需要 刷新页面/页面跳转 就能进行数据传输。
Asynchronous是一种异步机制,在网络编程中非常常见。网络编程中,数据通过网络传输,主要分成两个阶段:一是等待;二是拷贝数据
ajax可以在浏览器渲染页面的同时,进行网络请求,如果没有这种异步机制,那么浏览器要发起网络请求,就会阻塞渲染页面的线程,这样就会导致网络请求中界面被卡死。
1.原生ajax构造请求
注意: 如果把 send 中的地址改成其他服务器的地址(比如 http://www.sogou.com/index.html 这 种), 大概率是会出错的。
这个错误是因为 ajax 默认不能 "跨域", 也就是 "百度下面的 html 中的 ajax 不能访问 搜狗 的内
容"。如果想要强行进行跨域, 则需要服务器进行配合, 在服务器的响应中 "允许跨域" 才可以。
此时的服务器进行了允许跨域设置, 因此页面才能访问到其中的数据。
ajax为了保证安全性,要求发起ajax请求的页面和接收ajax请求的服务器,应该在同一个域名/地址下。如果发起请求的页面和接收ajax请求的服务器不相同,就认为是一次跨域请求,ajax在默认情况下是不允许跨域访问的。
2.浏览器和服务器交互过程 ( 引入 ajax 后 )
注意:
上面这个ajax原生的用法,其实是比较麻烦的。更推荐使用第三方库,利用封装好的ajax方法来使用。比如:jQuery
jQuery目前是JavaScript中最广泛使用的第三库之一。因为前端框架的出现,目前正在衰退,但还是使用广泛。
3. 那么就引入一个问题,JS中是如何安装引入第三库的呢?
我们都知道在java中,我们可以使用Maven,从中央仓库中进行下载
那么在JS中,就有一个比较简单的方法。因为JS代码都是在服务器这边,被浏览器下载到本地才会执行。那么只要在网页代码中,引入jQuery所在的网络地址,就能够直接使用。
一般我们都是使用.min.js结尾的。min表示压缩后的js代码,这样体积更小,下载更快。
然后复制地址,在浏览器打开:此时我们就会看到这个的界面。
复制地址,然后再代码中引入:
接下来,就可以使用了。
这段代码,与之前的原生的代码相比,就显得简单很多了。
注意:在浏览器页面加载过程中,是可以同时发起多个ajax请求的,此时这多个ajax请求相当于是一个并发执行的关系。但是和java相比,js对于并发编程的支持是非常有限的。
(二)如何通过 Java 代码构造 HTTP 请求
所谓的 " 发送 HTTP 请求 ", 本质上就是按照 HTTP 的格式往 TCP Socket 中写入一个字符串。
所谓的 " 接受 HTTP 响应 ", 本质上就是从 TCP Socket 中读取一个字符串 , 再按照 HTTP 的格式来解析。
基于 Socket 的知识, 可以构造出一个简单的 HTTP 客户端程序 , 用来发送各种类型的 HTTP 请求。
public class HttpClient913 { private Socket socket; private String ip; private int port; public HttpClient913(String ip, int port) throws IOException { this.ip = ip; this.port = port; socket = new Socket(ip,port); } public String get(String url) throws IOException { StringBuilder request = new StringBuilder(); //构造首行 request.append("GET" + url + "HTTP/1.1\n"); //构造header request.append("Host: " + ip + ":" + port + "\n"); //构造空行 request.append("\n"); //GET请求不需要body,这样请求基本就构造完毕了 //发送请求 OutputStream outputStream = socket.getOutputStream(); //outputStream 是一个字节流,以字节为单位进行写入,因此需要把request 转换成byte[] outputStream.write(request.toString().getBytes()); //读取响应 InputStream inputStream = socket.getInputStream(); //设置一个缓存区,用来存放响应数据 byte[] buffer = new byte[1024*1024]; //n 表示实际读到的字节数 int n = inputStream.read(buffer); return new String(buffer,0,n,"utf-8"); } //post 的实现和刚才的 get 基本一致,只是多了一步构造body public String post(String url, String body) throws IOException { StringBuilder request = new StringBuilder(); //构造首行 request.append("POST" + url + "HTTP/1.1\n"); //构造header request.append("Host: " + ip + ":" + port + "\n"); request.append("Content-Type: text/plain\n"); request.append("Content-Length: " + body.getBytes().length + "\n"); //构造空行 request.append("\n"); //构造body request.append(body); //发送请求 OutputStream outputStream = socket.getOutputStream(); outputStream.write(request.toString().getBytes()); //读取响应 InputStream inputStream = socket.getInputStream(); byte[] buffer = new byte[1024*1024]; int n = inputStream.read(buffer); return new String(buffer,0,n,"utf-8"); } }