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

分布微服务电商订单系统Rust编码开发[下]

5 网关与页面服务设计

5.1 功能设计

A. 网关功能:

统一API入口,转发请求到对应的微服务;

提供静态文件服务,包括HTML/CSS/JS;

统一错误处理和日志记录。

B. 路由设计:

/api/orders - 订单服务相关路由;

/api/payment - 支付服务相关路由;

/api/inventory - 库存服务相关路由。

/ordersHtml - 订单管理页面;

/paymentHtml - 支付管理页面;

/inventoryHtml - 库存管理页面。

C. 前端交互:

使用纯HTML/CSS/JS实现简单界面;

通过fetch API与后端交互;

表单提交处理各种业务操作。

D. 微服务集成:

使用reqwest库作为HTTP客户端;

支持配置不同的微服务地址;

转发请求并返回响应。

E. 错误处理:

自定义GatewayError类型;

统一处理各种错误情况;

返回适当的HTTP状态码。

5.2 主程序设计--main.rs

网关路由和Nacos注册。

use actix_web::{web, App, HttpServer, middleware::Logger};

use std::collections::HashMap; use log::info; use tera::Tera;

use nacos_sdk::api::naming::{NamingService, NamingServiceBuilder, ServiceInstance};

use nacos_sdk::api::props::ClientProps; mod routes;

#[actix_web::main]

async fn main() -> std::io::Result<()> {

    env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));

    info!("Starting gateway service");

    // 服务配置

    let service_name = "gateway".to_string();

    let group = "ecommerce".to_string(); let ip = "127.0.0.1"; let port = 9000;

    // 创建Nacos客户端

    let client = NamingServiceBuilder::new(

        ClientProps::new().server_addr("127.0.0.1:8848").namespace("public"),)

        .build().map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;

    // 构建服务实例

    let instance = ServiceInstance { service_name: Some(service_name.clone()),

        ip: ip.to_string(), port, weight: 1.0, healthy: true, enabled: true,

        ephemeral: true, instance_id: None, cluster_name: Some("DEFAULT".to_string()),

        metadata: HashMap::from([ ("version".into(), "1.0".into()),

            ("service".into(), "gateway".into()) ])

    };

    // 注册服务

    client.register_instance(service_name.clone(),Some(group.clone()),instance.clone())

        .await.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;

    println!(" 订单服务注册成功");

    // 微服务地址配置

    let services = web::Data::new(HashMap::from([

        ("order".to_string(), "http://localhost:9001".to_string()),

        ("payment".to_string(), "http://localhost:9002".to_string()),

        ("inventory".to_string(), "http://localhost:9003".to_string()) ]));

    // 模板引擎初始化

    let tera = Tera::new("templates/**/*.html").expect("Failed to initialize Tera");

    // HTTP客户端

    let client = web::Data::new(reqwest::Client::new());

    HttpServer::new(move || {

        App::new().app_data(web::Data::new(tera.clone()))

            .app_data(services.clone()).app_data(client.clone())

            .service(actix_files::Files::new("/static", "static"))

            .wrap(Logger::default()).configure(routes::config)

    }).bind("127.0.0.1:9000")?

      .run().await

}

5.3 路由程序设计--routes.rs

各个微服务的动态路由和网页的Web服务器实现。

use actix_web::{web, HttpResponse, Responder, HttpRequest};

use reqwest::Client; use std::collections::HashMap; use tera::Tera;

// 修改后的代理函数 - 支持完整路径和查询参数

