Java Python:从简单案例理解 HTTP 服务开发与调用!

ops/2025/1/18 12:53:05/

HTTP__1">使用 Java 和 Python 实现 HTTP 服务创建和调用

在现代网络应用开发中,创建和调用 HTTP 服务是一项基本技能。本文将详细介绍如何使用 Java 和 Python 语言实现一个简单的 HTTP 服务,并展示如何使用相应语言的客户端代码对其进行调用和测试。我们将实现一个用户管理服务,包括用户的创建、读取、更新和删除操作。

一、Java 实现

HTTP__7">(一)HTTP 服务创建

以下是使用 Java 原生类实现 HTTP 服务的代码:

java">import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;// 处理 HTTP 请求的处理器
class UserHttpHandler implements HttpHandler {private Map<String, String> users = new HashMap<>();@Overridepublic void handle(HttpExchange exchange) throws IOException {String response = "";int statusCode = 200;String method = exchange.getRequestMethod();String path = exchange.getRequestURI().getPath();if (method.equalsIgnoreCase("GET")) {if (path.equals("/users")) {// 获取所有用户信息StringBuilder userInfo = new StringBuilder();for (Map.Entry<String, String> entry : users.entrySet()) {userInfo.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n");}response = userInfo.toString();} else if (path.startsWith("/users/")) {// 获取特定用户信息String userId = path.substring("/users/".length());String user = users.get(userId);if (user == null) {statusCode = 404;response = "User not found";} else {response = user;}}} else if (method.equalsIgnoreCase("POST")) {if (path.equals("/users")) {// 创建新用户StringBuilder requestBody = new StringBuilder();byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = exchange.getRequestBody().read(buffer))!= -1) {requestBody.append(new String(buffer, 0, bytesRead));}String[] parts = requestBody.toString().split("&");Map<String, String> userData = new HashMap<>();for (String part : parts) {String[] keyValue = part.split("=");if (keyValue.length == 2) {userData.put(keyValue[0], keyValue[1]);}}String userId = userData.get("userId");String userName = userData.get("userName");if (userId!= null && userName!= null) {users.put(userId, userName);statusCode = 201;response = "User created successfully";} else {statusCode = 400;response = "Invalid user data";}}} else if (method.equalsIgnoreCase("PUT")) {if (path.startsWith("/users/")) {// 更新用户信息String userId = path.substring("/users/").length();StringBuilder requestBody = new StringBuilder();byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = exchange.getRequestBody().read(buffer))!= -1) {requestBody.append(new String(buffer, 0, bytesRead));}String newInfo = requestBody.toString();if (users.containsKey(userId)) {users.put(userId, newInfo);response = "User updated successfully";} else {statusCode = 404;response = "User not found";}}} else if (method.equalsIgnoreCase("DELETE")) {if (path.startsWith("/users/")) {// 删除用户String userId = path.substring("/users/").length();if (users.remove(userId)!= null) {response = "User deleted successfully";} else {statusCode = 404;response = "User not found";}}} else {statusCode = 405;response = "Method not allowed";}exchange.sendResponseHeaders(statusCode, response.length());try (OutputStream os = exchange.getResponseBody()) {os.write(response.getBytes(StandardCharsets.UTF_8));}}
}public class SimpleHttpServer {public static void main(String[] args) throws IOException {// 创建 HTTP 服务器,监听 8080 端口HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);// 为 /users 路径添加处理器server.createContext("/users", new UserHttpHandler());// 为根路径添加处理器,可用于测试或其他功能server.createContext("/", new HttpHandler() {@Overridepublic void handle(HttpExchange exchange) throws IOException {String response = "Welcome to the HTTP Server!";exchange.sendResponseHeaders(200, response.length());try (OutputStream os = exchange.getResponseBody()) {os.write(response.getBytes(StandardCharsets.UTF_8));}}});// 设置服务器的执行器为 null,使用默认的执行器server.setExecutor(null);// 启动服务器server.start();System.out.println("Server is listening on port 8080");}
}

代码逻辑

  • UserHttpHandler

    • 实现了 HttpHandler 接口,用于处理各种 HTTP 请求。
    • 存储用户信息使用 Map<String, String> 作为存储,模拟数据库。
    • handle 方法根据不同的请求方法(GET、POST、PUT、DELETE)和请求路径(/users/users/{userId})进行不同的处理:
      • GET 请求
        • /users:将存储的所有用户信息拼接成字符串返回。
        • /users/{userId}:根据用户 ID 获取用户信息,若用户不存在,设置状态码为 404。
      • POST 请求
        • /users:从请求体中解析 userIduserName 并添加新用户,若数据不完整设置状态码为 400。
      • PUT 请求
        • /users/{userId}:更新用户信息,若用户不存在,设置状态码为 404。
      • DELETE 请求
        • /users/{userId}:删除用户,若用户不存在,设置状态码为 404。
      • 其他情况:设置状态码为 405,表示方法不允许。
  • SimpleHttpServer

    • 创建一个 HttpServer 实例,监听 8080 端口。
    • 使用 server.createContext/users 路径添加 UserHttpHandler 处理器,为 / 路径添加一个简单的欢迎信息处理器。
    • server.setExecutor(null) 使用默认的执行器。
    • server.start() 启动服务器。

HTTP__172">(二)HTTP 服务调用与测试

以下是使用 Java 进行 HTTP 服务调用的测试代码:

java">import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Random;public class HttpInterfaceTester {private static final String BASE_URL = "http://localhost:8080/users";private static final Random RANDOM = new Random();public static void main(String[] args) {try {// 测试 GET 请求获取用户列表testGetUsers();// 测试 POST 请求创建用户String userId = String.valueOf(RANDOM.nextInt(1000));String userName = "TestUser" + userId;testCreateUser(userId, userName);// 测试 GET 请求获取特定用户testGetUser(userId);// 测试 PUT 请求更新用户信息String updatedInfo = "UpdatedTestUser" + userId;testUpdateUser(userId, updatedInfo);// 测试 DELETE 请求删除用户testDeleteUser(userId);} catch (Exception e) {e.printStackTrace();}}private static void testGetUsers() throws Exception {URL url = new URL(BASE_URL);HttpURLConnection connection = (HttpURLConnection) url.openConnection();connection.setRequestMethod("GET");int responseCode = connection.getResponseCode();if (responseCode == HttpURLConnection.HTTP_OK) {BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));String inputLine;StringBuilder response = new StringBuilder();while ((inputLine = in.readLine())!= null) {response.append(inputLine);}in.close();System.out.println("GET /users 响应: " + response.toString());} else {System.out.println("GET /users 失败,状态码: " + responseCode);}}private static void testCreateUser(String userId, String userName) throws Exception {URL url = new URL(BASE_URL);HttpURLConnection connection = (HttpURLConnection) url.openConnection();connection.setRequestMethod("POST");connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");connection.setDoOutput(true);String postData = "userId=" + userId + "&userName=" + userName;try (OutputStream os = connection.getOutputStream()) {byte[] input = postData.getBytes(StandardCharsets.UTF_8);os.write(input, 0, input.length);}int responseCode = connection.getResponseCode();if (responseCode == HttpURLConnection.HTTP_CREATED) {System.out.println("POST /users 成功创建用户: " + userId);} else {System.out.println("POST /users 失败,状态码: " + responseCode);}}private static void testGetUser(String userId) throws Exception {URL url = new URL(BASE_URL + "/" + userId);HttpURLConnection connection = (HttpURLConnection) url.openConnection();connection.setRequestMethod("GET");int responseCode = connection.getResponseCode();if (responseCode == HttpURLConnection.HTTP_OK) {BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));String inputLine;StringBuilder response = new StringBuilder();while ((inputLine = in.readLine())!= null) {response.append(inputLine);}in.close();System.out.println("GET /users/" + userId + " 响应: " + response.toString());} else {System.out.println("GET /users/" + userId + " 失败,状态码: " + responseCode);}}private static void testUpdateUser(String userId, String newInfo) throws Exception {URL url = new URL(BASE_URL + "/" + userId);HttpURLConnection connection = (HttpURLConnection) url.openConnection();connection.setRequestMethod("PUT");connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");connection.setDoOutput(true);String postData = newInfo;try (OutputStream os = connection.getOutputStream()) {byte[] input = postData.getBytes(StandardCharsets.UTF_8);os.write(input, 0, input.length);}int responseCode = connection.getResponseCode();if (responseCode == HttpURLConnection.HTTP_OK) {System.out.println("PUT /users/" + userId + " 成功更新用户信息");} else {System.out.println("PUT /users/" + userId + " 失败,状态码: " + responseCode);}}private static void testDeleteUser(String userId) throws Exception {URL url = new URL(BASE_URL + "/" + userId);HttpURLConnection connection = (HttpURLConnection) url.openConnection();connection.setRequestMethod("DELETE");int responseCode = connection.getResponseCode();if (responseCode == HttpURLConnection.HTTP_OK) {System.out.println("DELETE /users/" + userId + " 成功删除用户");} else {System.out.println("DELETE /users/" + userId + " 失败,状态码: " + responseCode);}}
}

代码逻辑

