如何开发一套固定资产管理系统?(附架构图+流程图+代码参考)

简介: 固定资产管理涉及采购、入库、维修、盘点、报废等多个环节,是企业资产保值增值的关键。本文详解固定资产管理系统(FAMS)的核心功能、系统架构、资产全生命周期流程,并提供功能设计、开发实操技巧与关键代码示例,涵盖台账、申购、入库、报修、处置、盘点等重点模块。内容聚焦企业落地实践,帮助提升资产管理效率、降低风险、保障审计合规。

固定资产这块,看起来是“流水线式”的业务,但实际上牵扯采购、入库、维修、盘点、报废、折旧和权限审计等多个环节。做得好能帮企业把资产“看得清、管得准、用得好”;做得不好就是账实不符、报表不靠谱、审计被揪出问题。下面我把从概念到落地、从架构到流程、再到关键代码都给你一套可直接参考的实现方案 —— 重点聚焦您列的模块:固定资产台账、固定资产申购、固定资产入库、固定资产报修、固定资产处置、固定资产盘点、盘点明细、基础设置


本文主要内容

  1. 为什么要讲固定资产管理?痛点与收益
  2. 什么是固定资产管理系统(FAMS)——核心功能概览
  3. 固定资产管理系统的高层架构(含架构图)
  4. 资产全生命周期业务流程(含流程图)
  5. 详细功能设计(逐项解释:台账/申购/入库/报修/处置/盘点/基础设置)
  6. 开发实操技巧与注意点(性能、安全、数据一致性、条码/RFID、折旧)
  7. 关键实现(数据库设计、API示例、盘点事务、报废与审核流程)——附代码参考
  8. 实施效果与KPI(如何衡量价值和ROI)
  9. 部署与运维建议(备份、审计日志、升级)

一、为什么要讲固定资产管理?痛点与收益

很多企业把固定资产当“捡着用”的东西:买了记账、用着不管、盘点靠人工。常见痛点:

  • 台账不齐全:资产位置、责任人、状态不准;
  • 报修/维修记录散落,维修成本看不清;
  • 盘点耗时耗力,账实不符难查原因;
  • 报废/处置流程不规范,审计风险高;
  • 折旧、报表无法自动化,财务凭证手工加工。

收益是直观的:减少资产流失、降低重复采购、提高盘点效率、提升审计合规性、准确计算折旧从而提升财务透明度。对于中大型企业,固定资产系统能降低采购成本与维修成本的叠加收益很可观。


二、什么是固定资产管理系统(FAMS)

一句话:FAMS 是用来记录和管理企业所有长期使用、价值较高的资产,从采购到处置全流程数字化的系统。核心模块:

  • 资产台账(主数据)
  • 资产申购(需求、审批)
  • 资产入库(验收、编码、上架、领用)
  • 资产报修/维修(工单、维修记录、成本)
  • 资产处置(报废、拍卖、调拨)
  • 资产盘点(盘点计划、盘点明细、差异处理)
  • 基础设置(资产分类、地点、部门、折旧策略、字典)
  • 报表与审计(资产清单、折旧明细、维修成本、盘点差异)
  • 接口与扩展(ERP、财务、条码/RFID、移动端)

三、固定资产管理系统高层架构(示意)

下面给一个简洁的三层架构图(可以用 mermaid 渲染或画成图):

graph LR

 subgraph Client

   WebApp[Web 前端]

   Mobile[移动扫码/APP]

 end

 subgraph Backend

   API[REST/GraphQL API]

   Auth[鉴权服务(OAuth2/JWT)]

   Worker[异步任务/定时任务(折旧、提醒)]

   Integrator[ERP/财务集成模块]

 end

 subgraph DB

   Postgres[(PostgreSQL)]

   Redis[(Redis 缓存/队列)]

 end

 Client -->|HTTPS| API

 Mobile -->|HTTPS| API

 API --> Auth

 API --> Postgres

 API --> Redis

 Worker --> Postgres

 Worker --> Redis

 API --> Integrator

说明:

  • 前端:PC 管理端 + 移动扫码端(盘点、验收、报修)
  • 后端:API 层、鉴权、定时任务(每月折旧、未处理报修提醒)
  • DB:关系型数据库保存主数据(首选 PostgreSQL),Redis 做缓存/分布式锁/队列
  • 集成:与 ERP/财务通过消息队列或 API 同步凭证/报表

