Java Python:从简单案例理解 HTTP 服务开发与调用!
使用 Java 和 Python 实现 HTTP 服务创建和调用
在现代网络应用开发中,创建和调用 HTTP 服务是一项基本技能。本文将详细介绍如何使用 Java 和 Python 语言实现一个简单的 HTTP 服务,并展示如何使用相应语言的客户端代码对其进行调用和测试。我们将实现一个用户管理服务,包括用户的创建、读取、更新和删除操作。
一、Java 实现
(一)HTTP 服务创建
以下是使用 Java 原生类实现 HTTP 服务的代码:
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<>();
@Override
public 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() {
@Override
public 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 服务调用与测试
以下是使用 Java 进行 HTTP 服务调用的测试代码:
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 服务创建
以下是使用 Python 的内置模块实现 HTTP 服务的代码:
import http.server
import socketserver
import urllib.parse
import json
class 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_data
self.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 服务调用与测试
以下是使用 Python 进行 HTTP 服务调用的测试代码,我们将使用 requests
库,在运行以下代码前,请确保已安装 requests
库:
pip install requests
import requests
BASE_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')) # 使用哈希函数生成一个相对唯一的 ID
user_name = "TestUser" + user_id
user_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_id
response = 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_id
updated_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_id
response = 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 请求,根据状态码判断用户是否成功删除。