当前位置: 首页 > article >正文

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:从请求体中解析 userIduserName 并添加新用户,若数据不完整设置状态码为 400。
      • PUT 请求
        • /users/{userId}:更新用户信息,若用户不存在,设置状态码为 404。
      • DELETE 请求
        • /users/{userId}:删除用户,若用户不存在,设置状态码为 404。
      • 其他情况:设置状态码为 405,表示方法不允许。
  • 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-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 服务调用与测试

以下是使用 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 请求,根据状态码判断用户是否成功删除。

http://www.kler.cn/a/505807.html

相关文章:

  • citrix netscaler13.1 重写负载均衡响应头(基础版)
  • Redis哨兵(Sentinel)
  • C++|CRC校验总结
  • 用Guiguider生成的字体代替LVGL默认字体
  • uni-app的学习
  • 【力扣Hot100】滑动窗口
  • 算法15、双指针(归并排序两种做法)
  • 视频本地化的特点
  • 本地视频进度加入笔记+根据进度快速锁定视频位置
  • LeetCode 每日一题 2025/1/6-2025/1/12
  • [Qt] 窗口 | QDialog | 常用内置对话框
  • 数据仓库的复用性:设计和构建一个高复用性的数仓
  • 软考信安20~数据库系统安全
  • 数据通过canal 同步es,存在延迟问题,解决方案
  • Web前端------HTML多媒体标签之音频和视频标签
  • 【MATLAB】subplot如何增加title
  • 如何开发一个分布式日志系统
  • 线上nginx编译参数
  • 回归预测 | MATLAB实SVM支持向量机多输入单输出回归预测
  • 设计模式02:结构型设计模式之适配器模式使用情景及其基础Demo
  • 反转字符串力扣--344
  • Abp vnext + OpenIddict的授权械与适应场景
  • Apache MINA 使用简单Demo案例
  • js使用qrcode与canvas生成带logo的二维码
  • lua下标是可以从0开始
  • Oracle+11g+笔记(9)-控制文件及日志文件的管理