四、资产全生命周期业务流程(流程图)

一个典型资产生命周期(简化):

flowchart TD

 A[申购] --> B[审批]

 B --> C[采购入库]

 C --> D[验收并入固定资产台账]

 D --> E[使用(领用/调拨)]

 E --> F[报修/维修]

 F --> E

 E --> G[盘点]

 G --> H{是否一致?}

 H -- 是 --> E

 H -- 否 --> I[调整台账 / 报差异]

 E --> J[处置(报废/出售)]

 J --> K[财务处理/更新台账]

盘点通常是周期性(年中/年末/专项)或随机抽查。每一步都应有审批链与操作人审计记录。


五、详细功能设计(逐项解释)

5.1固定资产台账(Asset)

作用:是系统的核心主表,记录资产基础信息及当前状态。建议字段:

  • asset_id(系统主键)
  • asset_code(资产编码/条码)
  • name, category_id, model, serial_no
  • purchase_order_id, supplier_id
  • purchase_date, purchase_price
  • depreciation_policy_id
  • location_id(保管地点/部门/仓库)
  • custodian_user_id(使用人/责任人)
  • status(在用/借出/维修/报废/处置中)
  • created_at, updated_at
  • current_value, accumulated_depreciation

要点:资产编码规则要统一(如:YYMM-分类-流水),同时保留条码或二维码字段用于扫码。

5.2固定资产申购

作用:由使用部门发起采购申请,包含资产明细、预算、审批流程(多级)。与采购模块或 ERP 对接,审批通过后生成采购单或推送到采购系统。

要点:支持模板、预算检查、审批意见记录。审批流可基于部门/金额/类别自定义。

5.3固定资产入库(验收)

作用:采购到货后验收并转入资产台账或待验收状态。入库流程包括:检验、打标(贴条码/二维码)、录入序列号/保修期、绑定保管人。

要点:移动端扫码验收效率高;入库要支持批量导入(CSV/Excel)并做幂等性检查(避免重复入库)。

5.4固定资产报修/维修

作用:使用者发起报修工单,维修完成后记录维修成本、零件、更换记录以及维修人员信息。

要点:维修单应与资产关联,并写入资产历史(用于成本分析);支持外包维修单据上传与费用结算。

5.5固定资产处置(报废、出售、调拨)

作用:不再使用时进入处置流程,含审批、财务处理(计提折旧/残值)、处置结果入账(如出售收入)。

要点:处置流程要与财务紧密对接,产生凭证。处置前要校验是否存在未完成维修/质押等状态。

5.6固定资产盘点 & 盘点明细

作用:周期性核对账面与实物。盘点包含:制定盘点计划、分配盘点任务、移动端扫码盘点、生成盘点明细并对差异进行处理(调整台账或提交申诉)。

要点:

  • 支持盲盘(盘点人不见账面数据)和公开盘;
  • 盘点要使用事务防止并发修改(例如一个资产在盘点时不能同时被报废);
  • 盘点明细要记录扫描时间、扫描人、设备等元数据。

5.7基础设置

包括:资产类别、科目映射、部门/地点、折旧政策(年限、方法:直线法/加速折旧)、条码规则、审批模板、用户角色权限等。基础设置决定了系统行为,务必做好权限与版本管理。


六、开发实操技巧与注意点(干货)

下面是实战中容易忽视但决定系统稳定性的点:

6.1资产编码 & 幂等性

  • 建议后端统一生成 asset_code,规则例如 AS-202508-IT-000123;
  • 批量导入时用 external_reference 或采购单号做幂等判断,避免重复。

6.2乐观锁与事务

  • 盘点、入库、处置等关键操作使用数据库事务;
  • 对于高并发更新(例如同时盘点和报废同一物品),使用乐观锁(version 字段)或 Redis 分布式锁。

6.3审计日志(不可删)

  • 每次状态变更记录:操作人、时间、旧值、新值、操作来源(web/mobile)。
  • 审计日志要独立表存,便于导出与审计。

6.4折旧与定时任务

  • 折旧建议放在后台 Worker(每日/每月批处理),并记录折旧分录日与累计折旧;
  • 折旧计算配置化(残值率、折旧年限、起算月)。

