分布微服务电商订单系统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 "电商订单系统"的库存操作浏览及其跟踪调试截图

相关推荐
kaizq14 小时前
分布微服务电商订单系统Rust编码开发[上]
rust编程·分布微服务框架·电商订单系统·订单/支持/库存