架构设计与UML建模:关联、关系与深度实践
详细解析架构设计与UML建模:
-
架构设计与UML建模的关联:UML是表达架构设计的语言/工具,架构设计是过程/产物。
-
关系与异同点:UML是图形化建模语言,用于可视化、说明、构建和记录软件系统的构件;架构设计关注系统的结构、行为、约束等。相同点:都关注系统的高层抽象;不同点:UML是工具/表示法,架构设计是设计活动/结果。UML可以用于表达架构的不同视图(4+1视图)。
-
提供具体实例:比如一个在线书店系统或之前的智能温控器,但最好是一个更典型的软件架构示例(如微服务架构的电商系统)。用UML图(用例图、类图、组件图、部署图、时序图等)来建模架构设计。然后详细解释每个模块的实现。
要求:Markdown格式,使用mermaid(注意是mermaid,不是mermind)。建立项目文件结构组织,举实例详细深入解析,并详细展开每个具体模块的实现。
输出包含:
-
标题和目录
-
关联与异同点分析
-
实例选择(如“在线书店系统”)
-
UML建模(多个图)
-
项目文件结构
-
每个模块的实现细节(伪代码/代码说明,或者类实现细节)
-
总结
注意深度:需要详细展开每个具体模块的实现,不仅仅是类图,还要有实现层面的描述(比如Spring Boot微服务的代码结构,或分层架构的实现类)。
选择:在线书店系统(BookStore),采用微服务架构 + 前后端分离。展示架构设计如何用UML建模,并展开实现。
架构设计与UML建模:关联、关系与深度实践
目录
- 架构设计与UML建模的关联
- 关系与异同点
- 实例:在线书店系统(微服务架构)
- 3.1 系统需求与架构风格
- 3.2 用UML表达架构设计(多视图)
- 3.3 项目文件结构组织
- 3.4 各模块详细实现
- 总结
1. 关联
架构设计 和 UML建模 之间的关系可以概括为:UML是表达架构设计的标准语言,架构设计是UML建模要捕捉的核心内容。
- 架构设计:解决系统的高层结构、行为、质量属性、约束与权衡,输出架构描述(包括组件、连接器、接口、部署、设计原理)。
- UML(统一建模语言):一种图形化建模语言,提供多种视图(结构、行为、交互、部署等)来描述软件系统的各个方面。它不是方法论,而是一种表示法。
关联点:
- UML 为架构设计提供了可视化载体,使得抽象的设计决策变得具体、可沟通、可评审。
- 架构设计的不同视角(逻辑视图、进程视图、物理视图等)可以精确映射到UML的特定图表类型。
- UML 的扩展机制(原型、约束、标记值)可以表达架构中的非功能性需求、模式标注等。
2. 关系与异同点
| 维度 | 架构设计 | UML建模 |
|---|---|---|
| 本质 | 设计活动 + 产物(决策、结构、原则) | 建模语言(一组图形符号与语义规则) |
| 目标 | 管理复杂性、满足质量属性、指导实现 | 提供无歧义的交流工具,支持正向/逆向工程 |
| 抽象层级 | 可高可低,但侧重系统级、子系统级 | 可高可低,从用例到类到部署均能覆盖 |
| 输出形式 | 架构文档、ADL(架构描述语言)、UML图、ADL图 | 各种UML图(类图、时序图、组件图等) |
| 是否必须 | 任何复杂系统都必须进行(显式或隐式) | 可选工具,不强制使用 |
相同点
- 目标一致:都为了理解、设计、沟通和记录系统。
- 抽象表达:都使用抽象概念(组件、接口、协作)而非实现细节。
- 支持多视图:架构设计有4+1视图,UML也有对应的9种图。
不同点
- 范围:架构设计包含非功能性权衡、技术选型、部署拓扑等,UML本身不表达“为什么”做这个决策,只表达“是什么”。
- 精确程度:UML有严格语义(如类图的多重性、时序图的生命线),而架构设计中的“连接器”可能是REST、消息队列等,需要UML配合文本描述。
- 生命周期:架构设计在早期阶段决策后持续演化;UML可以在分析、设计、实现、测试各阶段使用,但通常与代码保持同步。
关系总结:架构设计是“内容”,UML是“载体”;好的架构设计应善用UML来清晰表达,但UML不是唯一载体(也可以用C4模型、ADL等)。
3. 实例:在线书店系统(微服务架构)
3.1 系统需求与架构风格
功能需求:
- 用户管理(注册、登录、个人信息)
- 图书目录浏览、搜索
- 下单、支付、查看订单历史
- 库存管理(管理员)
- 评价系统(用户对图书评分+评论)
质量属性:
- 高可用(99.9%)
- 可伸缩性(支持黑五高峰)
- 数据一致性(最终一致性允许,但订单支付需强一致)
- 安全性(HTTPS、JWT鉴权)
架构风格:微服务架构 + API网关 + 事件驱动(用于库存更新和评价通知)
3.2 用UML表达架构设计(多视图)
采用 4+1视图模型 并用UML图分别表达。
3.2.1 逻辑视图(类图)——核心领域模型
3.2.2 进程/组件视图(组件图)——微服务划分
3.2.3 开发视图(包图)——模块组织
3.2.4 物理视图(部署图)——K8s集群部署
3.2.5 场景视图(时序图)——下单流程
3.3 项目文件结构组织
采用 Monorepo 风格,每个微服务独立子项目,共享公共库。
bookstore/
├── docs/
│ ├── architecture/
│ │ ├── 4+1_views.md # 本文档的扩展
│ │ ├── uml_diagrams.md # 所有mermaid源文件
│ │ └── adr/ # 架构决策记录
│ │ ├── 001-microservice-boundaries.md
│ │ └── 002-event-sourcing-inventory.md
│ └── README.md
├── api-gateway/ # Spring Cloud Gateway
│ ├── src/main/java/com/bookstore/gateway/
│ │ ├── config/
│ │ │ ├── RouteConfig.java
│ │ │ └── SecurityConfig.java
│ │ ├── filter/
│ │ │ └── JwtAuthFilter.java
│ │ └── GatewayApplication.java
│ └── pom.xml
├── services/
│ ├── user-service/ # 用户服务(Spring Boot)
│ │ ├── src/main/java/com/bookstore/user/
│ │ │ ├── domain/User.java
│ │ │ ├── web/UserController.java
│ │ │ ├── service/UserService.java
│ │ │ ├── repository/UserRepository.java
│ │ │ └── security/PasswordEncoder.java
│ │ ├── src/main/resources/application.yml
│ │ └── pom.xml
│ ├── catalog-service/ # 图书目录服务(Spring Boot + ElasticSearch)
│ │ ├── src/main/java/com/bookstore/catalog/
│ │ │ ├── domain/Book.java
│ │ │ ├── search/BookSearchService.java
│ │ │ └── web/CatalogController.java
│ │ └── pom.xml
│ ├── order-service/ # 订单服务(包含Saga)
│ │ ├── src/main/java/com/bookstore/order/
│ │ │ ├── domain/Order.java, OrderItem.java
│ │ │ ├── saga/OrderSagaManager.java
│ │ │ ├── event/OrderEventPublisher.java
│ │ │ ├── client/PaymentClient.java (Feign)
│ │ │ └── web/OrderController.java
│ │ ├── src/main/resources/
│ │ │ └── application.yml
│ │ └── pom.xml
│ ├── payment-service/ # 支付服务(模拟Stripe)
│ │ ├── src/main/java/com/bookstore/payment/
│ │ │ ├── PaymentController.java
│ │ │ ├── PaymentService.java
│ │ │ └── StripeAdapter.java
│ │ └── pom.xml
│ ├── inventory-service/ # 库存服务(事件消费者)
│ │ ├── src/main/java/com/bookstore/inventory/
│ │ │ ├── listener/OrderConfirmedListener.java
│ │ │ ├── service/InventoryService.java
│ │ │ └── repository/StockRepository.java
│ │ └── pom.xml
│ └── review-service/ # 评价服务(MongoDB + 事件)
│ ├── src/main/java/com/bookstore/review/
│ │ ├── domain/Review.java
│ │ ├── web/ReviewController.java
│ │ └── event/ReviewEventConsumer.java
│ └── pom.xml
├── common/ # 公共库
│ ├── dto/ # 共享DTO
│ ├── event/ # 领域事件基类
│ │ └── OrderConfirmedEvent.java
│ └── security/ # JWT工具
│ └── JwtUtils.java
├── docker-compose/ # 本地开发环境
│ ├── docker-compose.yml # 启动MySQL, Kafka, Mongo, ES
│ └── kafka/ # 配置
├── kubernetes/ # 生产部署清单
│ ├── namespace.yaml
│ ├── gateway-deployment.yaml
│ ├── ... 各服务deployment
│ └── ingress.yaml
├── tests/ # 集成测试
│ ├── contract/ # Pact测试
│ ├── performance/ # JMeter脚本
│ └── e2e/ # Cypress
└── README.md
3.4 各模块详细实现
以下选择 订单服务(Order Service) 和 库存服务(Inventory Service) 进行深入实现解析,展示如何将UML设计转化为代码。
3.4.1 订单服务核心实现(Java + Spring Boot)
领域模型(Order.java)
package com.bookstore.order.domain;
import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@Entity
@Table(name = "orders")
public class Order {
@Id
private UUID id;
private UUID userId;
private LocalDateTime createdAt;
@Enumerated(EnumType.STRING)
private OrderStatus status;
private BigDecimal totalAmount;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "order_id")
private List<OrderItem> items = new ArrayList<>();
public enum OrderStatus { PENDING, CONFIRMED, CANCELLED, PAID_FAILED }
// 工厂方法:创建订单并校验库存(同步调用Catalog服务)
public static Order createOrder(UUID userId, List<OrderItemRequest> itemReqs,
CatalogClient catalogClient) {
Order order = new Order();
order.id = UUID.randomUUID();
order.userId = userId;
order.createdAt = LocalDateTime.now();
order.status = OrderStatus.PENDING;
BigDecimal total = BigDecimal.ZERO;
for (OrderItemRequest req : itemReqs) {
BookInfo book = catalogClient.getBook(req.getBookId());
if (book.getStock() < req.getQuantity()) {
throw new InsufficientStockException(book.getTitle());
}
OrderItem item = new OrderItem(req.getBookId(), req.getQuantity(), book.getPrice());
order.items.add(item);
total = total.add(book.getPrice().multiply(BigDecimal.valueOf(req.getQuantity())));
}
order.totalAmount = total;
return order;
}
public void confirm() {
if (this.status != OrderStatus.PENDING) throw new IllegalStateException();
this.status = OrderStatus.CONFIRMED;
}
public void cancel() { this.status = OrderStatus.CANCELLED; }
}
Saga协调器(OrderSagaManager.java) —— 实现分布式事务(支付 + 库存扣减)
package com.bookstore.order.saga;
import com.bookstore.order.client.PaymentClient;
import com.bookstore.order.domain.Order;
import com.bookstore.order.domain.OrderRepository;
import com.bookstore.order.event.OrderEventPublisher;
import com.bookstore.common.event.OrderConfirmedEvent;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@Component
@RequiredArgsConstructor
public class OrderSagaManager {
private final PaymentClient paymentClient;
private final OrderRepository orderRepo;
private final OrderEventPublisher eventPublisher;
@Transactional
public void processOrder(UUID orderId) {
Order order = orderRepo.findById(orderId).orElseThrow();
// 步骤1:尝试支付
PaymentResult payment = paymentClient.charge(order.getUserId(), order.getTotalAmount());
if (!payment.isSuccess()) {
order.cancel();
orderRepo.save(order);
throw new PaymentFailedException();
}
// 步骤2:支付成功,更新订单状态
order.confirm();
orderRepo.save(order);
// 步骤3:发布领域事件,异步触发库存扣减(最终一致性)
OrderConfirmedEvent event = new OrderConfirmedEvent(order.getId(), order.getItems());
eventPublisher.publish(event);
}
}
事件发布(Kafka生产者)
package com.bookstore.order.event;
import com.bookstore.common.event.OrderConfirmedEvent;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class OrderEventPublisher {
private final KafkaTemplate<String, String> kafkaTemplate;
private final ObjectMapper mapper;
private static final String TOPIC = "order-events";
public void publish(OrderConfirmedEvent event) {
try {
String json = mapper.writeValueAsString(event);
kafkaTemplate.send(TOPIC, event.getOrderId().toString(), json);
} catch (Exception e) {
throw new RuntimeException("Failed to publish event", e);
}
}
}
3.4.2 库存服务实现(事件消费者)
package com.bookstore.inventory.listener;
import com.bookstore.common.event.OrderConfirmedEvent;
import com.bookstore.inventory.service.InventoryService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
@Slf4j
public class OrderConfirmedListener {
private final InventoryService inventoryService;
@KafkaListener(topics = "order-events", groupId = "inventory-group")
public void handleOrderConfirmed(String message) {
// 反序列化事件
OrderConfirmedEvent event = parseEvent(message);
log.info("Reserving stock for order {}", event.getOrderId());
// 扣减库存(幂等处理:使用订单ID作为幂等键)
for (OrderItemEvent item : event.getItems()) {
boolean success = inventoryService.reserveStock(item.getBookId(), item.getQuantity(),
event.getOrderId().toString());
if (!success) {
// 失败则触发补偿事件(本例简化为重试+告警)
log.error("Stock insufficient for book {}", item.getBookId());
// 可发送库存不足事件,触发订单服务取消订单
}
}
}
}
库存服务的幂等实现(Redis + 数据库)
package com.bookstore.inventory.service;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@RequiredArgsConstructor
public class InventoryService {
private final StockRepository stockRepo;
private final StringRedisTemplate redisTemplate;
@Transactional
public boolean reserveStock(UUID bookId, int quantity, String idempotencyKey) {
// 幂等检查
Boolean alreadyDone = redisTemplate.opsForValue().setIfAbsent("inv:" + idempotencyKey, "1");
if (Boolean.FALSE.equals(alreadyDone)) {
return true; // 已经处理过
}
BookStock stock = stockRepo.findByBookId(bookId);
if (stock.getAvailable() < quantity) {
redisTemplate.delete("inv:" + idempotencyKey);
return false;
}
stock.setAvailable(stock.getAvailable() - quantity);
stockRepo.save(stock);
// 设置幂等键过期(7天)
redisTemplate.expire("inv:" + idempotencyKey, Duration.ofDays(7));
return true;
}
}
3.4.3 API网关实现(Spring Cloud Gateway + JWT认证)
# application.yml
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates: Path=/api/users/**
filters:
- name: JwtAuthFilter
- id: order-service
uri: lb://order-service
predicates: Path=/api/orders/**
filters:
- JwtAuthFilter
- id: catalog-service
uri: lb://catalog-service
predicates: Path=/api/books/**
filters:
- name: RequestRateLimiter # 限流
args:
key-resolver: "#{@userKeyResolver}"
redis-rate-limiter.replenishRate: 10
JWT过滤器(全局过滤器)
package com.bookstore.gateway.filter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class JwtAuthFilter implements GlobalFilter {
private final JwtUtils jwtUtils;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String path = exchange.getRequest().getURI().getPath();
// 跳过登录/注册
if (path.equals("/api/users/login") || path.equals("/api/users/register")) {
return chain.filter(exchange);
}
String authHeader = exchange.getRequest().getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
String token = authHeader.substring(7);
try {
Claims claims = jwtUtils.validateToken(token);
// 将用户ID存入请求头,传递给下游服务
ServerWebExchange mutated = exchange.mutate()
.request(r -> r.header("X-User-Id", claims.getSubject()))
.build();
return chain.filter(mutated);
} catch (Exception e) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
}
}
3.4.4 服务间通信(Feign客户端声明式调用)
订单服务调用支付服务(同步REST):
package com.bookstore.order.client;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@FeignClient(name = "payment-service")
public interface PaymentClient {
@PostMapping("/api/payments/charge")
PaymentResult charge(@RequestBody PaymentRequest request);
}
4. 总结
- 架构设计 与 UML建模 是内容与形式的关系。UML提供了一套丰富的图形语言,能够将架构设计的各个视图(逻辑、进程、开发、物理、场景)无歧义地表达出来,从而降低沟通成本,提升设计质量。
- 在实际项目中,应遵循“架构设计驱动,UML视图验证”的原则。先明确架构风格(如微服务)、质量目标、约束,再选择对应的UML图进行细化。同时,UML图不是一次性的,应随代码演进持续更新。
- 通过在线书店实例,展示了如何将UML类图、组件图、部署图、时序图映射到真实的Spring Boot + Kafka + Kubernetes实现中。每个模块的实现都遵循了UML中定义的接口、协作和约束,验证了架构设计的有效性。
最终建议:将UML建模作为架构设计的标准工具箱,但避免过度建模——只对关键架构决策(如服务边界、事件流、部署拓扑)绘制UML图,其余细节可采用代码或自动化文档生成。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐




所有评论(0)