6.5条码/RFID 与移动端

  • 盘点与验收强烈建议用扫码;二维码信息只需包含 asset_code 或 asset_id;
  • 若引入 RFID,需与标签管理、批次入库整合,注意读取冲突与中间件设计。

6.6性能与分表

  • 台账量大(数十万条)时,按资产类别或年分表;
  • 报表(如折旧明细、维修成本)用 OLAP 数据库或定时汇总表避免对主库造成压力。

6.7权限与审批

  • 按角色/部门粒度控制操作;审批流建议支持自定义规则(金额、类别、部门);
  • 审批意见要不可篡改、可导出。

6.8数据迁移与对账

  • 上线迁移时保留原系统 ID,写入 legacy_id 字段,保证历史可追溯;
  • 首次盘点上线应做一次全面清点以校正台账。

七、关键实现(数据库设计 + API + 事务示例)

下面给出可直接用的参考代码片段(Postgres + Node.js (Express + Sequelize))。这只是参考实现,部署前请做安全审核和适配。

7.1 数据库表(PostgreSQL)示例(关键表)

-- 资产主表

CREATE TABLE asset (

 id BIGSERIAL PRIMARY KEY,

 asset_code VARCHAR(64) NOT NULL UNIQUE,

 name VARCHAR(200) NOT NULL,

 category_id INT NOT NULL,

 model VARCHAR(100),

 serial_no VARCHAR(100),

 purchase_date DATE,

 purchase_price NUMERIC(14,2),

 current_value NUMERIC(14,2),

 accumulated_depreciation NUMERIC(14,2) DEFAULT 0,

 location_id INT,

 custodian_user_id BIGINT,

 status VARCHAR(32) DEFAULT 'IN_USE', -- IN_USE, MAINTENANCE, SCRAPPED, DISPOSED

 version INT DEFAULT 0, -- 乐观锁

 created_at TIMESTAMP DEFAULT now(),

 updated_at TIMESTAMP DEFAULT now()

);

-- 资产历史(变更、维修、处置记录)

CREATE TABLE asset_history (

 id BIGSERIAL PRIMARY KEY,

 asset_id BIGINT NOT NULL REFERENCES asset(id),

 type VARCHAR(50) NOT NULL, -- PURCHASE, MAINTENANCE, TRANSFER, DISPOSAL, INVENTORY

 note TEXT,

 cost NUMERIC(14,2),

 operator_id BIGINT,

 created_at TIMESTAMP DEFAULT now()

);

-- 盘点表

CREATE TABLE inventory_count (

 id BIGSERIAL PRIMARY KEY,

 name VARCHAR(200) NOT NULL,

 start_at TIMESTAMP,

 end_at TIMESTAMP,

 status VARCHAR(20) DEFAULT 'PLANNED' -- PLANNED, IN_PROGRESS, COMPLETED

);

CREATE TABLE inventory_count_detail (

 id BIGSERIAL PRIMARY KEY,

 inventory_count_id BIGINT REFERENCES inventory_count(id),

 asset_id BIGINT REFERENCES asset(id),

 scanned BOOLEAN DEFAULT false,

 scanned_by BIGINT,

 scanned_at TIMESTAMP,

 expected_location_id INT,

 scanned_location_id INT,

 note TEXT

);

建索引:

CREATE INDEX idx_asset_code ON asset(asset_code); CREATE INDEX idx_asset_status ON asset(status); CREATE INDEX idx_inventory_count_id ON inventory_count_detail(inventory_count_id);

7.2 后端模型(Sequelize)示例(Node.js)

// models/asset.js

module.exports = (sequelize, DataTypes) => {

 const Asset = sequelize.define('Asset', {

   id: { type: DataTypes.BIGINT, primaryKey: true, autoIncrement: true },

   asset_code: { type: DataTypes.STRING, unique: true },

   name: DataTypes.STRING,

   category_id: DataTypes.INTEGER,

   model: DataTypes.STRING,

   serial_no: DataTypes.STRING,

   purchase_date: DataTypes.DATEONLY,

   purchase_price: DataTypes.DECIMAL(14,2),

   current_value: DataTypes.DECIMAL(14,2),

   accumulated_depreciation: { type: DataTypes.DECIMAL(14,2), defaultValue: 0 },

   location_id: DataTypes.INTEGER,

   custodian_user_id: DataTypes.BIGINT,

   status: { type: DataTypes.STRING, defaultValue: 'IN_USE' },

   version: { type: DataTypes.INTEGER, defaultValue: 0 }

 }, {

   tableName: 'asset',

   timestamps: true,

   updatedAt: 'updated_at',

   createdAt: 'created_at',

   version: true // Sequelize 会使用 version 字段做乐观锁

 });

 Asset.associate = (models) => {

   Asset.hasMany(models.AssetHistory, { foreignKey: 'asset_id' });

 };

 return Asset;

};