pub async fn proxy(client: web::Data<Client>,services: web::Data<HashMap<String, String>>,

    service_name: String,req: HttpRequest, body: web::Bytes,) -> impl Responder {

    // 获取完整路径(含查询参数)

    let full_path = req.uri().path_and_query()

        .map(|pq| pq.as_str()).unwrap_or(req.uri().path());

    let target_url = match services.get(&service_name) {

        Some(base_url) => format!("{}{}", base_url, full_path),

        None => return HttpResponse::BadRequest().body("Invalid service name"),

    };

    // 构建转发请求

    let mut request_builder = client.request(req.method().clone(), &target_url);

    // 复制原始请求头

    for (key, value) in req.headers().iter() {

        request_builder = request_builder.header(key, value);

    }

    match request_builder.body(body).send().await {

        Ok(res) => HttpResponse::build(res.status())

            .insert_header(("X-Proxy-Source", "gateway"))

            .streaming(res.bytes_stream()),

        Err(e) => { log::error!("Proxy error to {}: {}", target_url, e);

            HttpResponse::BadGateway().body(format!("Service unavailable: {}", e))

        }

    }

}

// 渲染HTML页面

pub async fn render_template(tmpl: web::Data<Tera>,

    template_name: &str, ) -> impl Responder {

    let ctx = tera::Context::new();

    match tmpl.render(template_name, &ctx) {

        Ok(html) => HttpResponse::Ok().content_type("text/html").body(html),

        Err(e) => HttpResponse::InternalServerError().body(e.to_string()),

    }

}

pub fn config(cfg: &mut web::ServiceConfig) {

    // 页面路由

    cfg.service(web::resource("/").to(|tmpl: web::Data<Tera>| async move {

        render_template(tmpl, "index.html").await

    }));

    cfg.service(web::resource("/ordersHtml").to(|tmpl: web::Data<Tera>| async move {

        render_template(tmpl, "orders.html").await

    }));

    cfg.service(web::resource("/paymentHtml").to(|tmpl: web::Data<Tera>| async move {

        render_template(tmpl, "payment.html").await

    }));

    cfg.service(web::resource("/inventoryHtml").to(|tmpl: web::Data<Tera>| async move {

        render_template(tmpl, "inventory.html").await

    }));

    // 订单服务路由: 创建订单 (POST /orders)

    cfg.service( web::resource("/orders").route(web::post().to(|client: web::Data<Client>,

        services: web::Data<HashMap<String, String>>, req: HttpRequest,

        body: web::Bytes| async move {

            proxy(client, services, "order".to_string(), req, body).await}, )) );

    // 订单服务路由: 获取订单详情 (GET /orders/{order_id})

    cfg.service( web::resource("/orders/{order_id}").route(web::get().to(|client: web::Data<Client>,

        services: web::Data<HashMap<String, String>>, req: HttpRequest,

        body: web::Bytes| async move {

            proxy(client, services, "order".to_string(), req, body).await}, )) );

    // 订单服务路由: 确认订单 (PUT /orders/{order_id}/confirm)

    cfg.service( web::resource("/orders/{order_id}/confirm")

        .route(web::put().to(|client: web::Data<Client>,

        services: web::Data<HashMap<String, String>>, req: HttpRequest,

        body: web::Bytes| async move {

            proxy(client, services, "order".to_string(), req, body).await}, )) );

    // 订单服务路由: 刷新订单 (PUT /orders/{order_id}/refresh)

    cfg.service( web::resource("/orders/{order_id}/refresh")

        .route(web::put().to(|client: web::Data<Client>,

        services: web::Data<HashMap<String, String>>, req: HttpRequest,

        body: web::Bytes| async move {

            proxy(client, services, "order".to_string(), req, body).await}, )) );

    // 支付服务路由: 支付订单 (POST /orders/{order_id}/pay)

    cfg.service( web::resource("/payment/{order_id}/pay")

        .route(web::post().to(|client: web::Data<Client>,

        services: web::Data<HashMap<String, String>>, req: HttpRequest,

        body: web::Bytes| async move {

            proxy(client, services, "payment".to_string(), req, body).await },)) );

    // 支付服务路由: 获取支付订单详情 (GET /orders/{order_id})

    cfg.service( web::resource("/payment/{order_id}")

        .route(web::get().to(|client: web::Data<Client>,

        services: web::Data<HashMap<String, String>>, req: HttpRequest,

        body: web::Bytes| async move {

            proxy(client, services, "payment".to_string(), req, body).await }, )) );

    // 支付服务路由: 查询用户己支付订单 (GET /orders?user_id=...&pay_status=...)

    cfg.service( web::resource("/payment").route(web::get().to(|client: web::Data<Client>,

        services: web::Data<HashMap<String, String>>, req: HttpRequest,

        body: web::Bytes| async move {

            proxy(client, services, "payment".to_string(), req, body).await }, )) );

    // 库服务路由: 库存生成与查询

    cfg.service(

        web::resource("/api/inventory")

            .route(web::post().to( |client: web::Data<Client>,

                 services: web::Data<HashMap<String, String>>, req: HttpRequest,

                 body: web::Bytes| async move {

                    proxy(client, services, "inventory".to_string(), req, body).await }, ))

            .route(web::get().to(

                |client: web::Data<Client>,

                 services: web::Data<HashMap<String, String>>,

                 req: HttpRequest,

                 body: web::Bytes| async move {

                    proxy(client, services, "inventory".to_string(), req, body).await }, )) );

    // 库服务路由: 库存更新

    cfg.service( web::resource("/api/inventory/update")

        .route(web::post().to(|client: web::Data<Client>,

        services: web::Data<HashMap<String, String>>, req: HttpRequest,

        body: web::Bytes| async move {

            proxy(client, services, "inventory".to_string(), req, body).await }, )) );

    // 库服务路由: 库存预占

    cfg.service( web::resource("/api/inventory/reserve")

        .route(web::post().to( |client: web::Data<Client>,

        services: web::Data<HashMap<String, String>>, req: HttpRequest,

        body: web::Bytes| async move {

            proxy(client, services, "inventory".to_string(), req, body).await }, )) );

    // 库服务路由: 库存释放

    cfg.service( web::resource("/api/inventory/release")

        .route(web::post().to( |client: web::Data<Client>,

        services: web::Data<HashMap<String, String>>, req: HttpRequest,

        body: web::Bytes| async move {

            proxy(client, services, "inventory".to_string(), req, body).await }, )) );

}

