說明
最近在看一本java web和tomcat技術介紹的書籍。故此,希望通過文字總結的方式總結自己學習所獲,本篇主要介紹java實現web基本的信息瀏覽的方法原理。
web的本質
由於技術能力有限,或許我的表述存在某些問題,僅供參考。web網頁技術其本質包括三個要素:訪問用戶、瀏覽器(軟件)、訪問地址(Url).三個基本的要素構成了一次簡單的網頁瀏覽的過程。其中訪問用戶爲數據被動接收者,瀏覽器爲數據加工者(根據既定規則展示數據),訪問地址爲數據獲取(也可以理解爲數據提供方)。由此可見,web的基礎就是對於數據的獲取和數據的展示,展示本篇不做介紹,主要介紹瀏覽器如何通過url獲取網頁數據的。
web實現
web構成主要就兩個部分:服務端和客戶端。而web的訪問其實就是一次簡單的net間的數據傳輸,web是基於TCP/IP協議簇的HTTP來規範通信過程,而基本的通信過程其實就是一次tcp方式連接get的請求過程。瀏覽器通過get方式獲取當前的瀏覽信息(html或者其他資源文件信息)。如下,簡單介紹有關http協議的的基本格式信息內容以及如何通過java程序模擬實現一次簡單的網頁訪問。
1) HTTP協議
HTTP(HyperText Transfer Protocol)爲超文本傳輸協議,這是萬維網通信文件均需要遵循的標準。初期是爲了專門處理超文本(html)數據傳輸的方法,後來慢慢規範,現在已經成爲網絡通信的一個基礎的請求應答通信協議,成爲首選的通信協議。HTTP規範了net請求過程中數據格式,規定了請求數據和響應數據格式。HTTP主要將通信數據分爲三個部分方法(method)、頭部(Header)、正文(Body)其中通過”\r\n”將正文與方法和頭部進行分離。如下簡單介紹一些常用的請求格式:
請求格式
請求格式分爲三個部分組成:請求方法、請求頭、請求體,如下給出一個簡單的請求格式示例:GET / HTTP/1.1 Host: www.enjoytoday.cn Connection: keep-alive Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36 Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Referer: http://www.enjoytoday.cn/posts/326 Accept-Encoding: gzip, deflate, sdch Accept-Language: zh-CN,zh;q=0.8 Cookie: bdshare_firstime=1466032270994; UM_distinctid=15c4ef2ac4e2e4-0d13269271b947-1b2a120b-1fa400-15c4ef2ac4f7b5; un=aGZjYWk=; comment_author=aGZjYWk=; [email protected]; comment_author_url=http://www.enjoytoday.cn; c_id=dUhIaTlndmc4MVVYbjRQTGxMRTotMTpFODg3QjgzQjg1NjgxQjQxRUYxNjg2QzJFRkMyQjI2QQ==; JSESSIONID=ADBC8C3DADF6C815D778450C193C6637.ajp13_worker; Hm_lvt_ce55bfda158556585a8b7b246346c8ba=1498560244,1498739070,1498833193,1498917432; Hm_lpvt_ce55bfda158556585a8b7b246346c8ba=1498917597; CNZZDATA1262047894=1598545996-1495973145-%7C1498917578 username=hfcai&sex=man
如上,首行爲請求方法、URI、和http協議版本號;請求頭爲和請求正文以及請求返回信息相關的一一些信息,包括數據編碼、請求agent、連接類型、接受數據類型等。
響應格式
響應格式也是由三部分組成:相應狀態碼、響應頭、響應體。其格式如下所示:HTTP/1.1 200 OK Date: Sat, 01 Jul 2017 14:51:26 GMT Server: Apache/2.4.7 (Ubuntu) Set-Cookie: JSESSIONID=84C993F5E433C4DE9BFBA57150FFC065.ajp13_worker;path=/;HttpOnly Content-Language: zh-CN Vary: Accept-Encoding Content-Encoding: gzip Content-Length: 7333 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html;charset=UTF-8 <html> <head> <title>title of html.</html> </head> <body> <h1>Hello world!</h1> </body> </html>
如上,首行爲Http協議版本號和返回狀態碼、返回描述信息(狀態碼由3位數字組成,200爲成功接收返回),響應頭包括服務器使用的服務容器類型版本、響應體數據類型、編碼、長度等信息,最後響應體就是我們需要請求返回的數據,url訪問返回的也就是html文本信息了。
2) Java實現一個簡單的url訪問web
爲了能讓瀏覽器通過url直接訪問到我們的網頁,我們需要通過java完成一個socket服務端,來模擬返回,代碼如下:
public class HTTPServer {
public static void main(String[] args) {
int port=9000;
if (args!=null && args.length>0 && args[0]!=null && args[0].trim().length()>0) {
port=Integer.parseInt(args[0]);
}
ServerSocket serverSocket=null;
try {
serverSocket=new ServerSocket(port);
System.out.printf("[*] Listener success,and address %s",serverSocket.getLocalSocketAddress().toString());
while (true) {
Socket socket=serverSocket.accept();
System.out.printf("[*]Receiver Request,from %s:%d",socket.getInetAddress().getHostAddress(),socket.getPort());
handl_client(socket);
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
System.out.printf("[*] Listener failed,and address %s",serverSocket.getLocalSocketAddress().toString());
try {
serverSocket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
private static void handl_client(Socket socket) throws Exception{
DataInputStream dataInputStream=new DataInputStream(socket.getInputStream());
DataOutputStream outputStream=new DataOutputStream(socket.getOutputStream());
int size=dataInputStream.read();
byte[] bs=new byte[size];
dataInputStream.read(bs);
String request=new String(bs);
System.out.println("[*]Request content is:"+request);
String requestParams=request.substring(0,request.indexOf("\r\n")).split(" ")[1];
String contentType;
if (requestParams.indexOf("html") !=-1 || requestParams.indexOf("htm")!=-1){
contentType="text/html";
}else if(requestParams.indexOf("jpg")!=-1 || requestParams.indexOf("jpeg")!=-1) {
contentType="image/jpeg";
}else if(requestParams.indexOf("gif")!=-1){
contentType="image/gif";
}else {
contentType="application/octet-stream";
}
String firstLine="HTTP/1.1 200 ok\r\n";
String responseHeader="Content-Type:"+contentType+"\r\n\r\n";
InputStream in=HttpServer.class.getResourceAsStream("html"+File.separator+requestParams);
outputStream.write(firstLine.getBytes());
outputStream.write(responseHeader.getBytes());
int len=0;
bs=new byte[128];
if (in!=null) {
while ((len=in.read(bs))!=-1) {
outputStream.write(bs,0,len);
}
}
in.close();
outputStream.close();
dataInputStream.close();
socket.close();
}
}
編譯生成HTTPServer.class 運行監聽請求,通過瀏覽器訪問:http://localhost:9000/index.html, 瀏覽器返回顯示如下: