Skip to main content

19 关于在java中http的基本使用示例

1 本文的目标是什么?

  • 理解http的是什么?
  • 和在java中的示例代码

2 准备工作

名称必要文中示例说明
java 17如果没有可以去官网下载。
SprintBoot 3.0示例的代码都将写在这里, 如果没有可以去官网下载。
ncNetcat ( nc ) 一个命令行网络测试工具,本文中用启用一个tcp服务器并演示http的报文格式
curl一个命令行的请求工具,本文中用于在终端中演示http客户端并发起请求
git版本控制工具

3 什么是http?

http是一个文本文件,每发起一个请求就是上传一个文本到服务器那边,那服务器那边的响应也等同于下载回了一个文本文件, 而这所以叫http是因为这个文件 定义的格式与其它协议不同,而http的报文格式为,请求行,请求头和请求体, 如以下是一人Post请求:

http的文本数据示例格式
POST / HTTP/1.1                         // <-- 1 首行记录请求方式和版本号 格式是固定的: 请求方式 路由 HTTP/版本号
Host: localhost:1234 // <-- 2 从第二行开始到\r\n\r\n结束为请求头部,这部分数据是属于说明作用,可根据需要自由扩展
User-Agent: curl/7.79.1
Accept: */*
Content-Type: application/json // 解释了请求体的数据格式为json
Content-Length: 15 // 解释了请求体数据长度为: 15

{"key":"value"} // <-- 3 请求体的数据
step 1: 用nc在本地启动tcp服务并监听1234端口
用nc在本地启动tcp服务并监听1234端口
$ nc -l 1234  # <-- 1 启用服务
POST / HTTP/1.1 # <-- 2 接收到的http的post请求文本数据
Host: localhost:1234
User-Agent: curl/7.79.1
Accept: */*
Content-Type: application/json
Content-Length: 15

{"key":"value"}

step 2: 打开新的终端并发出post请求过去
向本地发起post请求
$ curl -X POST http://localhost:1234 -H 'Content-Type: application/json' -d '{"key":"value"}'

4 在java中http请求是如何实现的?

4.1 Get请求的演示

4.1.1 服务端代码

服务端Get请求服务
src/main/java/com/wuchuheng/java/http_demo_java/controllers/HttpRequestDemo.java
package com.wuchuheng.java.http_demo_java.controllers;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.Map;

@Controller
@Slf4j
public class HttpRequestDemo {
/**
* Get 请求/
*/
@GetMapping("/")
public ResponseEntity<String> getRequest(
@RequestHeader Map<String, String> headers,
@RequestParam Map<String, String> params
) {
headers.forEach((key, value) -> {
log.info("header value: key: {}, value: {}", key, value);
});
params.forEach((key, value) -> {
log.info("params: key: {}, value: {}", key, value);
});

return ResponseEntity
.ok()
.header("custom-field", "custom-value")
.body( "Hello world");
}
}
接收请求后打印内容
2022-11-28T05:27:03.988+08:00  INFO 7022 --- [nio-8080-exec-6] c.w.j.h.controllers.HttpRequestDemo      : header value: key: user-agent, value: Java/17.0.2
2022-11-28T05:27:03.988+08:00 INFO 7022 --- [nio-8080-exec-6] c.w.j.h.controllers.HttpRequestDemo : header value: key: host, value: localhost:8080
2022-11-28T05:27:03.988+08:00 INFO 7022 --- [nio-8080-exec-6] c.w.j.h.controllers.HttpRequestDemo : header value: key: accept, value: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
2022-11-28T05:27:03.988+08:00 INFO 7022 --- [nio-8080-exec-6] c.w.j.h.controllers.HttpRequestDemo : header value: key: connection, value: keep-alive
2022-11-28T05:27:03.988+08:00 INFO 7022 --- [nio-8080-exec-6] c.w.j.h.controllers.HttpRequestDemo : params: key: bar, value: 2
2022-11-28T05:27:03.988+08:00 INFO 7022 --- [nio-8080-exec-6] c.w.j.h.controllers.HttpRequestDemo : params: key: foo, value: 1
2022-11-28T05:30:55.532+08:00 INFO 7022 --- [io-8080-exec-10] o.apache.coyote.http11.Http11Processor : Error parsing HTTP request header