5.4 子项目及其依赖配置--Cargo.toml

[package]
name = "gateway"
version = "0.1.0"
edition = "2024"
[dependencies]
actix-web = "4.0"                                    # Web框架
reqwest = { version = "0.11", features = ["json", "stream"] }  # HTTP客户端
tera = "1.0"                                         # 模板引擎
log = "0.4"                                         # 日志
env_logger = "0.9"
actix-files = "0.6"                                    # 静态文件服务专用库[1](@ref)[7](@ref)
nacos-sdk = { version = "0.4", features = ["naming"] }

6 Web交互展现页面设计

6.1 主页--indexHtml.html

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>电商微服务网关</title>

    <link rel="stylesheet" href="/static/style.css">

</head>

<body>

  <header><h1>电商微服务网关</h1></header>

  <nav>

    <ul>

        <li><a href="/">首页</a></li>

        <li><a href="/ordersHtml">订单管理</a></li>

        <li><a href="/paymentHtml">支付管理</a></li>

        <li><a href="/inventoryHtml">库存管理</a></li>

    </ul>

  </nav>

  <main>

    <section class="intro">

        <h2>欢迎使用电商微服务网关</h2>

        <p>本系统提供订单、支付和库存微服务的统一管理界面。</p>

    </section>

  </main>

  <footer><p>&copy; 2025 电商微服务系统</p></footer>

</body>

<script src="/static/script.js"></script>

</html>

6.2 订单页面--ordersHtml.httml

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>订单管理</title>

    <link rel="stylesheet" href="/static/style.css">

</head>

