課程回顧
- 如何創建一個Servlet
- 如何配置Servlet
- Servlet生命週期
- Servlet源碼解析
XML解析
xml簡介
Extensible Markup Language 中文: 可擴展標記語言
可擴展標記語言,標準通用標記語言的子集,簡稱XML。是一種用於標記電子文件使其具有結構性的標記語言。 在電子計算機中,標記指計算機所能理解的信息符號,通過此種標記,計算機之間可以處理包含各種的信息比如文章等。它可以用來標記數據、定義數據類型,是一種允許用戶對自己的標記語言進行定義的源語言。 它非常適合萬維網傳輸,提供統一的方法來描述和交換獨立於應用程序或供應商的結構化數據。是Internet環境中跨平臺的、依賴於內容的技術,也是當今處理分佈式結構信息的有效工具。早在1998年,W3C就發佈了XML1.0規範,使用它來簡化Internet的文檔信息傳輸。
不同的系統之間如何進行數據傳輸,JAVA寫的系統如何把數據傳遞給.Net系統或者PHP系統;反之亦然。我們就需要一個可以跨各種技術平臺的一種數據傳遞格式;不依賴於具體的技術。這就是XML技術,不依賴於底層技術,僅僅傳遞數據。
xml語法
1、必須有聲明語句。
<?xml version="1.0" encoding="UTF-8"?>
2、注意大小寫,區分大小寫
3、XML文檔有且只有一個根元素
4、屬性值使用引號
5、所有的標記必須有相應的結束標記
6、所有的空標記也必須被關閉
xml節點類型
- 元素節點 element
- 屬性節點 attribute
- 文本節點 text
- 註釋節點 comment
xml和對象的轉換
我們編程是面向對象的編程,所有數據都是以對象的方式傳輸, 問題:
- 把java對象轉換成XML文件
- 把XML文件解析成java對象
譬如: 調用別的系統返回的數據是XML格式的
<?xml version="1.0" encoding="UTF-8"?>
<response>
<status>200</status>
<mchuid>100</mchuid>
<mchmid>100</mchmid>
<userid>50</userid>
<msg>信息正確,授權成功</msg>
</response>
xml解析的主流技術
廣義的解析包括: 把對象轉換成XML文件、創建XML文件、修改XML文件、刪除XML文件節點、把XML轉換成對象
主流的XML文件解析技術:
- DOM解析: W3C的官方標準, 以層次結構(類似於樹型)來組織節點和信息片段,
- SAX(Simple API for XML)解析:通過事件驅動,每發現一個節點就引發一個事件,事件推給事件處理器
- DOM4J((Document Object Model for Java))解析:簡單易用,採用Java集合框架,並完全支持DOM、SAX和JAXP
- JDOM(Java-based Document Object Model)解析:Java特定的文檔對象模型。自身不包含解析器,使用SAX
- StAX(Streaming API for XML) 解析: 流模型中的拉模型分析方式。提供基於指針和基於迭代器兩種方式的支持
DOM4解析XML文件
使用DOM4J操作XML文件
<?xml version="1.0" encoding="UTF-8"?>
<phoneInfo>
<brand name="小米" id="1001">
<type name="小米8"/>
<type name="小米9"/>
<type name="小米MIX"/>
</brand>
<brand name="iphone" id="1002">
<type name="iphoneX"/>
<type name="iphoneXs"/>
<type name="iphone8">xxx</type>
</brand>
<brand name="華爲" id="1003">
<type name="p20"/>
<type name="p30"/>
<type name="P30pro"/>
</brand>
</phoneInfo>
案例:
package com.ujiuye.xml;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.Iterator;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.junit.Test;
public class XMLTest {
@Test
public void deleteElement() throws Exception{
//1.創建解析器對象
SAXReader reader = new SAXReader();
//2.讀取XML文件
Document document = reader.read(new File("src/info.xml"));
//3.獲取根節點
Element rootEle = document.getRootElement();
//4.獲取所有的子節點
Iterator<?> it = rootEle.elementIterator();
while(it.hasNext()) {
Element element = (Element) it.next();
if(element.attributeValue("name").equals("魅族")) {
element.getParent().remove(element);
}
}
//5.寫到文件
XMLWriter writer = new XMLWriter(new FileOutputStream("src/info.xml"), OutputFormat.createPrettyPrint());
writer.write(document);
writer.flush();
writer.close();
}
@Test
public void updateElement() throws Exception{
//1.創建解析器對象
SAXReader reader = new SAXReader();
//2.讀取XML文件
Document document = reader.read(new File("src/info.xml"));
//3.獲取根節點
Element rootEle = document.getRootElement();
//4.獲取所有的子節點
Iterator<?> it = rootEle.elementIterator();
while(it.hasNext()) {
Element element =(Element) it.next();
if(element.attributeValue("name").equals("魅族")) {
Iterator<?> it2 = element.elementIterator();
while(it2.hasNext()) {
Element eleType = (Element) it2.next();
if(eleType.attributeValue("name").equals("魅族17pro")) {
eleType.addAttribute("name", "華爲P30");
}
}
}
}
//把文檔寫到文件
OutputStream os = new FileOutputStream("src/info.xml");
XMLWriter writer = new XMLWriter(os,OutputFormat.createPrettyPrint());
writer.write(document);
writer.flush();
writer.close();
}
@Test
public void addElement() throws Exception{
//1.創建解析器對象
SAXReader reader = new SAXReader();
//2.讀取XML文件
Document document = reader.read(new File("src/info.xml"));
//3.獲取根節點
Element rootEle = document.getRootElement();
//4.添加子節點
Element childEle = rootEle.addElement("brand");
//5.給子節點添加屬性
childEle.addAttribute("name", "魅族");
//6.給子節點添加節點
Element typeEle = childEle.addElement("type");
typeEle.addAttribute("name", "魅族17pro");
//把文檔寫到文件
OutputStream os = new FileOutputStream("src/info.xml");
XMLWriter writer = new XMLWriter(os,OutputFormat.createPrettyPrint());
writer.write(document);
writer.flush();
writer.close();
}
@Test
public void parseXMl() throws Exception{
//1.創建解析器對象
SAXReader reader = new SAXReader();
//2.讀取xml文件
Document document = reader.read(new File("src/info.xml"));
//3.獲取根節點
Element rootEle = document.getRootElement();
System.out.println("根節點名稱:"+rootEle.getName());
//4.獲取所有的字節點
Iterator<?> it = rootEle.elementIterator();
//5.遍歷所有的子節點
while(it.hasNext()) {
Element element = (Element) it.next();
System.out.println("子節點名稱:"+element.getName());
System.out.print("\tname:"+element.attributeValue("name"));
System.out.print("\tid:"+element.attributeValue("id"));
System.out.println();
//再獲取子節點
Iterator<?> it2 = element.elementIterator();
while(it2.hasNext()) {
Element ele2 = (Element) it2.next();
System.out.println("\n節點名稱:"+ele2.getName() );
System.out.print("屬性:"+ele2.attributeValue("name"));
}
}
}
}
把一組對象寫入XML文件
實體類:
package com.ujiuye.xml;
public class Emp {
private int id;
private String name;
private int age;
private String gender;
private int salary;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public Emp(int id, String name, int age, String gender, int salary) {
super();
this.id = id;
this.name = name;
this.age = age;
this.gender = gender;
this.salary = salary;
}
}
寫入文件:
public static void main(String[] args) {
List<Emp> list = new ArrayList<Emp>();
list.add(new Emp(1, "jack", 33, "男", 5000));
list.add(new Emp(2, "boss", 55, "男", 55000));
list.add(new Emp(3, "marry", 22, "女", 3500));
list.add(new Emp(4, "kate", 25, "女", 6000));
list.add(new Emp(5, "tom", 32, "男", 8500));
/*
* 生成一個xml的基本步驟
* 1:創建文檔對象Document
* 2:爲Document添加根節點
* 3:爲根節點組建樹狀結構
* 4:創建XMLWriter
* 5:爲XMLWriter指定寫出目標
* 6:寫出xml
*/
// 1.通過DocumentHelper創建Document對象
Document doc = DocumentHelper.createDocument();
/*
* 2.Document的方法 Element addElement(String name) 該方法用於向文檔中添加給定名字的根元素,
* 返回的Element實例就表示該 根元素 需要注意的是,該方法只能調用一次。 調用第二次會拋出異常。
*/
Element root = doc.addElement("list");
//循環添加每一個員工信息
for (Emp e : list) {
// 向根標籤中添加emp標籤
Element emp = root.addElement("emp");
// 向emp標籤中添加子標籤name
Element name = emp.addElement("name");
name.addText(e.getName());
// 向emp標籤中添加子標籤age
emp.addElement("age").addText(e.getAge() + "");
emp.addElement("gender").addText(e.getGender());
emp.addElement("salary").addText(e.getSalary() + "");
/*
* 爲標籤添加屬性 Element addAttribute( String name,String value ) 爲當前標籤添加給定名字以及對應值的屬性
* 返回值仍然爲當前標籤。這樣做的目的是可以連續添加若干屬性 就好像StringBuilder的append的 返回值效果和作用。
*/
emp.addAttribute("id", e.getId() + "");
}
//當退出循環後,那麼Document中的 結構就已經構建完了 需要將其寫出爲xml
try {
XMLWriter writer = new XMLWriter(new FileOutputStream("src/emp.xml"), OutputFormat.createPrettyPrint());
//將Document對象寫出到文件中 這時會將Document轉換爲xml格式 寫入文件。
writer.write(doc);
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
DOM4J和XPath
剛纔在DOM4J解析XML文件的時候,問題是我們要遍歷所有的節點,然後再判斷找到需要的節點進行操作。能不能直接定位到某個節點而不是遍歷。這就是XPath的功能: xml path根據節點路徑獲取節點。
XPath: XPath 是xml的路徑語言,使用路徑表達式來操作xml文檔,使用XPath操作xml文檔更加便捷。
使用XPath,我們還需要導入一個依賴包,https://mvnrepository.com/artifact/jaxen/jaxen/1.1.6
1.XPath的基本使用
dom4j提供了兩個方法支持XPath搜索:
-
List selectNodes(String expr); 獲取多個節點
-
Node selectSingleNode(String expr); 獲取單個節點
我們首先還是獲取Document對象,因爲以上兩個搜索方法都是Document的方法。
2.Xpath表達式的幾種寫法
第一種形式:
/AAA/BBB/CCC:表示層級結構,表示AAA下面BBB下面的所有CCC
第二種形式:
//BBB:選擇文檔中所有的BBB元素
第三種形式:
/AAA/BBB/:選擇目錄下的所有元素
////BBB:選擇有三個祖先元素的BBB元素
//*:選擇所有的元素
第四種形式:
//AAA[1]/BBB:選擇第一個AAA下的BBB元素
//AAA/BBB[1]:選擇所有AAA的第一個BBB元素
//AAA/BBB[last()]:選擇所有AAA的最後一個BBB元素
第五種形式:
//@id:選擇所有的id屬性
//BBB[@id]:選擇具有id屬性的BBB元素
第六種形式:
//BBB[@id=‘b1’] :選擇含有屬性id並且其值爲b1的BBB元素
3.路徑的問題
如果我們的XPath表達式以 “/” 開頭,那麼表示相對於整個文檔進行搜索;
如果我們的XPath表達式以結點(標籤)名開頭,那麼表示相對於調用搜索方法的結點進行搜索;
舉個例子:
// 首先我們拿到了student的父標籤 students
Node students = doc.selectSingleNode("/classroom/persons/students");
// 以下兩種方式搜索的結果是相同的
List<?> list1 = students.selectNodes("/classroom/persons/students/student"); // 以 “/” 開頭
List<?> list2 = students.selectNodes(“student”); // 以標籤名開頭
4.測試案例
<?xml version="1.0" encoding="utf-8"?>
<classroom grade="primary5">
<persons>
<teacher id="1">
<property name="name" value="laosi"/>
<property name="age" value="24"/>
</teacher>
<students>
<student id="1">
<property name="name" value="lisi"/>
<property name="age" value="12"/>
</student>
<student id="2">
<property name="name" value="zhangsan"/>
<property name="age" value="12"/>
</student>
<student id="3">
<property name="name" value="wangwu"/>
<property name="age" value="12"/>
</student>
</students>
</persons>
</classroom>
使用XPath讀取XML文件
@Test
public void xpath1() throws Exception{
//1.創建解析器對象
SAXReader reader = new SAXReader();
//2.讀取xml文件
Document document = reader.read(new File("src/student.xml"));
Node students = document.selectSingleNode("/classroom/persons/students");
List<Element> list1 = students.selectNodes("student"); // 以標籤名開頭
for (Element element : list1) {
System.out.println(element.getName()+"=="+element.attributeValue("id"));
List<Element> list2 = element.elements();//獲取當前節點的子節點
for (Element element2 : list2) {
System.out.println("\t"+element2.getName());
System.out.println("\t\t"+element2.attributeValue("name") + "-->" +
element2.attributeValue("value"));
}
}
}
可以根據節點路徑直接獲取節點,不用全部遍歷所有節點;效率會更高。
處理上面把一組員工信息寫入XML的案例:
@Test
public void xpath2() throws Exception {
try {
// 讀取xml文件轉換爲Document
SAXReader reader = new SAXReader();
Document doc = reader.read(new File("src/emp.xml"));
String path = "/list/emp[gender='女']/salary[.>4000]";
List<Element> list = doc.selectNodes(path);
for (Object o : list) {
Element e = (Element) o;
System.out.println(e.getText());
}
} catch (Exception e) {
e.printStackTrace();
}
}
第2種主流技術是W3C規範的DOM解析XML文件。
DOM解析XML文件
微信支付接口案例
請求參數和響應結果都是XML格式的字符串,發送請求的時候我們需要把對象的數據轉換成XML格式的字符串,解析響應的時候我們需要把返回的XML格式的字符串轉換成對象。微信支付案例如下:
把請求對象轉換成XML字符串
請求數據格式
字段名 | 變量名 | 必填 | 類型 | 說明 |
---|---|---|---|---|
商戶編號 | mchuid | 是 | int | 商戶授權接口獲取到的商家ID |
門店編號 | mchmid | 是 | int | 商戶授權接口獲取到的門店ID |
總金額 | total | 是 | String | 支付總金額 單位:元 最小金額0.01元 不允許包含任何字、 符號 |
付款碼 | auth_code | 是 | String | 掃碼支付授權碼, 設備讀取用戶展示的條碼 或者二維碼信息 |
終端號 | terminal_number | 是 | String | pos端生成 |
第一步: 把需要傳輸的參數封裝成一個對象:
package com.ujiuye.xml;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.TreeMap;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import cn.hutool.core.util.XmlUtil;
public class RequestData {
/**
* 商戶授權接口獲取到的商家ID
*/
private Integer mchuid;
/**
* 商戶授權接口獲取到的門店ID
*/
private Integer mchmid;
/**
* 支付總金額 單位:元 最小金額0.01元 不允許包含任何字、 符號
*/
private String total;
/**
* 掃碼支付授權碼, 設備讀取用戶展示的條碼 或者二維碼信息
*/
private String auth_code;
/**
* pos端生成
*/
private String terminal_number;
/**
* 把請求參數解析成xml文件
* <response>
* <total>
* 180
* </total
* </response>
*/
public static String getXml(RequestData requestData) {
Document document = XmlUtil.createXml();//創建XML文件
document.setXmlStandalone(true);//單獨文件,無需驗證
Element root = document.createElement("response");//創建根節點
try {
Class<? extends RequestData> requestDataClass = requestData.getClass();
Field[] declaredFields = requestDataClass.getDeclaredFields();
//簽名需要對數據進行排序: 使用SortedMap
Map<String, String> signData = new TreeMap<>();
for (Field field : declaredFields) {
field.setAccessible(true);
signData.put(field.getName().toString(), field.get(requestData).toString());
}
//遍歷map生成XML文檔
for (Map.Entry<String, String> entry : signData.entrySet()) {
Element element = document.createElement(entry.getKey());
element.setTextContent(entry.getValue());
root.appendChild(element);//創建的新節點添加到根節點
}
} catch (Exception e) {
e.printStackTrace();
}
document.appendChild(root);//把根節點添加的document
System.out.println("構建的XML文件內容:\n" + XmlUtil.toStr(document));
return XmlUtil.toStr(document);
}
//生成getter、setter方法和無參、有參構造方法
}
lombok插件的安裝 可以幫助我們生成getter、setter、無參構造、有參構造、toString等方法,簡化編碼。
單步測試, 注意從test1方法到test2方法再到test3方法。
package com.ujiuye.xml;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.TreeMap;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import cn.hutool.core.util.XmlUtil;
public class RequestDataTest {
//思考題: 所有的屬性安裝字典順序排序生成xml文件,ASCII
@Test
public void test3() throws Exception {
//創建XML文檔
Document document = XmlUtil.createXml();
//創建根節點
Element root = document.createElement("response");
//遍歷對象的所有屬性
RequestData data = new RequestData(1001,123456,"180","2342894234835234","6666");
//反射Class對象,Class是反射的入口,照妖鏡
Class<?> clazz = data.getClass();
//獲取獲取所有的屬性
Field [] fileds = clazz.getDeclaredFields();
//遍歷所有的屬性
//創建一個有序的map
Map<String,String> map = new TreeMap<>();
for (Field field : fileds) {
//Accessible adj. 易接近的;可進入的;可理解的
field.setAccessible(true);//破門而入,強制訪問 set設置,get獲取
System.out.println(field.getName() + "-->" + field.get(data));
map.put(field.getName(), field.get(data).toString());
}
//把map中有序的數據寫到xml文件
for(Map.Entry<String, String> entry : map.entrySet() ) {
//每一個屬性封裝成一個節點
Element element = document.createElement( entry.getKey() );
element.setTextContent(entry.getValue());
//把當前節點加入到root
root.appendChild(element);
}
System.out.println(map);
//把root添加到xml文件
document.appendChild(root);
//輸出文件
System.out.println(XmlUtil.toStr(document));
}
@Test
public void test2() throws Exception {
//創建XML文檔
Document document = XmlUtil.createXml();
//創建根節點
Element root = document.createElement("response");
//遍歷對象的所有屬性
RequestData data = new RequestData(1001,123456,"180","2342894234835234","6666");
//反射Class對象,Class是反射的入口,照妖鏡
Class<?> clazz = data.getClass();
//獲取獲取所有的屬性
Field [] fileds = clazz.getDeclaredFields();
//遍歷所有的屬性
for (Field field : fileds) {
//Accessible adj. 易接近的;可進入的;可理解的
field.setAccessible(true);//破門而入,強制訪問 set設置,get獲取
System.out.println(field.getName() + "-->" + field.get(data));
//每一個屬性封裝成一個節點
Element element = document.createElement( field.getName() );
element.setTextContent(field.get(data).toString());
//把當前節點加入到root
root.appendChild(element);
}
//把root添加到xml文件
document.appendChild(root);
//輸出文件
System.out.println(XmlUtil.toStr(document));
}
@Test
public void test1() throws Exception {
//遍歷對象的所有屬性
RequestData data = new RequestData(1001,123456,"180","2342894234835234","6666");
//反射Class對象,Class是反射的入口,照妖鏡
Class<?> clazz = data.getClass();
//獲取獲取所有的屬性
Field [] fileds = clazz.getDeclaredFields();
//遍歷所有的屬性
for (Field field : fileds) {
//Accessible adj. 易接近的;可進入的;可理解的
field.setAccessible(true);//破門而入,強制訪問 set設置,get獲取
System.out.println(field.getName() + "-->" + field.get(data));
}
}
}
微信支付簽名:
Hutool工具包應用
糊塗的意思,重點學習日期工具類、XML工具類、HTTP請求的工具類。
Maven官網
DTD&Schema
XML文件是不同系統之間傳輸數據的格式,有個問題: XML文件使用哪些標籤、標籤有哪些屬性、標籤有哪些子標籤這些需要事先定義好的;否則不同系統無法傳輸並解析XML文件。爲了解決這個問題, 產生了兩種XML約束的規範:
- DTD document type defination 文檔類型定義
- Schema XML模式,也是定義XML的規範
DTD案例
mybatis的配置文件:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<typeAlias type="com.news.entity.Dept" alias="Dept"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql:///db1" />
<property name="username" value="root"/>
<property name="password" value="admin"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/news/entity/deptMapper.xml" />
</mappers>
</configuration>
該XML文件的DTD約束是: http://mybatis.org/dtd/mybatis-3-config.dtd
<?xml version="1.0" encoding="UTF-8" ?>
<!-- 定義了該XML文件可以出現的節點名稱 -->
<!ELEMENT configuration (properties?, settings?, typeAliases?, typeHandlers?, objectFactory?, objectWrapperFactory?, plugins?, environments?, databaseIdProvider?, mappers?)>
<!ELEMENT databaseIdProvider (property*)>
<!ATTLIST databaseIdProvider
type CDATA #REQUIRED
>
<!ELEMENT properties (property*)>
<!-- attribute list 屬性列表可以出現的屬性: resource和url -->
<!ATTLIST properties
resource CDATA #IMPLIED
url CDATA #IMPLIED
>
Schema約束
Spring的配置文件就是使用Schema約束,創建web項目的web.xml文件也是使用Schema約束,Schema逐步替換DTD
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>chapter12</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
web.xml文件的約束就是: http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd,這是一個schema約束文件。schema相比較DTD有更好語義支持,可以定義數據類型;一些開源框架都是使用schema定義XML文件的約束。
HTTP協議
簡介:
http是一個簡單的請求-響應協議,它通常運行在TCP之上。它指定了客戶端可能發送給服務器什麼樣的消息以及得到什麼樣的響應。請求和響應消息的頭以ASCII碼形式給出;而消息內容則具有一個類似MIME的格式。這個簡單模型是早期Web成功的有功之臣,因爲它使得開發和部署是那麼的直截了當。
工作原理
HTTP是基於客戶/服務器模式,且面向連接的。典型的HTTP事務處理有如下的過程:
(1)客戶與服務器建立連接;
(2)客戶向服務器提出請求;
(3)服務器接受請求,並根據請求返回相應的文件作爲應答;
(4)客戶與服務器關閉連接。
客戶與服務器之間的HTTP連接是一種一次性連接,它限制每次連接只處理一個請求,當服務器返回本次請求的應答後便立即關閉連接,下次請求再重新建立連接。這種一次性連接主要考慮到WWW服務器面向的是Internet中成幹上萬個用戶,且只能提供有限個連接,故服務器不會讓一個連接處於等待狀態,及時地釋放連接可以大大提高服務器的執行效率。 [8]
HTTP是一種無狀態協議,即服務器不保留與客戶交易時的任何狀態。這就大大減輕了服務器記憶負擔,從而保持較快的響應速度。HTTP是一種面向對象的協議。允許傳送任意類型的數據對象。它通過數據類型和長度來標識所傳送的數據內容和大小,並允許對數據進行壓縮傳送。當用戶在一個HTML文檔中定義了一個超文本鏈後,瀏覽器將通過TCP/IP協議與指定的服務器建立連接。 [8]
從技術上講是客戶在一個特定的TCP端口(端口號一般爲80)上打開一個套接字。如果服務器一直在這個周知的端口上傾聽連接,則該連接便會建立起來。然後客戶通過該連接發送一個包含請求方法的請求塊。
HTTP規範定義了9種請求方法,每種請求方法規定了客戶和服務器之間不同的信息交換方式,常用的請求方法是GET和POST。服務器將根據客戶請求完成相應操作,並以應答塊形式返回給客戶,最後關閉連接。
常規
請求URL: 請求的地址
請求方法: get post
狀態代碼: 302
遠程地址: 服務器地址
引用站點策略: 沒有引用,直接通過瀏覽器地址訪問的
響應頭
Connection: 連接
Content-Length: 內容長度
Date: 時間
Keep-Alive: 20毫秒
Location: 地址