  • 测试代码使用 HttpURLConnection 进行 HTTP 请求:
    • testGetUsers():发送 GET 请求到 /users 获取用户列表,根据状态码判断请求是否成功并输出响应内容或错误信息。
    • testCreateUser(userId, userName):发送 POST 请求到 /users 创建新用户,将用户信息以 application/x-www-form-urlencoded 格式发送。
    • testGetUser(userId):发送 GET 请求到 /users/{userId} 获取用户信息。
    • testUpdateUser(userId, newInfo):发送 PUT 请求到 /users/{userId} 更新用户信息。
    • testDeleteUser(userId):发送 DELETE 请求到 /users/{userId} 删除用户。

二、Python 实现

HTTP__320">(一)HTTP 服务创建

以下是使用 Python 的内置模块实现 HTTP 服务的代码:

python">import http.server
import socketserver
import urllib.parse
import jsonclass UserHandler(http.server.SimpleHTTPRequestHandler):users = {}def do_GET(self):if self.path == '/users':# 获取所有用户信息response = json.dumps(self.users)self.send_response(200)self.send_header('Content-Type', 'application/json')self.end_headers()self.wfile.write(response.encode('utf-8'))elif self.path.startswith('/users/'):# 获取特定用户信息parts = self.path.split('/')if len(parts) == 3:user_id = parts[2]user = self.users.get(user_id)if user:self.send_response(200)self.send_header('Content-Type', 'application/json')self.end_headers()self.wfile.write(json.dumps(user).encode('utf-8'))else:self.send_error(404, 'User not found')else:self.send_error(400, 'Invalid user ID')else:self.send_error(404, 'Not Found')def do_POST(self):if self.path == '/users':content_length = int(self.headers['Content-Length'])post_data = self.rfile.read(content_length)user_data = json.loads(post_data.decode('utf-8'))user_id = user_data.get('id')if user_id:self.users[user_id] = user_dataself.send_response(201)self.send_header('Content-Type', 'application/json')self.end_headers()self.wfile.write(json.dumps({'message': 'User created successfully'}).encode('utf-8'))else:self.send_error(400, 'Invalid user data')else:self.send_error(404, 'Not Found')def do_PUT(self):if self.path.startswith('/users/'):parts = self.path.split('/')if len(parts) == 3:user_id = parts[2]if user_id in self.users:content_length = int(self.headers['Content-Length'])put_data = self.rfile.read(content_length)updated_user = json.loads(put_data.decode('utf-8'))self.users[user_id].update(updated_user)self.send_response(200)self.send_header('Content-Type', 'application/json')self.end_headers()self.wfile.write(json.dumps({'message': 'User updated successfully'}).encode('utf-8'))else:self.send_error(404, 'User not found')else:self.send_error(400, 'Invalid user ID')else:self.send_error(404, 'Not Found')def do_DELETE(self):if self.path.startsWith('/users/'):parts = self.path.split('/')if len(parts) == 3:user_id = parts[2]if user_id in self.users:del self.users[user_id]self.send_response(200)self.send_header('Content-Type', 'application/json')self.end_headers()self.wfile.write(json.dumps({'message': 'User deleted successfully'}).encode('utf-8'))else:self.send_error(404, 'User not found')else:self.send_error(400, 'Invalid user ID')else:self.send_error(404, 'Not Found')def run(server_class=http.server.HTTPServer, handler_class=UserHandler, port=8080):server_address = ('', port)httpd = server_class(server_address, handler_class)print(f'Starting server on port {port}...')httpd.serve_forever()

代码逻辑

