1. 项目背景与技术选型
明星周边在线购物商城是一个典型的B2C电商平台,面向粉丝群体提供明星相关商品的展示、购买和售后服务。选择Java+SSM框架组合作为技术栈,主要基于以下几个考量:
-
成熟稳定的技术生态:SSM(Spring+SpringMVC+MyBatis)作为JavaEE领域的经典组合框架,经过多年企业级项目验证,特别适合电商这类业务逻辑复杂的系统开发。Spring的IoC容器和AOP特性能够优雅地解耦业务组件,MyBatis的灵活SQL映射则能应对电商多变的数据查询需求。
-
性能与扩展性平衡:相较于纯Servlet开发,SpringMVC提供了更结构化的Web层解决方案;相比重量级的EJB,SSM又保持了轻量级特性。这种平衡使得系统在应对明星周边商品抢购等高并发场景时,既不会过度消耗资源,又能通过集群部署实现横向扩展。
-
开发效率与维护成本:SSM框架丰富的注解支持和约定优于配置的特性,可以显著减少样板代码。例如商品模块的CRUD操作,通过MyBatis Generator自动生成基础代码后,开发人员只需专注业务逻辑实现。
实际开发中发现:当商品SKU超过5000个时,需要特别注意MyBatis的一级缓存策略,建议在配置文件中显式设置localCacheScope=STATEMENT,避免长时间运行的查询操作占用过多内存。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计
2.1 整体架构分层
采用经典的三层架构设计,各层职责明确:
-
表现层:
- 基于SpringMVC实现RESTful API
- 使用Jackson处理JSON序列化
- 集成Thymeleaf模板引擎用于后台管理页面渲染
- 示例代码:商品详情接口设计
java复制@RestController @RequestMapping("/api/product") public class ProductController { @Autowired private ProductService productService; @GetMapping("/{id}") public Result<ProductDetailVO> getDetail(@PathVariable Long id) { return Result.success(productService.getDetail(id)); } } -
业务逻辑层:
- 领域模型驱动设计(DDD-lite)
- 事务管理采用Spring声明式事务
- 关键业务如订单创建使用策略模式
-
数据访问层:
- MyBatis动态SQL构建复杂查询
- 二级缓存使用Ehcache实现
- 分页插件PageHelper处理商品列表
2.2 数据库设计要点
明星周边商城的数据库设计有几个特殊考量点:
-
商品属性扩展性:
sql复制CREATE TABLE `product` ( `id` bigint NOT NULL AUTO_INCREMENT, `star_id` bigint NOT NULL COMMENT '关联明星ID', `type` tinyint NOT NULL COMMENT '商品类型:1-应援棒 2-写真集...', `spec_json` json DEFAULT NULL COMMENT '动态规格属性', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -
粉丝特权的实现:
- 会员等级表与订单表的关联设计
- 专属签名版商品的库存隔离机制
-
热点数据分离:
- 将商品浏览数、收藏数等高频更新字段拆分到单独统计表
- 使用Redis缓存明星主页的周边商品列表
3. 核心功能实现
3.1 商品模块关键技术
-
多维度商品检索:
- 基于MyBatis的动态SQL构建器
xml复制<select id="search" resultMap="BaseResultMap"> SELECT * FROM product <where> <if test="starId != null">AND star_id = #{starId}</if> <if test="type != null">AND type = #{type}</if> <if test="keywords != null"> AND name LIKE CONCAT('%',#{keywords},'%') </if> </where> ORDER BY <choose> <when test="sortType == 1">sales DESC</when> <when test="sortType == 2">price ASC</when> <otherwise>create_time DESC</otherwise> </choose> </select> -
限量商品抢购:
- Redis分布式锁防止超卖
- 乐观锁更新库存
java复制public boolean reduceStock(Long productId, int num) { int affected = productMapper.updateStock( productId, num, new Date()); return affected > 0; }对应Mapper方法:
java复制@Update("UPDATE product SET stock = stock - #{num}, " + "version = version + 1 " + "WHERE id = #{id} AND stock >= #{num} " + "AND version = #{version}") int updateStock(@Param("id") Long id, @Param("num") Integer num, @Param("version") Date version);
3.2 订单系统设计
-
状态机设计:
java复制public enum OrderStatus { UNPAID(1, "待支付") { @Override public boolean canChangeTo(OrderStatus newStatus) { return newStatus == PAID || newStatus == CANCELLED; } }, PAID(2, "已支付") { // 其他状态转换逻辑 }; } -
分布式事务处理:
- 使用Seata处理跨服务的订单创建
- 本地消息表保证最终一致性
4. 性能优化实践
4.1 缓存策略优化
-
多级缓存架构:
- JVM缓存(Caffeine):存储用户个性化推荐数据
- Redis集群:缓存热点商品信息
- CDN静态资源缓存:商品图片等静态资源
-
缓存击穿解决方案:
java复制public Product getProduct(Long id) { String cacheKey = "product:" + id; Product product = redisTemplate.opsForValue().get(cacheKey); if (product == null) { synchronized (this) { product = redisTemplate.opsForValue().get(cacheKey); if (product == null) { product = productMapper.selectById(id); if (product != null) { redisTemplate.opsForValue().set( cacheKey, product, 30, TimeUnit.MINUTES); } else { // 防止缓存穿透 redisTemplate.opsForValue().set( cacheKey, new NullProduct(), 5, TimeUnit.MINUTES); } } } } return product instanceof NullProduct ? null : product; }
4.2 高并发处理
-
秒杀系统设计:
- 采用令牌桶限流
- 商品详情页静态化
- 下单接口异步化处理
-
线程池优化配置:
java复制@Bean public ThreadPoolTaskExecutor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(20); executor.setMaxPoolSize(100); executor.setQueueCapacity(200); executor.setThreadNamePrefix("mall-async-"); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); return executor; }
5. 安全防护措施
5.1 常见攻击防护
-
XSS防护:
- 前端使用DOMPurify过滤富文本
- 后端统一响应处理:
java复制@ControllerAdvice public class SecurityAdvice implements ResponseBodyAdvice<Object> { @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { // 对String类型返回值进行HTML转义 if (body instanceof String) { return HtmlUtils.htmlEscape((String) body); } return body; } } -
CSRF防护:
- Spring Security默认启用CSRF防护
- 针对API请求添加Token验证
5.2 数据安全
-
敏感信息加密:
- 用户手机号使用AES加密存储
- 数据库连接信息通过Jasypt加密
-
审计日志:
java复制@Aspect @Component public class AuditLogAspect { @AfterReturning(pointcut = "@annotation(auditLog)", returning = "result") public void afterReturning(JoinPoint joinPoint, AuditLog auditLog, Object result) { // 记录操作日志 } }
6. 部署与监控
6.1 容器化部署
-
Docker Compose编排:
yaml复制version: '3' services: app: image: mall-service:1.0 ports: - "8080:8080" depends_on: - redis - mysql redis: image: redis:6 ports: - "6379:6379" -
健康检查配置:
java复制@RestController @RequestMapping("/actuator") public class HealthCheckController { @GetMapping("/health") public ResponseEntity<String> health() { // 自定义健康检查逻辑 return ResponseEntity.ok("UP"); } }
6.2 监控体系
-
Prometheus监控指标:
java复制@Bean MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() { return registry -> registry.config().commonTags( "application", "star-mall"); } -
ELK日志收集:
- Logstash配置示例:
conf复制input { tcp { port => 5044 codec => json_lines } }
在项目实际运行过程中,我们发现当明星发布新专辑时,周边商品访问量会在短时间内激增300%以上。通过引入Sentinel实现动态限流,配合Nginx的负载均衡策略,系统成功应对了多次流量高峰。具体做法是在商品查询接口上添加@SentinelResource注解,并配置集群流控规则:
java复制@SentinelResource(value = "productQuery",
blockHandler = "handleBlockException")
@GetMapping("/products")
public Result<List<Product>> queryProducts(ProductQuery query) {
// 业务逻辑
}
对于支付接口这类关键业务,我们额外实现了熔断降级策略,当第三方支付平台响应时间超过2秒时,自动切换备用支付通道。这种设计在"双十一"等大促期间有效保障了系统的可用性。