4.1.2 发起请求

客户端必起请求
src/test/java/com/wuchuheng/java/http_demo_java/HttpGetMethodRequestTest.java
package com.wuchuheng.java.http_demo_java;

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;


import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@SpringBootTest
@Slf4j
public class HttpGetMethodRequestTest {

/**
* 把Map数据转换为url格式上的数据
* @param params
* @return
* @throws UnsupportedEncodingException
*/
public String convertParamsToUrlParams(Map<String, String> params) throws UnsupportedEncodingException {
StringBuilder result = new StringBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) {
result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
result.append("=");
result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
result.append("&");
}

String resultString = result.toString();
return resultString.length() > 0
? resultString.substring(0, resultString.length() - 1)
: resultString;
}


/**
* Get 请求测试
*/
@Test
void httpGetTest() throws IOException {
// 1 请求参数url序列化
Map<String, String> params = new HashMap<>();
params.put("foo", "1");
params.put("bar", "2");
String paramsUrlStr = convertParamsToUrlParams(params);
URL obj = new URL("http://localhost:8080/?" + paramsUrlStr);
// 2 TCP 连接handler
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// 3 GET 请求方式
con.setRequestMethod("GET");
con.setDoInput(true);
// 4 响应头部
Map<String, List<String>> headers = con.getHeaderFields();
// 5 响应状态码
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader( new InputStreamReader(con.getInputStream()));
String inputLine;
// 6 响应内容
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
// 7 关闭连接和缓存
in.close();
con.disconnect();
System.out.println(responseCode);
System.out.println(headers);
System.out.println(response);
}
}

输入结果
200
{Keep-Alive=[timeout=60], null=[HTTP/1.1 200], custom-field=[custom-value], Connection=[keep-alive], Content-Length=[11], Date=[Sun, 27 Nov 2022 21:27:03 GMT], Content-Type=[text/html;charset=UTF-8]}
Hello world

4.1.3 提交代码

提交代码
$ git add -A  &&  git commit -m 'feat: 实现GET功能和测试用例'
[master 2576c58] feat: 实现GET功能和测试用例
3 files changed, 112 insertions(+)
create mode 100644 src/main/java/com/wuchuheng/java/http_demo_java/controllers/HttpRequestDemo.java
create mode 100644 src/test/java/com/wuchuheng/java/http_demo_java/HttpGetMethodRequestTest.java

4.2 Post请求的演示

4.2.1 服务端代码

服务端代码
Post请求代码 src/main/java/com/wuchuheng/java/http_demo_java/controllers/HttpRequestDemo.java
// ...
/**
* Post 请求/
*/
@PostMapping("/")
public ResponseEntity<String> PostRequest(
@RequestHeader Map<String, String> headers,
@RequestParam Map<String, String> params,
@RequestBody Object body
) {
headers.forEach((key, value) -> {
log.info("header value: key: {}, value: {}", key, value);
});
params.forEach((key, value) -> {
log.info("params: key: {}, value: {}", key, value);
});
log.info("body: {}", body);

return ResponseEntity
.ok()
.header("custom-field", "custom-value")
.body( "Hello world");
}

// ...


4.2.2 post请求代码

Post请求代码
src/test/java/com/wuchuheng/java/http_demo_java/HttpGetMethodRequestTest.java
// ...
@Test
void httpPostTest() throws IOException {
// 1 请求参数url序列化
Map<String, String> params = new HashMap<>();
params.put("foo", "1");
params.put("bar", "2");
String paramsUrlStr = convertParamsToUrlParams(params);
URL obj = new URL("http://localhost:8080/?" + paramsUrlStr);
// 2 TCP 连接handler
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setDoOutput(true);
// 3 GET 请求方式
con.setRequestMethod("POST");
con.setDoInput(true);
con.setRequestProperty("Content-Type", "application/json");
// 3.1 设置请求体参数
String requestBodyJson = "{\"body1\": 1, \"body2\": 2}";
DataOutputStream out = new DataOutputStream(con.getOutputStream());
out.writeBytes(requestBodyJson);
out.flush();
out.close();
// 4 获取响应头部
Map<String, List<String>> headers = con.getHeaderFields();
// 5 获取响应状态码
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader( new InputStreamReader(con.getInputStream()));
String inputLine;
// 6 获取响应内容
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
// 7 关闭连接和缓存
in.close();
con.disconnect();
System.out.println(responseCode);
System.out.println(headers);
System.out.println(response);
}
// ...