7.3 关键 API 示例:入库并创建台账(含事务与幂等)

// routes/asset.js

const express = require('express');

const router = express.Router();

router.post('/inbound', async (req, res) => {

 const { purchaseOrderId, items, operatorId } = req.body;

 const t = await sequelize.transaction();

 try {

   // 幂等:检查 purchaseOrderId 是否已处理

   const existing = await AssetHistory.findOne({ where: { note: `PO:${purchaseOrderId}`, type: 'PURCHASE' }, transaction: t });

   if (existing) {

     await t.rollback();

     return res.status(409).json({ message: '采购单已入库' });

   }

   const createdAssets = [];

   for (const it of items) {

     const code = generateAssetCode(it.category_id);

     const asset = await Asset.create({

       asset_code: code,

       name: it.name,

       category_id: it.category_id,

       model: it.model,

       serial_no: it.serial_no,

       purchase_date: it.purchase_date,

       purchase_price: it.price,

       current_value: it.price,

       location_id: it.location_id,

       custodian_user_id: it.custodian_user_id

     }, { transaction: t });

     await AssetHistory.create({

       asset_id: asset.id,

       type: 'PURCHASE',

       note: `PO:${purchaseOrderId}`,

       cost: it.price,

       operator_id: operatorId

     }, { transaction: t });

     createdAssets.push(asset);

   }

   await t.commit();

   res.json({ created: createdAssets.length, assets: createdAssets });

 } catch (err) {

   await t.rollback();

   console.error(err);

   res.status(500).json({ message: '入库失败', error: err.message });

 }

});

generateAssetCode 可简单实现为 AS-YYYYMM-category-流水,但需保证线程安全(可用数据库序列或 Redis 计数器)。

7.4 盘点事务示例(保证账实一致处理)

盘点时若发现差异,需要在事务中更新台账与写入 asset_history:

async function processInventoryResult(inventoryId, detailList, operatorId) {

 const t = await sequelize.transaction();

 try {

   for (const d of detailList) {

     const asset = await Asset.findByPk(d.asset_id, { transaction: t, lock: t.LOCK.UPDATE });

     if (!asset) {

       // 新发现的实物(账外资产)

       const newAsset = await Asset.create({

         asset_code: generateAssetCode(d.category_id || 0),

         name: d.name || '未知',

         category_id: d.category_id || null,

         current_value: d.estimated_value || 0,

         status: 'IN_USE'

       }, { transaction: t });

       await AssetHistory.create({ asset_id: newAsset.id, type: 'INVENTORY_FOUND', note: `Found in inventory ${inventoryId}`, operator_id: operatorId }, { transaction: t });

     } else {

       // 若位置或状态不一致,记录并更新

       if (asset.location_id !== d.scanned_location_id) {

         await AssetHistory.create({ asset_id: asset.id, type: 'INVENTORY_ADJUST', note: `Location mismatch. Expected ${asset.location_id}, found ${d.scanned_location_id}`, operator_id: operatorId }, { transaction: t });

         asset.location_id = d.scanned_location_id;

         await asset.save({ transaction: t });

       }

       // 标记扫描

       await InventoryCountDetail.update({ scanned: true, scanned_by: operatorId, scanned_at: new Date() }, { where: { id: d.detail_id }, transaction: t });

     }

   }

   await InventoryCount.update({ status: 'COMPLETED', end_at: new Date() }, { where: { id: inventoryId }, transaction: t });

   await t.commit();

 } catch (err) {

   await t.rollback();

   throw err;

 }

}

7.5 报废/处置的关键点

报废处置要生成审批流并在批准后写资产历史、更新状态,并把残值/处置价写入财务接口。示例:

// 审批通过后调用