<body>

  <header><h1>订单管理</h1></header>

  <nav>

    <ul>

        <li><a href="/">首页</a></li>

        <li><a href="/ordersHtml">订单管理</a></li>

        <li><a href="/paymentHtml">支付管理</a></li>

        <li><a href="/inventoryHtml">库存管理</a></li>

    </ul>

  </nav>

  <main>

    <section class="order-form">

        <h2>创建新订单</h2>

        <form id="createOrderForm">

            <div class="form-group">

                <label for="userId">用户ID:</label>

                <input type="text" id="userId" name="user_id" required>

            </div>

            <div class="form-group">

                <label for="productId">商品ID:</label>

                <input type="text" id="productId" name="product_id" required>

            </div>

            <div class="form-group">

                <label for="quantity">数量:</label>

                <input type="number" id="quantity" name="quantity" required>

            </div>

            <div class="form-group">

                <label for="totalPrice">总价:</label>

                <input type="number" step="0.01" id="totalPrice" name="total_price" required>

            </div>

            <button type="submit">创建订单</button>

        </form>

    </section>

    <section class="order-actions">

        <h2>订单操作</h2>

        <div class="form-group">

            <label for="orderId">订单ID:</label>

            <input type="text" id="orderId" name="order_id" required>

        </div>

        <button id="getOrderBtn">查询订单</button>

        <button id="confirmOrderBtn">确认订单</button>

        <button id="refreshOrderBtn">刷新订单</button>

    </section>

    <section class="order-list">

        <h2>订单列表</h2>

        <div id="orderList"></div>

    </section>

  </main>

  <footer><p>&copy; 2025 电商微服务系统</p></footer>

</body>

<script src="/static/script.js"></script>

</html>

6.3 支付页面--paymentHtml.httml

<!DOCTYPE html>

<html lang="en">

<head>

  <meta charset="UTF-8">

  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <title>支付管理</title>

  <link rel="stylesheet" href="/static/style.css">

</head>

<body>

  <header><h1>支付管理</h1></header>

  <nav>

   <ul>

    <li><a href="/">首页</a></li>

    <li><a href="/ordersHtml">订单管理</a></li>

    <li><a href="/paymentHtml">支付管理</a></li>

    <li><a href="/inventoryHtml">库存管理</a></li>

   </ul>

  </nav>

  <main>

   <section class="payment-form">

    <h2>支付订单</h2>

    <form id="payOrderForm">

      <div class="form-group">

        <label for="payOrderId">订单ID:</label>

        <input type="text" id="payOrderId" name="order_id" required>

      </div>

      <div class="form-group">

        <label for="currency">货币:</label>

        <select id="currency" name="currency" required>

          <option value="CNY">人民币 (CNY)</option>

          <option value="USD">美元 (USD)</option>

          <option value="EUR">欧元 (EUR)</option>

        </select>

      </div>

      <div class="form-group">

        <label for="paymentMethod">支付方式:</label>

        <select id="paymentMethod" name="payment_method" required>

          <option value="WeChatPay">微信支付</option>

          <option value="Alipay">支付宝</option>

          <option value="CreditCard">信用卡</option>

        </select>

      </div>

      <button type="submit">支付</button>

    </form>

   </section>

   <section class="payment-status">

    <h2>支付状态查询</h2>

    <div class="form-group">

      <label for="queryUserId">用户ID:</label>

      <input type="text" id="queryUserId" name="user_id">

    </div>

    <div class="form-group">

      <label for="queryPayStatus">支付状态:</label>

      <select id="queryPayStatus" name="pay_status">

        <option value="">全部</option>

        <option value="Paid">已支付</option>

        <option value="Unpaid">未支付</option>

        <option value="Failed">支付失败</option>

      </select>

    </div>

    <button id="queryPaymentBtn">查询</button>

    <div id="paymentList"></div>

   </section>

  </main>

  <footer><p>&copy; 2025 电商微服务系统</p></footer>

</body>

<script src="/static/script.js"></script>

</html>

6.4 库存页面--inventoryHtml.httml

<!DOCTYPE html>

<html lang="en">

<head>

  <meta charset="UTF-8">

  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <title>库存管理</title>

  <link rel="stylesheet" href="/static/style.css">

</head>

