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
:从请求体中解析userId
和userName
并添加新用户,若数据不完整设置状态码为 400。
- PUT 请求:
/users/{userId}
:更新用户信息,若用户不存在,设置状态码为 404。
- DELETE 请求:
/users/{userId}
:删除用户,若用户不存在,设置状态码为 404。
- 其他情况:设置状态码为 405,表示方法不允许。
- GET 请求:
- 实现了
-
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-Type
为application/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 请求,根据状态码判断用户是否成功删除。