日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

简约之美Jodd-http--深入源码理解http协议

發(fā)布時(shí)間:2025/4/5 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 简约之美Jodd-http--深入源码理解http协议 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Jodd 是一個(gè)開源的 Java 工具集, 包含一些實(shí)用的工具類和小型框架。簡(jiǎn)單,卻很強(qiáng)大!

jodd-http是一個(gè)輕巧的HTTP客戶端。現(xiàn)在我們以一個(gè)簡(jiǎn)單的示例從源碼層看看是如何實(shí)現(xiàn)的?

 HttpRequest httpRequest = HttpRequest.get("http://jodd.org"); //1. 構(gòu)建一個(gè)get請(qǐng)求HttpResponse response = httpRequest.send(); //2.發(fā)送請(qǐng)求并接受響應(yīng)信息System.out.println(response);//3.打印響應(yīng)信息

構(gòu)建一個(gè)get請(qǐng)求

先復(fù)習(xí)一下http請(qǐng)求報(bào)文的格式:

下圖展示一般請(qǐng)求所帶有的屬性

調(diào)用get方法構(gòu)建http請(qǐng)求:

/*** Builds a GET request.*/public static HttpRequest get(String destination) {return new HttpRequest().method("GET").set(destination);}

method方法如下:

/*** Specifies request method. It will be converted into uppercase.*/public HttpRequest method(String method) {this.method = method.toUpperCase();return this;}

set方法如下:

