浏览器与服务器交互
服务器端Web开发常用的技术有哪些?PHP、Java、ASP.NET、node.js
HTTP是一种基于“请求”和“响应”的协议。
当客户端与服务器建立连接后:
如何查看HTTP消息?借助浏览器的开发者工具。操作步骤:
HTTP协议
// 请求行
// GET / HTTP/1.1
// 请求头
// Host: www.itheima.com
// Connection: keep-alive
// User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML,…
// Upgrade-Insecure-Requests: 1
// Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/ …
// Accept-Encoding: gzip, deflate
// Accept-Language: zh-CN,zh;q=0.9
// 请求行
// POST /form.php HTTP/1.1
// 请求头
// Host: localhost
// Content-Type: application/x-www-form-urlencoded
// Content-Length: 20
// 请求实体
// user=Jim&pass=123456
请求行的组成
注:请求行各组成部分之间,使用空格隔开。
请求头
实体内容
标签的enctype属性来设定。默认值为application/x-www-form-urlencoded。文件上传为multipart/form-data。// 响应状态行
// HTTP/1.1 200 OK
// 响应头
// Date: Thu, 02 Nov 2017 06:22:27 GMT
// Server: Apache/2.4.23 (Win64) OpenSSL/1.0.2h PHP/5.6.28
// Accept-Ranges: bytes
// Content-Type: text/html
// 实体内容
//
//
响应状态行
响应状态行用于告知客户端本次响应的状态。
状态码 | 含义 | 状态码 | 含义 |
---|---|---|---|
200 | 正常 | 403 | 禁止 |
301 | 永久移动 | 404 | 找不到 |
302 | 临时移动 | 500 | 内部服务器错误 |
304 | 未修改 | 502 | 无效网关 |
401 | 未经授权 | 504 | 网关超时 |
状态码表示服务器对客户端请求的各种不同的处理结果和状态。
响应头用于告知客户端本次响应的基本信息,包括服务器程序名、内容的编码格式、缓存控制等。
请求头和响应头是浏览器和服务器之间交互的重要信息,由程序自动处理,通常不需要人为干预。
实体内容
MIME是目前大部分互联网应用程序通用的格式。MIME的表示方法为“大类别/具体类型”。
MIME | 含义 | MIME | 含义 |
---|---|---|---|
text/plain | 普通文本(.txt) | image/gif | GIF图像(.gif) |
text/xml | XML文本(.xml) | image/png | PNG图像(.png) |
text/html | HTML文本(.html) | image/jpeg | JPEG图像(.jpeg) |
text/css | CSS文本(.css) | application/javascript | JavaScript程序(.js) |
浏览器会根据服务器响应的不同MIME类型采取不同的处理方式。
如果浏览器遇到无法识别的类型时,在默认情况下会执行下载文件的操作。
表单交互
表单交互是指在HTML中创建一个表单,用户填写表单后提交给服务器,服务器收到表单后返回处理结果。
URL参数交互
URL参数经常用于浏览器向服务器提交一些请求信息。
Ajax:Asynchronous JavaScript And XML,异步JavaScript和XML技术。
描述:不是一门新的语言或技术,是由JavaScript、XML、DOM、CSS等多种已有技术组合而成的一种浏览器端技术。
功能:用于实现与服务器进行异步交互的功能。
Ajax相对于传统的Web应用开发区别:
传统Web工作流程
Ajax工作流程
相较于传统网页,使用Ajax技术的优势具体有以下几个方面。
创建Ajax对象
W3C标准
var xhr = new XMLHttpRequest();
早期IE浏览器
var xhr = new ActiveXObject('Microsoft.XMLHTTP');
var xhr = new ActiveXObject('Msxml2.XMLHTTP');
var xhr = new ActiveXObject('Msxml2.XMLHTTP.3.0');
var xhr = new ActiveXObject('Msxml2.XMLHTTP.5.0');
var xhr = new ActiveXObject('Msxml2.XMLHTTP.6.0');
创建一个新的HTTP:open()方法
open('method', 'URL' [, asyncFlag [, 'userName' [, 'password']]])
method:用于指定请求方式,如GET、POST,不区分大小写。
URL:表示请求的地址。
asyncFlag:可选参数,用于指定请求方式,同步请求为false,默认为异步请求true。
userName和password:可选参数,表示HTTP认证的用户名和密码。
设置HTTP请求头:setRequestHeader()方法
setRequestHeader('haeder', 'value')
参数都为字符串类型。
header表示请求头字段。
value为该字段的值。
此方法必须在open()方法后调用。
向Web服务器发送请求并接收响应:send()方法
send(content)
content:用于指定要发送的数据,其值可为DOM对象的实例、输入流或字符串,一般与POST请求类型配合使用。
注意:如果请求声明为同步,该方法将会等待请求完成或者超时才会返回,否则此方法将立即返回。
在进行Ajax开发时,经常使用GET方式或POST方式发送请求。
Ajax对象发送请求的方法。
// GET
var xhr = new XMLHttpRequest(); // 创建Ajax对象
xhr.open('GET', 'test?a=1&b=2'); // 建立HTTP请求
xhr.send();
// POST
var xhr = new XMLHttpRequest();
xhr.open('POST', 'test?a=1&b=2');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('c=3&d=4');
同步请求与异步请求
Ajax对象open()方法的第3个参数用于设置同步请求和异步请求。两种方式的区别在于,是否阻塞代码的执行。
异步方式(默认):是非阻塞的,浏览器端的JavaScript程序不用等待Web服务器响应,可以继续处理其他事情。当服务器响应后,再来处理Ajax对象获取到的响应结果。
同步方式:是阻塞的,当Ajax对象向Web服务器发送请求后,会等待Web服务器响应的数据接收完成,再继续执行后面的代码。
由于同步请求的Ajax导致程序阻塞,会对用户体验造成不利影响,因此通常情况下不推荐使用同步请求。
获取Ajax的当前状态:readyState属性
readyState属性用于获取Ajax的当前状态,状态值有5种形式。
状态值 | 说明 | 解释 |
---|---|---|
0 | 未发送 | 对象已创建,尚未调用open()方法 |
1 | 已打开 | open()方法已调用,此时可以调用send()方法发起请求 |
2 | 收到响应头 | send()方法已调用,响应头也已经被接收 |
3 | 数据接收中 | 响应体部分正在被接收。responseText将会在载入的过程中拥有部分响应数据 |
4 | 完成 | 数据接收完毕。此时可以通过responseText获取完整的响应 |
另外,Ajax状态的还可以通过“XMLHttpRequest.属性名”的方式获取。
XMLHttpRequest.UNSENT; // 对应状态值0
XMLHttpRequest.OPENED; // 对应状态值1
XMLHttpRequest.HEADERS_RECEIVED; // 对应状态值2
XMLHttpRequest.LOADING; // 对应状态值3
XMLHttpRequest.DONE; // 对应状态值4
感知Ajax状态的改变:onreadystatechange事件属性
onreadystatechange事件属性用于感知readyState属性状态的改变,每当readyState的值发生改变时,就会调用此事件。
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
console.log(xhr.readyState);
};
console.log(xhr.readyState);
xhr.open('GET', 'test.php');
xhr.send();
返回当前请求的HTTP状态码:status属性
获取响应信息:responseText属性、responseXML属性等
当请求服务器成功且数据接收完成时,可以使用Ajax对象提供的相关属性获取服务器的响应信息。
属性名 | 说明 |
---|---|
responseText | 将响应信息作为字符串返回 |
responseXML | 将响应信息格式化为XML Document对象并返回(只读) |
responseXML属性在请求失败或相应内容无法解析时的值为null。
需要注意的是,服务器在返回XML时应设置响应头Content-Type的值为text/xml或application/xml,否则会解析失败。
Ajax如何处理服务器返回的信息。
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status < 200 || xhr.status >= 300 && xhr.status !== 304) {
alert('服务器异常');
return;
}
console.log(xhr.responseText);
}
};
xhr.open('GET', 'hello.php');
xhr.send();
URL参数编码转换
在通过URL参数传递数据时,如果参数中包含特殊字符可能会出现问题。
例如 “?” “=” “&”,这些字符已经被赋予了特定的含义。
如果需要传递这些特殊字符,可以使用encodeURIComponent()进行URL编码。
var str = encodeURIComponent('A&B C');
var url = 'http://xxx/test?name=' + str;
// 输出结果:http://xxx/test?name=A%26B%20C
console.log(url);
“&”被转换为“%26”。
空格被转换为“%20”。
当服务器收到已编码的内容之后,会对其进行解码,从而正确识别这些特殊字符。
对于已经编码的字符串,可以使用decodeURIComponent()进行解码。
var str = 'A%26B%20C';
// 输出结果:A&B C
console.log(decodeURIComponent(str));
前后端应用程序在进行数据交换时,如何确保它们都能识别?
约定一种格式,确保通信双方都能够正确识别对方发送的信息。
XML:eXtensible Markup Language,可扩展标记语言。
与HTML都是标签语言,XML主要用于描述和存储数据,可以自定义标签。
<booklist>
<book>
<name>三国演义name>
<author>罗贯中author>
book>
<book>
<name>水浒传name>
<author>施耐庵author>
book>
booklist>
当服务器返回的是一个XML格式的数据时,利用Ajax对象的responseXML属性即可对XML数据进行处理。
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
var data = xhr.responseXML;
var booklist = data.getElementsByTagName('booklist')[0];
console.log(booklist.childNodes);
var book = booklist.children[0];
console.log(book.children[0].innerHTML); // 方式1
console.log(book.children[0].firstChild); // 方式2(会加上引号)
console.log(book.children[0].firstChild.wholeText); // 方式3
}
};
xhr.open('GET', 'xml.php');
xhr.send();
JSON:是一种轻量级的数据交换格式。
特点:采用完全独立于语言的文本格式,这使得JSON更易于程序的解析和处理。
与XML对比:使用JSON对象访问属性的方式获取数据更加方便,在JavaScript中可以轻松地在JSON字符串与对象之间转换。
JSON格式的数据交互实现。
var obj = {name: 'Tom', age: 24}; // 准备要发送的数据
var json = JSON.stringify(obj); // 将对象转换为JSON字符串
var xhr = new XMLHttpRequest();
xhr.open('POST', 'json.php');
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
var obj = JSON.parse(xhr.responseText); // 将JSON字符串转换为对象
console.log(obj);
/*
console.log(typeof xhr.responseText); // 查看服务器返回数据的类型:string
eval('var obj = ' + xhr.responseText); // 用eval()函数将字符型转成对象
console.log(obj.name); // 输出结果:Tom
console.log(obj.age); // 输出结果:24
*/
}
};
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('json=' + encodeURIComponent(json));
eval()函数
JavaScript中的eval()函数可将传入的字符串当做JavaScript代码执行。
console.log(typeof xhr.responseText); // 查看服务器返回数据的类型:string
eval('var obj = ' + xhr.responseText); // 用eval()函数将字符型转成对象
console.log(obj.name); // 输出结果:Tom
console.log(obj.age); // 输出结果:24
eval()在设置参数时,如果传入的字符串不合法,会导致后面的代码也不执行,所以一般情况下不推荐使用它。
A网站 -> 利用Ajax读取用户在B网站中的余额 -> B网站
A网站 <- 通过Ajax向A网站发送修改密码的请求 <- B网站
跨域请求会导致网页失去安全性,因此浏览器阻止跨域请求。
浏览器如何解决跨域问题带来的危害。
遵循同源策略,同源是指请求URL地址中的协议、域名和端口都相同。
非同源的URL地址
问题 | URL-1 | URL-2 |
---|---|---|
域名不同 | http://www.example.com/1.html | http://api.example.com/1.html |
协议不同 | http://www.example.com/1.html | https://www.example.com/1.html |
端口不同 | http://www.example.com/1.html | http://www.example.com:8080/1.html |
浏览器遵循“同源策略”带来的问题:给网站正常的跨域需求带来了难题。
解决办法之一:为使受信任的网站之间能够跨域访问,HTML5提供了一个新的策略,就是Access-Control-Allow-Origin响应头。目标服务器通过该响应头可以指定允许来自特定URL的跨域请求,其值可以设置为任意URL或特定URL等。
header('Access-Control-Allow-Origin: http://localhost:8081');
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://localhost:8082/8082');
xhr.send();
JSONP:遵循浏览器的同源策略基础上实现跨域请求的一种方式。
原理:与XMLHttpRequest无关,是利用 标签的src属性实现了跨域请求。
在浏览器中, 哪些标签可以加载跨域资源?