<body>

  <header><h1>库存管理</h1></header>

  <nav>

   <ul>

    <li><a href="/">首页</a></li>

    <li><a href="/ordersHtml">订单管理</a></li>

    <li><a href="/paymentHtml">支付管理</a></li>

    <li><a href="/inventoryHtml">库存管理</a></li>

   </ul>

  </nav>

  <main>

   <section class="inventory-form">

    <h2>库存操作</h2>

    <div class="form-group">

      <label for="productId">商品ID:</label>

      <input type="text" id="productId" name="product_id" required>

    </div>

    <button id="genInventoryBtn">创建库存</button>

    <button id="getInventoryBtn">查询库存</button>

   </section>

   <section class="inventory-actions">

    <h2>库存变更</h2>

    <form id="updateInventoryForm">

      <div class="form-group">

        <label for="delta">变更数量 (正数增加,负数减少):</label>

        <input type="number" id="delta" name="delta" required>

      </div>

      <button type="submit">更新库存</button>

    </form>

    <form id="reserveInventoryForm">

      <div class="form-group">

        <label for="reserveQuantity">预留数量:</label>

        <input type="number" id="reserveQuantity" name="quantity" required>

      </div>

      <div class="form-group">

        <label for="reserveOrderId">订单ID:</label>

        <input type="text" id="reserveOrderId" name="order_id" required>

      </div>

      <button type="submit" onclick="fechtData(false);">预留库存</button>

      <button type="submit" onclick="fechtData(true);" >释放库存</button>

    </form>

   </section>

   <section class="inventory-list">

    <h2>库存信息</h2>

    <div id="inventoryInfo"></div>

   </section>

  </main>

  <footer><p>&copy; 2025 电商微服务系统</p></footer>

</body>

<script src="/static/script.js"></script>

</html>

6.5 页面样式--style.css

/* 全局样式 */