  • UserHandler
    • 继承自 http.server.SimpleHTTPRequestHandler,用于处理 HTTP 请求。
    • users 是一个字典,用于存储用户信息,作为一个简单的存储机制,模拟数据库。
    • do_GET 方法:
      • 当请求路径为 /users 时,将存储在 users 字典中的所有用户信息以 JSON 格式返回,设置状态码为 200,并设置 Content-Typeapplication/json
      • 当请求路径为 /users/{user_id} 时,从路径中提取 user_id,尝试从 users 字典中获取用户信息。如果用户存在,将其以 JSON 格式返回并设置状态码为 200;如果用户不存在,返回 404 错误;如果 user_id 提取错误,返回 400 错误。
    • do_POST 方法:
      • 当请求路径为 /users 时,从请求体中读取内容并解析为 JSON 数据,尝试提取 id 作为用户 ID。如果 id 存在,将该用户数据存储到 users 字典中,并返回创建成功的消息及 201 状态码;如果 id 不存在,返回 400 错误;如果请求路径不匹配,返回 404 错误。
    • do_PUT 方法:
      • 当请求路径为 /users/{user_id} 时,从路径中提取 user_id,并检查该用户是否存在于 users 字典中。如果存在,读取请求体中的更新数据,更新该用户信息,并返回更新成功的消息及 200 状态码;如果用户不存在,返回 404 错误;如果 user_id 提取错误,返回 400 错误。
    • do_DELETE 方法:
      • 当请求路径为 /users/{user_id} 时,从路径中提取 user_id,尝试从 users 字典中删除该用户。如果删除成功,返回删除成功的消息及 200 状态码;如果用户不存在,返回 404 错误;如果 user_id 提取错误,返回 400 错误。

HTTP__437">(二)HTTP 服务调用与测试

以下是使用 Python 进行 HTTP 服务调用的测试代码,我们将使用 requests 库,在运行以下代码前,请确保已安装 requests 库:

pip install requests
python">import requestsBASE_URL = "http://localhost:8080/users"def test_get_users():response = requests.get(BASE_URL)if response.status_code == 200:print("GET /users 响应:", response.json())else:print("GET /users 失败,状态码:", response.status_code)def test_create_user():# 生成一个随机的用户 ID 和用户名user_id = str(abs(hash('user'))  # 使用哈希函数生成一个相对唯一的 IDuser_name = "TestUser" + user_iduser_data = {"id": user_id, "name": user_name}response = requests.post(BASE_URL, json=user_data)if response.status_code == 201:print("POST /users 成功创建用户:", user_id)else:print("POST /users 失败,状态码:", response.status_code)def test_get_user(user_id):url = BASE_URL + "/" + user_idresponse = requests.get(url)if response.status_code == 200:print("GET /users/{} 响应:".format(user_id), response.json())else:print("GET /users/{} 失败,状态码:".format(user_id), response.status_code)def test_update_user(user_id):url = BASE_URL + "/" + user_idupdated_info = {"name": "UpdatedTestUser" + user_id}response = requests.put(url, json=updated_info)if response.status_code == 200:print("PUT /users/{} 成功更新用户信息".format(user_id))else:print("PUT /users/{} 失败,状态码:".format(user_id), response.status_code)def test_delete_user(user_id):url = BASE_URL + "/" + user_idresponse = requests.delete(url)if response.status_code == 200:print("DELETE /users/{} 成功删除用户".format(user_id))else:print("DELETE /users/{} 失败,状态码:".format(user_id), response.status_code)if __name__ == "__main__":# 测试 GET 请求获取用户列表test_get_users()# 测试 POST 请求创建用户test_create_user()# 获取创建的用户 ID,这里假设上一步创建的用户 ID 可通过某种方式获取,这里简单生成一个新的user_id = str(abs(hash('user2'))test_create_user()# 测试 GET 请求获取特定用户test_get_user(user_id)# 测试 PUT 请求更新用户信息test_update_user(user_id)# 测试 DELETE 请求删除用户test_delete_user(user_id)

代码逻辑