await sequelize.transaction(async (t) => {

 await AssetHistory.create({ asset_id, type: 'DISPOSAL', note: disposalNote, cost: disposalPrice, operator_id }, { transaction: t });

 await Asset.update({ status: 'DISPOSED', current_value: 0 }, { where: { id: asset_id }, transaction: t });

 // 推送会计凭证到财务系统(异步)

 queuePush('finance.disposal', { asset_id, disposalPrice, operator_id });

});

在这里我给大家推荐一个业务人员就能够直接上手的高性价比、零代码平台——简道云固定资产管理系统,简道云背靠国内BI龙头帆软,在数据处理、数据展示上的能力有绝对优势,数据分析支持高度自定义,任何分析需求都可以快速制作仪表盘,简道云固定资产管理系统提供全面的资产信息管理功能,用户可以实时跟踪资产的使用情况和位置,确保资产利用的最大化。


八、实施效果与KPI(如何衡量价值)

实施后可以用这些 KPI 来评估系统价值:

  • 盘点差异率(资产账面差异数 / 资产总数)下降比例
  • 平均盘点时间/人(盘点效率提升)
  • 采购重复率降低(同类资产重复采购次数)
  • 维修成本 / 年(是否下降)
  • 折旧准确率与财务调整条数(审计问题减少)

举例:某公司上线 FAMS 后一年内盘点差异率从 6% 降到 1.2%,重复采购成本下降 18%,折旧与财务对账工作量减少 40%。


九、部署与运维建议

  • 数据备份:生产库每日增量、每周全量,关键报表定期导出;
  • 审计日志:保留至少 7 年(或依企业合规要求),日志应该是不可篡改的(写入不可修改表或外部审计库);
  • 升级与回滚:DB 变更采用幂等迁移脚本(Flyway 或 Sequelize migration),升级前在预发做一次全量盘点模拟;
  • 灾备:在不同可用区或异地部署 DB 只读副本,快速故障切换;
  • 权限管理:最小权限原则,关键操作(处置、批量删除)需要二次确认或二级审批。

十、FAQ

FAQ 1:资产编码要怎么设计,是否可以用条码/二维码代替人工编码?

资产编码建议采用规则化、结构化的方式,例如 AS-YYYYMM-分类-流水号。这样既可通过编码快速定位采购时间和资产类别,也便于分表和检索。条码/二维码是编码的载体,不是替代规则。通常做法是:系统生成唯一 asset_code,然后将该编码制成二维码或条码贴在设备上。盘点和验收时只需要扫码,就能把条码映射回 asset_code。如果以后要支持 RFID,也可以把 asset_code 存入标签的 UID 映射表。注意编码生成要保证幂等,最好用数据库序列或 Redis 原子计数来生成流水,避免并发冲突。

FAQ 2:盘点对业务影响大,如何在不影响生产的情况下做好盘点?

一个成熟的盘点实践是:先做风险评估并制定盘点计划,分区域和时间窗口执行,优先处理高价值/高风险资产。采用移动扫码工具可以显著缩短停机时间,支持夜间或非高峰期盘点,另外支持抽样盘点(对低价值或不常移动资产),并在盘点过程中对发现的问题采用“先记录后处理”的策略:立即记录盘差并标记责任人,后续通过事务性调整来修正台账,以免盘点过程中阻塞生产。盲盘和公开盘的混用能减少人为作假风险,并且将盘点与维护、巡检工作结合起来,减少重复工作。

FAQ 3:折旧如何在系统中实现,是否需要和财务系统打通?

折旧通常按会计准则(例如直线法)在系统中按期计算:每月或每年运行折旧任务,计算当期折旧额并写入资产累计折旧与当期凭证。系统应支持配置折旧政策(年限、残值率、起算日、折旧方法)。与财务系统的对接非常必要:折旧结果要推送给财务系统生成凭证,避免人工手动录入导致误差。对接方式可以用 API 或消息队列异步传输折旧分录,确保财务凭证与资产台账一致并保留相关凭证号以备审计。


小结(落地建议)

  • 第一阶段:先做资产台账能覆盖 80% 问题(导入历史数据、建立编码、上手移动扫码验收与盘点)。
  • 第二阶段:上线报修/维修与处置流程,建立维修成本追踪与处置审批。
  • 第三阶段:与财务 ERP 对接,自动化折旧和凭证生成。
  • 技术上选 Postgres + Node.js/Java + 移动扫码 App 的组合能快速实现且易于扩展;企业规模大时考虑微服务拆分与OLAP报表库。
