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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

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

Jodd 是一個開源的 Java 工具集, 包含一些實用的工具類和小型框架。簡單,卻很強大!

jodd-http是一個輕巧的HTTP客戶端。現在我們以一個簡單的示例從源碼層看看是如何實現的?

 HttpRequest httpRequest = HttpRequest.get("http://jodd.org"); //1. 構建一個get請求HttpResponse response = httpRequest.send(); //2.發送請求并接受響應信息System.out.println(response);//3.打印響應信息

構建一個get請求

先復習一下http請求報文的格式:

下圖展示一般請求所帶有的屬性

調用get方法構建http請求:

/*** 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;}

上述方法,根據destination解析出一下幾個部分:

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

2. 協議:http或者https

3. 主機:請求的服務器地址

4. 端口:請求的服務器端口

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

/*** 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;}

發送請求

先熟悉一下http響應報文的格式:

響應首部一般包含如下內容:

/*** {@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;}

判斷是否有連接,若沒有連接則創建一個新的連接。

2. 創建連接實現

/*** 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. 創建socket

  根據協議的不同,http使用SocketFactory創建socket,https使用SSLSocketFactory創建SSLSocket。最終使用SocketHttpConnection進行包裝。

SocketHttpConnection繼承自HttpConnection,實現了socket的輸入輸出流連接。注意:https創建完SSLSocket時需要進行握手。

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的輸出流發送信息,打開connection的輸入流接受返回信息。

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

發送過程:

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();}

將緩沖區的數據寫入輸出流,并發送。

接受數據并讀取報文內容:

/*** 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;}

小結

? 從上面的代碼,我們可以看出http使用socket來建立和destination的連接,然后通過連接的輸出流和輸入流來進行通信。

參考文獻:

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

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

轉載于:https://www.cnblogs.com/davidwang456/p/4569283.html

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。