  • test_get_users():使用 requests.get() 方法向 BASE_URL 发送 GET 请求,若请求成功(状态码为 200),将响应内容以 JSON 格式打印;若失败,打印相应的状态码。
  • test_create_user():使用 requests.post() 方法向 /users 发送 POST 请求,创建一个用户,用户数据以 JSON 格式发送。根据返回的状态码判断用户是否创建成功。
  • test_get_user(user_id):向 /users/{user_id} 发送 GET 请求,根据状态码判断是否成功获取用户信息。
  • test_update_user(user_id):向 /users/{user_id} 发送 PUT 请求,更新用户信息,根据状态码判断更新是否成功。
  • test_delete_user(user_id):向 /users/{user_id} 发送 DELETE 请求,根据状态码判断用户是否成功删除。

http://www.ppmy.cn/ops/151090.html

相关文章

消息队列实战指南:三大MQ 与 Kafka 适用场景全解析

前言&#xff1a;在当今数字化时代&#xff0c;分布式系统和大数据处理变得愈发普遍&#xff0c;消息队列作为其中的关键组件&#xff0c;承担着系统解耦、异步通信、流量削峰等重要职责。ActiveMQ、RabbitMQ、RocketMQ 和 Kafka 作为市场上极具代表性的消息队列产品&#xff0…

芝麻http/品易http/太阳http/极光http退市后,还有哪家好用推荐?

相信&#xff0c;已经有不少程序员朋友在讨论芝麻HTTP、品易HTTP、太阳HTTP和极光HTTP退市的消息。说实话&#xff0c;芝麻系HTTP代理服务商在代理IP圈子里可以说是有举足轻重的位置&#xff0c;曾经也是吸引了不少用户的青睐。2个月前它们的退市可以说让代理IP整个市场无论是用…

Java 高级工程师面试高频题:JVM+Redis+ 并发 + 算法 + 框架

前言 在过 2 个月即将进入 3 月了&#xff0c;然而面对今年的大环境而言&#xff0c;跳槽成功的难度比往年高了很多&#xff0c;很明显的感受就是&#xff1a;对于今年的 java 开发朋友跳槽面试&#xff0c;无论一面还是二面&#xff0c;都开始考验一个 Java 程序员的技术功底…

BGP联盟

一、BGP联盟简介 1、什么是BGP联盟 BGP联盟&#xff08;Confederation&#xff09;是处理AS内部的IBGP网络连接激增的另一种方法&#xff0c;它将一个AS划分为若干个子自治系统&#xff08;Sub AS&#xff09;&#xff0c;每个子AS内部建立IBGP全连接关系或者配置反射器&#…

AI编程工具使用技巧——通义灵码

活动介绍通义灵码1. 理解通义灵码的基本概念示例代码生成 2. 使用明确的描述示例代码生成 3. 巧妙使用注释示例代码生成 4. 注意迭代与反馈原始代码反馈后生成优化代码 5. 结合生成的代码进行调试示例测试代码 其他功能定期优化生成的代码合作与分享结合其他工具 总结 活动介绍…

k8s pod 中通过service account 访问API Server

创建Role,Rolebinding, Service account 和Pod 创建Role apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: myns name: myrole rules: - apiGroups: ["apps"] resources: ["deployments"] verbs: ["get", …

【2024年华为OD机试】(A卷,100分)- 完美走位 (Java JS PythonC/C++)

一、问题描述 题目解析 题目描述 在第一人称射击游戏中&#xff0c;玩家通过键盘的 A、S、D、W 四个按键控制游戏人物分别向左、向后、向右、向前进行移动。假设玩家每按动一次键盘&#xff0c;游戏人物会向某个方向移动一步。如果玩家在操作一定次数的键盘并且各个方向的步…

币安面经(2)

自我介绍 项目介绍 qps 数据量 缓存一致性&#xff1f; qps 使用缓存&#xff1a; 将热点数据缓存在内存中&#xff0c;提高读取效率。 负载均衡&#xff1a; 使用负载均衡器&#xff08;如 Nginx&#xff09;分配请求&#xff0c;避免某一节点过载。 异步处理&#xff1a; 对…