/*** Sets the destination (method, host, port... ) at once.*/public HttpRequest set(String destination) {destination = destination.trim();// http methodint ndx = destination.indexOf(' ');if (ndx != -1) {method = destination.substring(0, ndx).toUpperCase();destination = destination.substring(ndx + 1);}// protocol ndx = destination.indexOf("://");if (ndx != -1) {protocol = destination.substring(0, ndx);destination = destination.substring(ndx + 3);}// host ndx = destination.indexOf('/');if (ndx == -1) {ndx = destination.length();}if (ndx != 0) {host = destination.substring(0, ndx);destination = destination.substring(ndx);// port ndx = host.indexOf(':');if (ndx == -1) {port = DEFAULT_PORT;} else {port = Integer.parseInt(host.substring(ndx + 1));host = host.substring(0, ndx);}}// path + query path(destination);return this;}

上述方法,根據(jù)destination解析出一下幾個(gè)部分:

1. 方法:HTTP1.1支持7種請(qǐng)求方法:GET、POST、HEAD、OPTIONS、PUT、DELETE和TARCE。

2. 協(xié)議:http或者h(yuǎn)ttps

3. 主機(jī):請(qǐng)求的服務(wù)器地址

4. 端口:請(qǐng)求的服務(wù)器端口

5. 路徑+查詢參數(shù),其中參數(shù)以“?”開頭,使用“&”連接

/*** Sets request path. Query string is allowed.* Adds a slash if path doesn't start with one.* Query will be stripped out from the path.* Previous query is discarded.* @see #query()*/public HttpRequest path(String path) {// this must be the only place that sets the pathif (path.startsWith(StringPool.SLASH) == false) {path = StringPool.SLASH + path;}int ndx = path.indexOf('?');if (ndx != -1) {String queryString = path.substring(ndx + 1);path = path.substring(0, ndx);query = HttpUtil.parseQuery(queryString, true);} else {query = HttpValuesMap.ofObjects();}this.path = path;return this;}

發(fā)送請(qǐng)求

先熟悉一下http響應(yīng)報(bào)文的格式:

響應(yīng)首部一般包含如下內(nèi)容:

/*** {@link #open() Opens connection} if not already open, sends request,* reads response and closes the request. If keep-alive mode is enabled* connection will not be closed.*/public HttpResponse send() {if (httpConnection == null) { open();}// prepare http connectionif (timeout != -1) {httpConnection.setTimeout(timeout);}// sends data HttpResponse httpResponse;try {OutputStream outputStream = httpConnection.getOutputStream();sendTo(outputStream);InputStream inputStream = httpConnection.getInputStream();httpResponse = HttpResponse.readFrom(inputStream);httpResponse.assignHttpRequest(this);} catch (IOException ioex) {throw new HttpException(ioex);}boolean keepAlive = httpResponse.isConnectionPersistent();if (keepAlive == false) {// closes connection if keep alive is false, or if counter reached 0 httpConnection.close();httpConnection = null;}return httpResponse;}

?

1. 打開HttpConnection

/*** Opens a new {@link HttpConnection connection} using* {@link JoddHttp#httpConnectionProvider default connection provider}.*/public HttpRequest open() {return open(JoddHttp.httpConnectionProvider);}/*** Opens a new {@link jodd.http.HttpConnection connection}* using given {@link jodd.http.HttpConnectionProvider}.*/public HttpRequest open(HttpConnectionProvider httpConnectionProvider) {if (this.httpConnection != null) {throw new HttpException("Connection already opened");}try {this.httpConnectionProvider = httpConnectionProvider;this.httpConnection = httpConnectionProvider.createHttpConnection(this);} catch (IOException ioex) {throw new HttpException(ioex);}return this;}

判斷是否有連接,若沒(méi)有連接則創(chuàng)建一個(gè)新的連接。

2. 創(chuàng)建連接實(shí)現(xiàn)

/*** Creates new connection from current {@link jodd.http.HttpRequest request}.** @see #createSocket(String, int)*/public HttpConnection createHttpConnection(HttpRequest httpRequest) throws IOException {Socket socket;if (httpRequest.protocol().equalsIgnoreCase("https")) {SSLSocket sslSocket = createSSLSocket(httpRequest.host(), httpRequest.port());sslSocket.startHandshake();socket = sslSocket;} else {socket = createSocket(httpRequest.host(), httpRequest.port());}return new SocketHttpConnection(socket);}

3. 創(chuàng)建socket

  根據(jù)協(xié)議的不同,http使用SocketFactory創(chuàng)建socket,https使用SSLSocketFactory創(chuàng)建SSLSocket。最終使用SocketHttpConnection進(jìn)行包裝。

SocketHttpConnection繼承自HttpConnection,實(shí)現(xiàn)了socket的輸入輸出流連接。注意:https創(chuàng)建完SSLSocket時(shí)需要進(jìn)行握手。

public class SocketHttpConnection implements HttpConnection {protected final Socket socket;public SocketHttpConnection(Socket socket) {this.socket = socket;}public OutputStream getOutputStream() throws IOException {return socket.getOutputStream();}public InputStream getInputStream() throws IOException {return socket.getInputStream();}public void close() {try {socket.close();} catch (IOException ignore) {}}public void setTimeout(int milliseconds) {try {socket.setSoTimeout(milliseconds);} catch (SocketException sex) {throw new HttpException(sex);}}/*** Returns <code>Socket</code> used by this connection.*/public Socket getSocket() {return socket;} }

?打開Connection的輸出流發(fā)送信息,打開connection的輸入流接受返回信息。

OutputStream outputStream = httpConnection.getOutputStream();sendTo(outputStream);InputStream inputStream = httpConnection.getInputStream();

發(fā)送過(guò)程:

protected HttpProgressListener httpProgressListener;/*** Sends request or response to output stream.*/public void sendTo(OutputStream out) throws IOException {Buffer buffer = buffer(true);if (httpProgressListener == null) {buffer.writeTo(out);}else {buffer.writeTo(out, httpProgressListener);}out.flush();}

將緩沖區(qū)的數(shù)據(jù)寫入輸出流,并發(fā)送。

接受數(shù)據(jù)并讀取報(bào)文內(nèi)容:

/*** Reads response input stream and returns {@link HttpResponse response}.* Supports both streamed and chunked response.*/public static HttpResponse readFrom(InputStream in) {InputStreamReader inputStreamReader;try { inputStreamReader = new InputStreamReader(in, StringPool.ISO_8859_1);} catch (UnsupportedEncodingException ignore) {return null;}BufferedReader reader = new BufferedReader(inputStreamReader);HttpResponse httpResponse = new HttpResponse();// the first line String line;try {line = reader.readLine();} catch (IOException ioex) {throw new HttpException(ioex);}if (line != null) {line = line.trim();int ndx = line.indexOf(' ');httpResponse.httpVersion(line.substring(0, ndx));int ndx2 = line.indexOf(' ', ndx + 1);if (ndx2 == -1) {ndx2 = line.length();}httpResponse.statusCode(Integer.parseInt(line.substring(ndx, ndx2).trim()));httpResponse.statusPhrase(line.substring(ndx2).trim());}httpResponse.readHeaders(reader);httpResponse.readBody(reader);return httpResponse;}

小結(jié)

? 從上面的代碼,我們可以看出http使用socket來(lái)建立和destination的連接,然后通過(guò)連接的輸出流和輸入流來(lái)進(jìn)行通信。

參考文獻(xiàn):

【1】http://www.it165.net/admin/html/201403/2541.html

【2】http://jodd.org/doc/http.html

轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/p/4569283.html

總結(jié)

以上是生活随笔為你收集整理的简约之美Jodd-http--深入源码理解http协议的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。