ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Spring Boot+Vue全栈电商系统架构设计与实践

Spring Boot+Vue全栈电商系统架构设计与实践 1. 项目概述全栈电商系统的技术选型与架构设计去年接手的一个电商平台重构项目让我深刻体会到技术栈选型的重要性。这个基于Spring BootVue的全栈系统从零开始搭建最终实现了日均10万UV的稳定运行。不同于传统JSP或Thymeleaf方案前后端分离架构让我们的团队能够并行开发效率提升40%以上。Spring Boot 2.7作为后端核心框架提供了开箱即用的企业级特性内嵌Tomcat容器简化部署自动配置的Spring Security鉴权体系与MyBatis-Plus的无缝集成Actuator端点监控前端选用Vue 3组合式API开发配合以下技术栈形成完整解决方案Pinia状态管理替代传统VuexElement Plus组件库快速搭建管理后台Axios封装实现RESTful API调用Vue Router处理前端路由鉴权2. 核心模块设计与实现2.1 分层架构设计采用经典DDD分层架构各层职责明确com.example.ecommerce ├── application # 应用服务层 │ ├── dto # 数据传输对象 │ └── service # 业务逻辑 ├── domain # 领域层 │ ├── model # 领域模型 │ └── repository # 仓储接口 ├── infrastructure # 基础设施层 │ ├── config # 配置类 │ ├── dao # 数据访问 │ └── util # 工具类 └── interfaces # 接口层 ├── api # REST接口 └── web # Web相关2.2 商品模块实现商品核心领域模型采用贫血模型设计Data public class Product { private Long id; private String sku; private String name; private BigDecimal price; private Integer stock; private ProductStatus status; // 领域方法 public void reduceStock(Integer quantity) { if(this.stock quantity) { throw new BusinessException(库存不足); } this.stock - quantity; } }前端采用TreeSelect组件实现商品分类template el-tree-select v-modelform.categoryId :datacategoryTree :propstreeProps check-strictly / /template script setup const treeProps { label: name, value: id, children: children } /script2.3 订单状态机设计使用Spring StateMachine实现订单状态流转Configuration EnableStateMachineFactory public class OrderStateMachineConfig { Bean public StateMachineOrderStatus, OrderEvent stateMachine() { StateMachineBuilder.BuilderOrderStatus, OrderEvent builder StateMachineBuilder.builder(); builder.configureStates() .withStates() .initial(OrderStatus.UNPAID) .states(EnumSet.allOf(OrderStatus.class)); builder.configureTransitions() .withExternal() .source(OrderStatus.UNPAID).target(OrderStatus.PAID) .event(OrderEvent.PAY) .and() .withExternal() .source(OrderStatus.PAID).target(OrderStatus.SHIPPED) .event(OrderEvent.SHIP); return builder.build(); } }3. 关键技术实现细节3.1 分布式锁解决超卖问题采用Redisson实现分布式锁public void deductStock(Long productId, Integer quantity) { RLock lock redissonClient.getLock(product: productId); try { boolean locked lock.tryLock(5, 10, TimeUnit.SECONDS); if(locked) { productService.reduceStock(productId, quantity); } } finally { lock.unlock(); } }3.2 支付结果异步通知使用RabbitMQ实现支付结果回调RabbitListener(queues payment.callback.queue) public void handlePaymentCallback(PaymentMessage message) { Order order orderService.getById(message.getOrderId()); if(order.getStatus() OrderStatus.UNPAID) { orderService.processPayment(order, message); } }前端轮询支付状态const checkPaymentStatus async (orderId) { const timer setInterval(async () { const res await getOrderStatus(orderId) if(res.data.status ! UNPAID) { clearInterval(timer) // 更新UI } }, 3000) }3.3 高性能购物车设计采用前端本地存储后端Redis的混合方案// 前端合并本地和服务器购物车 const mergeCarts async () { const localCart JSON.parse(localStorage.getItem(cart)) || [] const serverCart await getServerCart() const merged [...localCart, ...serverCart].reduce((acc, item) { const exist acc.find(i i.sku item.sku) exist ? exist.quantity item.quantity : acc.push(item) return acc }, []) await syncCart(merged) }4. 性能优化实践4.1 缓存策略设计采用多级缓存架构前端缓存Vue的keep-alive组件缓存路由应用缓存Caffeine本地缓存热点数据分布式缓存Redis集群缓存商品详情Cacheable(value products, key #id) public Product getProductById(Long id) { return productMapper.selectById(id); }4.2 数据库优化读写分离配置spring: datasource: master: url: jdbc:mysql://master:3306/ecommerce slave: url: jdbc:mysql://slave:3306/ecommerce索引优化案例ALTER TABLE order_item ADD INDEX idx_order_product (order_id, product_id);4.3 前端性能优化路由懒加载const ProductDetail () import(./views/ProductDetail.vue)图片懒加载img v-lazyproduct.image altproductWebpack分包策略configureWebpack: { optimization: { splitChunks: { chunks: all } } }5. 安全防护方案5.1 接口安全设计JWT鉴权流程Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers(/api/auth/**).permitAll() .anyRequest().authenticated() .and() .addFilter(new JwtAuthenticationFilter(authenticationManager())) .addFilter(new JwtAuthorizationFilter(authenticationManager())); }参数过滤PostMapping(/products) public Result createProduct(RequestBody Valid ProductCreateDTO dto) { // 自动校验参数 }5.2 支付安全防护签名验证public boolean verifySign(PaymentNotify notify) { String sign DigestUtils.md5Hex(notify.getOrderId() notify.getAmount() secretKey); return sign.equals(notify.getSign()); }金额校验if(!order.getTotalAmount().equals(notify.getAmount())) { throw new SecurityException(金额不一致); }6. 部署与监控6.1 Docker Compose部署version: 3 services: backend: image: ecommerce-backend:latest ports: - 8080:8080 depends_on: - redis - mysql frontend: image: ecommerce-frontend:latest ports: - 80:806.2 Prometheus监控配置management: endpoints: web: exposure: include: health,info,metrics,prometheus metrics: export: prometheus: enabled: true6.3 ELK日志收集Logback配置示例appender nameLOGSTASH classnet.logstash.logback.appender.LogstashTcpSocketAppender destinationlogstash:5044/destination encoder classnet.logstash.logback.encoder.LogstashEncoder/ /appender7. 典型问题解决方案7.1 跨域问题处理Spring Boot配置Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/api/**) .allowedOrigins(https://yourdomain.com) .allowedMethods(*); } }; }Vue代理配置devServer: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } }7.2 文件上传优化分片上传实现const uploadChunk async (file, chunkSize, chunks) { for(let i0; ichunks; i){ const chunk file.slice(i*chunkSize, (i1)*chunkSize) await axios.post(/upload, chunk, { headers: { Content-Range: bytes ${i*chunkSize}-${(i1)*chunkSize-1}/${file.size} } }) } }7.3 第三方登录集成Spring Social配置Bean public ConnectionFactoryLocator connectionFactoryLocator() { ConnectionFactoryRegistry registry new ConnectionFactoryRegistry(); registry.addConnectionFactory(new OAuth2ConnectionFactory( wechat, new ServiceProvider( new WechatOAuth2Api(), new WechatOAuth2Service(clientId, clientSecret) ), new WechatAdapter() )); return registry; }8. 项目演进方向微服务化改造将单体应用拆分为商品、订单、用户等独立服务引入Kubernetes实现自动化部署和扩缩容增加推荐系统提升转化率实现多租户SaaS化支持接入支付风控系统在项目开发过程中最大的经验教训是前期要建立完善的API文档规范。我们使用Swagger UI自动生成文档并通过Git Hook强制要求更新文档才能提交代码。另一个关键点是建立全链路日志追踪我们通过MDC实现请求ID透传极大提升了排查问题的效率。
返回列表