4.1.3 提交代码

post请求变动的代码
diff --git a/src/main/java/com/wuchuheng/java/http_demo_java/controllers/HttpRequestDemo.java b/src/main/java/com/wuchuheng/java/http_demo_java/controllers/HttpRequestDemo.java
index b0d3112..6480da9 100644
--- a/src/main/java/com/wuchuheng/java/http_demo_java/controllers/HttpRequestDemo.java
+++ b/src/main/java/com/wuchuheng/java/http_demo_java/controllers/HttpRequestDemo.java
@@ -3,9 +3,7 @@ package com.wuchuheng.java.http_demo_java.controllers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestHeader;
-import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.*;

import java.util.Map;

@@ -32,4 +30,27 @@ public class HttpRequestDemo {
.header("custom-field", "custom-value")
.body( "Hello world");
}
+
+ /**
+ * Post 请求/
+ */
+ @PostMapping("/")
+ public ResponseEntity<String> PostRequest(
+ @RequestHeader Map<String, String> headers,
+ @RequestParam Map<String, String> params,
+ @RequestBody Object body
+ ) {
+ headers.forEach((key, value) -> {
+ log.info("header value: key: {}, value: {}", key, value);
+ });
+ params.forEach((key, value) -> {
+ log.info("params: key: {}, value: {}", key, value);
+ });
+ log.info("body: {}", body);
+
+ return ResponseEntity
+ .ok()
+ .header("custom-field", "custom-value")
+ .body( "Hello world");
+ }
}
diff --git a/src/test/java/com/wuchuheng/java/http_demo_java/HttpGetMethodRequestTest.java b/src/test/java/com/wuchuheng/java/http_demo_java/HttpGetMethodRequestTest.java
index 8925e08..47c67ad 100644
--- a/src/test/java/com/wuchuheng/java/http_demo_java/HttpGetMethodRequestTest.java
+++ b/src/test/java/com/wuchuheng/java/http_demo_java/HttpGetMethodRequestTest.java
@@ -73,4 +73,44 @@ public class HttpGetMethodRequestTest {
System.out.println(headers);
System.out.println(response);
}
+
+ @Test
+ void httpPostTest() throws IOException {
+ // 1 请求参数url序列化
+ Map<String, String> params = new HashMap<>();
+ params.put("foo", "1");
+ params.put("bar", "2");
+ String paramsUrlStr = convertParamsToUrlParams(params);
+ URL obj = new URL("http://localhost:8080/?" + paramsUrlStr);
+ // 2 TCP 连接handler
+ HttpURLConnection con = (HttpURLConnection) obj.openConnection();
+ con.setDoOutput(true);
+ // 3 GET 请求方式
+ con.setRequestMethod("POST");
+ con.setDoInput(true);
+ con.setRequestProperty("Content-Type", "application/json");
+ // 3.1 设置请求体参数
+ String requestBodyJson = "{\"body1\": 1, \"body2\": 2}";
+ DataOutputStream out = new DataOutputStream(con.getOutputStream());
+ out.writeBytes(requestBodyJson);
+ out.flush();
+ out.close();
+ // 4 获取响应头部
+ Map<String, List<String>> headers = con.getHeaderFields();
+ // 5 获取响应状态码
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader( new InputStreamReader(con.getInputStream()));
+ String inputLine;
+ // 6 获取响应内容
+ StringBuilder response = new StringBuilder();
+ while ((inputLine = in.readLine()) != null) {
+ response.append(inputLine);
+ }
+ // 7 关闭连接和缓存
+ in.close();
+ con.disconnect();
+ System.out.println(responseCode);
+ System.out.println(headers);
+ System.out.println(response);
+ }
}
代码提交
$ git add -A
$ git commit -m 'feat: 实现POST功能和测试用例'
[master d164653] feat: 实现POST功能和测试用例
2 files changed, 64 insertions(+), 3 deletions(-)

参考资料