相关文章
|
2月前
|
前端开发 JavaScript BI
如何开发车辆管理系统中的车务管理板块(附架构图+流程图+代码参考)
本文介绍了中小企业如何通过车务管理模块提升车辆管理效率。许多企业在管理车辆时仍依赖人工流程,导致违章处理延误、年检过期、维修费用虚高等问题频发。将这些流程数字化,可显著降低合规风险、提升维修追溯性、优化调度与资产利用率。文章详细介绍了车务管理模块的功能清单、数据模型、系统架构、API与前端设计、开发技巧与落地建议,以及实现效果与验收标准。同时提供了数据库建表SQL、后端Node.js/TypeScript代码示例与前端React表单设计参考,帮助企业快速搭建并上线系统,实现合规与成本控制的双重优化。
|
2月前
|
运维 监控 安全
公链开发中的高可用架构设计要点
本指南提供公链高可用架构的可复用流程与模板,涵盖目标拆解、先决条件、分步执行、故障排查及验收标准,结合跨链DApp与量化机器人案例,提升落地效率与系统稳定性。
|
2月前
|
消息中间件 运维 监控
交易所开发核心架构拆解与流程图
本文系统解析交易所架构核心要素,从接入层到清算结算,结合系统流程图拆解各模块职责与协作机制。深入剖析撮合引擎、账本设计与风控逻辑,建立性能、可用性、安全性等多维评估标准,并提供可落地的流程图绘制、压测优化与进阶学习路径,助力构建高效、安全、可扩展的交易系统。(238字)
|
3月前
|
机器学习/深度学习 人工智能 搜索推荐
从零构建短视频推荐系统:双塔算法架构解析与代码实现
短视频推荐看似“读心”,实则依赖双塔推荐系统:用户塔与物品塔分别将行为与内容编码为向量,通过相似度匹配实现精准推送。本文解析其架构原理、技术实现与工程挑战,揭秘抖音等平台如何用AI抓住你的注意力。
774 7
从零构建短视频推荐系统:双塔算法架构解析与代码实现
|
2月前
|
Cloud Native Serverless API
微服务架构实战指南:从单体应用到云原生的蜕变之路
🌟蒋星熠Jaxonic,代码为舟的星际旅人。深耕微服务架构,擅以DDD拆分服务、构建高可用通信与治理体系。分享从单体到云原生的实战经验,探索技术演进的无限可能。
微服务架构实战指南:从单体应用到云原生的蜕变之路
|
弹性计算 API 持续交付
后端服务架构的微服务化转型
本文旨在探讨后端服务从单体架构向微服务架构转型的过程,分析微服务架构的优势和面临的挑战。文章首先介绍单体架构的局限性,然后详细阐述微服务架构的核心概念及其在现代软件开发中的应用。通过对比两种架构,指出微服务化转型的必要性和实施策略。最后,讨论了微服务架构实施过程中可能遇到的问题及解决方案。
|
5月前
|
缓存 Cloud Native Java
Java 面试微服务架构与云原生技术实操内容及核心考点梳理 Java 面试
本内容涵盖Java面试核心技术实操,包括微服务架构(Spring Cloud Alibaba)、响应式编程(WebFlux)、容器化(Docker+K8s)、函数式编程、多级缓存、分库分表、链路追踪(Skywalking)等大厂高频考点,助你系统提升面试能力。
278 0
|
Cloud Native Devops 云计算
云计算的未来:云原生架构与微服务的革命####
【10月更文挑战第21天】 随着企业数字化转型的加速,云原生技术正迅速成为IT行业的新宠。本文深入探讨了云原生架构的核心理念、关键技术如容器化和微服务的优势,以及如何通过这些技术实现高效、灵活且可扩展的现代应用开发。我们将揭示云原生如何重塑软件开发流程,提升业务敏捷性,并探索其对企业IT架构的深远影响。 ####
353 3
|
Java 开发者 微服务
从单体到微服务:如何借助 Spring Cloud 实现架构转型
**Spring Cloud** 是一套基于 Spring 框架的**微服务架构解决方案**,它提供了一系列的工具和组件,帮助开发者快速构建分布式系统,尤其是微服务架构。
1000 70
从单体到微服务:如何借助 Spring Cloud 实现架构转型