body { font-family: Arial, sans-serif; line-height: 1.6; margin: 0;

    padding: 0; color: #333; background-color: #f5f5f5; }

h1, h2, p, div { margin-top: 0.1rem; margin-bottom: 0.1rem }

header { background-color: #4CAF50; color: white; padding: 0.5rem; text-align: center; }

nav { background-color: #333; color: white; padding: 0.5rem; }

nav ul { list-style-type: none; margin: 0; padding: 0;

    display: flex; justify-content: space-around; }

nav a { color: white; text-decoration: none; }

nav a:hover { text-decoration: underline; }

main { padding: 1rem; max-width: 1200px; margin: 0 auto; }

footer { background-color: #333; color: white; text-align: center;

    padding: 0.5rem; position: fixed; bottom: 0; width: 100%; }

/* 表单样式 */

.form-group { margin-bottom: 0.1rem; }

label { display: block; margin-bottom: 0.1rem; }

input, select { width: 95%; padding: 0.5rem; border: 1px solid #ddd; border-radius: 4px; }

button { background-color: #4CAF50; color: white; border: none; padding: 0.5rem 1rem;

    border-radius: 4px; cursor: pointer; margin-top: 0.2rem; }

button:hover { background-color: #45a049; }

/* 分区样式 */

section { background-color: white; padding: 0.5rem; margin-bottom: 0.1rem;

    border-radius: 4px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }

.intro { text-align: center; padding: 2rem; }

6.6 页面行为控制--script.js

document.addEventListener('DOMContentLoaded', function() {

    // 创建订单

    if (document.getElementById('createOrderForm')) {

        document.getElementById('createOrderForm').addEventListener('submit', function(e) {

            e.preventDefault();

            const formData = { user_id: document.getElementById('userId').value,

                product_id: document.getElementById('productId').value,

                quantity: parseInt(document.getElementById('quantity').value),

                total_price: parseFloat(document.getElementById('totalPrice').value)

            };

            fetch('/orders', { method:'POST', headers:{'Content-Type':'application/json'},

                body: JSON.stringify(formData) }).then(response => response.json())

                .then(data => { alert(`订单创建成功! 订单ID: ${data.id}`); })

                .catch(error => { console.error('Error:', error);

                    alert('创建订单失败'); });

        });

    }

    // 查询订单

    if (document.getElementById('getOrderBtn')) {

        document.getElementById('getOrderBtn').addEventListener('click', function() {

            const orderId = document.getElementById('orderId').value;

            fetch(`/orders/${orderId}`).then(response => response.json())

                .then(data => {

                    document.getElementById('orderList').innerHTML =

                        `<pre>${JSON.stringify(data, null, 2)}</pre>`;

                })

                .catch(error => { console.error('Error:', error);

                    alert('查询订单失败'); });

        });

    }

    // 确认订单

    if (document.getElementById('confirmOrderBtn')) {

        document.getElementById('confirmOrderBtn').addEventListener('click', function() {

            const orderId = document.getElementById('orderId').value;

            fetch(`/orders/${orderId}/confirm`, { method: 'PUT',

                headers: {'Content-Type': 'application/json'},

                body: JSON.stringify({ status: 'confirmed' }) })

                .then(response => response.json())

                .then(data => { alert('订单确认成功'); })

                .catch(error => { console.error('Error:', error);

                    alert('确认订单失败'); });

        });

    }

    // 刷新订单

    if (document.getElementById('refreshOrderBtn')) {

        document.getElementById('refreshOrderBtn').addEventListener('click', function() {

            const orderId = document.getElementById('orderId').value;

            fetch(`/api/orders/${orderId}/refresh`, { method: 'PUT' })

                .then(response => response.json())

                .then(data => { alert('订单刷新成功'); })

                .catch(error => { console.error('Error:', error);

                    alert('刷新订单失败'); });

        });

    }

    // 支付订单

    if (document.getElementById('payOrderForm')) {

        document.getElementById('payOrderForm').addEventListener('submit', function(e) {

            e.preventDefault();

            const formData = { order_id: document.getElementById('payOrderId').value,

                currency: document.getElementById('currency').value,

                payment_method: document.getElementById('paymentMethod').value

            };

            fetch('/payment/'+formData.order_id+'/pay',  { method: 'POST',

                headers: { 'Content-Type': 'application/json' },

                body: JSON.stringify(formData) }).then(response => response.json())

                .then(data => { alert('支付请求已提交'); })

                .catch(error => { console.error('Error:', error);

                    alert('支付失败'); });

        });

    }

    // 查询支付状态

    if (document.getElementById('queryPaymentBtn')) {

        document.getElementById('queryPaymentBtn').addEventListener('click', function() {

            const userId = document.getElementById('queryUserId').value;

            const payStatus = document.getElementById('queryPayStatus').value;

            let queryParams = {}; if (userId) queryParams.user_id = userId;

            if (payStatus) queryParams.pay_status = payStatus;

            const queryString = new URLSearchParams(queryParams).toString();

            fetch(`/payment?${queryString}`)

                .then(response => response.json())

                .then(data => {

                    document.getElementById('paymentList').innerHTML =

                        `<pre>${JSON.stringify(data, null, 2)}</pre>`;

                })

                .catch(error => { console.error('Error:', error);

                    alert('查询支付状态失败'); });

        });

    }

    // 创建库存

    if (document.getElementById('genInventoryBtn')) {

        document.getElementById('genInventoryBtn').addEventListener('click', function() {

            const formData = { product_id: document.getElementById('productId').value, };

            fetch('/api/inventory', { method: 'POST',

                headers: { 'Content-Type': 'application/json' },

                body: JSON.stringify(formData)

            }).then(response => response.json())

                .then(data => { alert('库存创建成功'); })

                .catch(error => { console.error('Error:', error);

                    alert('创建库存失败'); });

        });

    }

    // 查询库存

    if (document.getElementById('getInventoryBtn')) {

        document.getElementById('getInventoryBtn').addEventListener('click', function() {

            const productId = document.getElementById('productId').value;

            fetch(`/api/inventory?product_id=${productId}`)

                .then(response => response.json())

                .then(data => {

                    document.getElementById('inventoryInfo').innerHTML =

                        `<pre>${JSON.stringify(data, null, 2)}</pre>`;

                })

                .catch(error => { console.error('Error:', error); alert('查询库存失败'); });

        });

    }

    // 更新库存

    if (document.getElementById('updateInventoryForm')) {

        document.getElementById('updateInventoryForm').addEventListener('submit', function(e) {

            e.preventDefault();

            const formData = { product_id: document.getElementById('productId').value,

                delta: parseInt(document.getElementById('delta').value)

            };

            fetch('/api/inventory/update', { method: 'POST',

                headers: { 'Content-Type': 'application/json'},

                body: JSON.stringify(formData)

            }).then(response => response.json())

                .then(data => { alert('库存更新成功'); })

                .catch(error => { console.error('Error:', error); alert('更新库存失败'); });

        });

    }

    if (document.getElementById('reserveInventoryForm')) {

        document.getElementById('reserveInventoryForm').addEventListener('submit', function(e) {

            e.preventDefault();

        });

    }

});

// 预留/释放库存

function fechtData(svTp) {

    let t = "/api/inventory/reserve", k = "预留"

    if (svTp === true)  { t = "/api/inventory/release"; k = "释放" }

    const formData = { product_id: document.getElementById('productId').value,

        quantity: parseInt(document.getElementById('reserveQuantity').value),

        order_id: document.getElementById('reserveOrderId').value

    };

    fetch(t, { method: 'POST', headers: { 'Content-Type': 'application/json' },

        body: JSON.stringify(formData) }).then(response => response.json())

        .then(data => { alert(k+'库存成功'); })

        .catch(error => { console.error('Error:', error); alert(k+'库存失败'); });

}

7 测调试与运行

7.1 独立微服测试

A. 订单

# bash,创建订单

curl.exe -X POST http://localhost:9001/orders -H "Content-Type: application/json" \

-d '{"user_id": "user123", "product_id": "prod456", "quantity": 2, "total_price": 99.98}'

# bash,查询订单

curl.exe http://localhost:9001/orders/ {order_id}

# bash,确认订单:

curl -X PUT http://localhost:9001/orders/ {order_id}/confirm -H "Content-Type: application/json" \

-d '{"status": "confirmed"}'

# bash,刷新订单:

curl -X PUT http://localhost:9001/orders/ {order_id}/refresh

浏览器测试、ApiFox测试、IDE跟踪调试、Navicat数据库监护的典型过程截图,如图2~4所示。

图2 “电商订单微服务”测试与监护组合截图

图3 “电商订单微服务”测试组合截图

图4 “电商订单微服务”RustRoverIDE跟踪调试组合截图

B. 支付

# bash,支付订单

curl.exe -X POST http://localhost:9002/orders/5364b201-e155-4967-b796-96cfc44aa8ac/pay -H "Content-Type: application/json" -d '{"order_id": "orders/5364b201-e155-4967-b796-96cfc44aa8ac", "currency":"CNY", "payment_method":"WeChatPay"}'

# bash,查询订单

curl http://localhost:9002/orders/5364b201-e155-4967-b796-96cfc44aa8ac

# bash,查询用户订单:

curl " http://localhost:9002/orders?user_id=user123&pay_status=Paid "

浏览器测试、ApiFox测试、IDE跟踪调试、Navicat数据库监护的典型过程截图,如图5~7所示。由于逐步开发,作订单设计表时没有考虑订单相应的支付表例,故测试前,需要在Navicat管理器中先向orders集合中添加字段--pay_status及其默认值Pending,如图5所示。

图5 “电商支付微服务”数据库操作与监护组合截图

图6 “电商支付微服务”测试组合截图

图7 “电商支付微服务”RustRoverIDE跟踪调试组合截图

C. 库存

a. 测试操作

# 创建库存记录:

POST /api/inventory

请求体:{"product_id": "prod123"}

# 查询库存:

GET /api/inventory?product_id=prod123

# 更新库存:

POST /api/inventory/update

请求体:{"product_id": "prod123", "delta": 10} (正数增加,负数减少)

# 预留库存:

POST /api/inventory/reserve

请求体:{"product_id": "prod123", "quantity": 5, "order_id": "order123"}

b. 过程记录

浏览器测试、ApiFox测试、IDE跟踪调试、Navicat数据库监护的典型截图,如图8~10所示。

图8 “电商库存微服务”测试组合截图

图9 “电商库存微服务”测试与数据库操作及监护组合截图

图10 “电商库存微服务”RustRoverIDE跟踪调试组合截图

D. 网关

ApiFox测试、IDE跟踪调试的典型过程截图,如图11~12所示。

图11 “网关路由”的IDE跟踪调试过程截图

图12 “网关路由”的ApiFox典型测试过程组合截图

7.2 整体运行与测试

编译得到四个可执行文件:gateway.exe、inventory_service.exe、order_service.exe、payment_service.exe,检查并启动MongoDB数据库,启动Nacos注册配置中心[startup.cmd -m standalone],再逐一启动四个可执行文件。成功运行后的Nacos、gateway.exe、inventory_service.exe、order_service.exe、payment_service.exe,如13组合截图所示。Nacos的浏览器监护页面如图14所示。注意,gateway.exe运行时需要templates和static目录页面文件,可把这两个目录拷贝到gateway.exe同一目录下,两启动,以免页面访问不能打开。

图13 “电商订单系统”开发及其支撑软件启动与运行组合截图

图14 “电商订单系统”的Nacos浏览器监护截图

浏览器交互访问及其跟踪调试截图,如图15~18所示。

图15 “电商订单系统”的主页操作浏览及其跟踪调试截图

图16 “电商订单系统”的订单页操作浏览及其跟踪调试截图

图17 “电商订单系统”的支付操作浏览及其跟踪调试截图

图18 “电商订单系统”的库存操作浏览及其跟踪调试截图

http://www.xdnf.cn/news/17600.html

相关文章:

  • MySQL的逻辑架构和SQL执行的流程:
  • Stream流应用
  • MPLS特性之PHP(Penultimate Hop Popping)
  • afsim2.9_使用QtCreator和VSCode编译
  • 【杂谈】-智能代理+可观察性:构建下一代复杂系统监控体系
  • 《解锁 C++ 起源与核心:命名空间用法 + 版本演进全知道》
  • AUTOSAR进阶图解==>AUTOSAR_ASWS_TransformerGeneral
  • 关于linux操作系统下的文件操作方法:
  • ThinkPHP8学习篇(二):路由
  • 20250810 | 深度学习入门笔记1
  • 从色彩心理学看嵌入式设备UI设计:原则、挑战与实践
  • C语言-动态内存分配函数、变量属性(全局、局部、静态、只读)、C语言内存结构;
  • go加速配置(下载第三方库)
  • [0CTF 2016]piapiapia
  • 【秋招笔试】2025.08.09美团秋招研发岗机考真题-第二题
  • 在Mac上搭建本地AI工作流:Dify与DeepSeek的完美结合
  • 【2025CVPR-图象分类方向】ProAPO:视觉分类的渐进式自动提示优化
  • 【MySQL——第三章 :MySQL库表操作】
  • STM32 DMAMUX 平台驱动程序注册
  • 机器学习——DBSCAN 聚类算法 + 标准化
  • 解读 GPT-5:从“博士级 AI 专家”能力到 OpenAI API Key 获取与实践(提示工程→性能调优全流程)
  • 【递归、搜索与回溯算法】深度优先搜索
  • Spring AOP 底层实现(面试重点难点)
  • 结构化记忆、知识图谱与动态遗忘机制在医疗AI中的应用探析(上)
  • scikit-learn/sklearn学习|线性回归解读
  • 深度相机---双目深度相机
  • 神经机器翻译(NMT)框架:编码器-解码器(Encoder-Decoder)结构详解
  • tlias智能学习辅助系统--原理篇-SpringBoot原理-自动配置-自定义starter
  • Agent在游戏行业的应用:NPC智能化与游戏体验提升
  • SupChains团队:化学品制造商 ChampionX 供应链需求预测案例分享(十七)