SSM框架实现二手交易平台:Spring Boot+Vue全栈开发指南

📅 发布时间:2026/9/17 8:13:02
SSM框架实现二手交易平台:Spring Boot+Vue全栈开发指南
1. 项目概述这个基于SSM框架的二手物品交易网站系统是我最近完成的一个课程设计/毕业设计项目。作为一个有10年开发经验的程序员我想分享一下这个项目的完整实现过程和技术细节。这个系统实现了商品发布、订单处理和分类检索等核心功能采用了Spring Boot MyBatis Vue的前后端分离架构数据库使用MySQL。在实际开发过程中我发现很多同学在做类似项目时都会遇到一些共性问题比如SSM框架整合不顺畅、前后端对接困难、数据库设计不合理等。这个项目我特别注重了这些问题点的解决现在把完整的开发思路和实现过程分享出来希望能帮助到正在做课程设计或毕业设计的同学。2. 系统架构设计2.1 技术选型分析选择合适的技术栈是项目成功的关键。经过仔细评估我最终确定了以下技术组合后端技术栈Spring Boot 2.7.x简化配置快速构建项目MyBatis-Plus 3.5.x增强的ORM框架减少SQL编写Shiro 1.10.x负责认证和授权Lombok简化实体类开发HutoolJava工具包前端技术栈Vue 3.x前端框架Element PlusUI组件库AxiosHTTP客户端Vue Router路由管理Pinia状态管理数据库MySQL 8.0关系型数据库Redis 6.x缓存和会话管理选择这些技术主要基于以下考虑Spring Boot的自动配置和起步依赖能大幅减少配置工作MyBatis-Plus提供了强大的CRUD操作和代码生成器Vue 3的组合式API更适合复杂前端逻辑MySQL 8.0在性能和功能上都有显著提升2.2 系统架构设计系统采用典型的三层架构表示层Web层 │ ├── 前端Vue Element Plus │ 业务逻辑层Service层 │ ├── Spring Boot MyBatis-Plus │ 数据访问层DAO层 │ ├── MySQL Redis这种分层架构的优势在于职责分离各层专注自己的功能便于团队协作开发易于维护和扩展可以针对不同层进行独立测试2.3 数据库设计数据库设计遵循第三范式主要表结构如下用户表(user)id: 主键username: 用户名password: 加密密码phone: 手机号email: 邮箱avatar: 头像status: 状态商品表(goods)id: 主键user_id: 卖家IDcategory_id: 分类IDtitle: 商品标题price: 价格original_price: 原价description: 描述images: 图片JSONstatus: 状态订单表(order)id: 主键order_no: 订单编号buyer_id: 买家IDseller_id: 卖家IDgoods_id: 商品IDamount: 金额status: 状态address: 收货地址分类表(category)id: 主键name: 分类名称parent_id: 父分类IDlevel: 层级数据库关系图如下用户 1:n 商品 用户 1:n 订单(作为买家) 用户 1:n 订单(作为卖家) 商品 1:n 订单 分类 1:n 商品设计心得在实际开发中商品图片存储采用了JSON格式存储多个图片URL而不是创建单独的图片表这样简化了查询逻辑。但要注意JSON字段在MySQL中的索引问题。3. 核心功能实现3.1 用户认证模块用户认证采用了Shiro框架实现了以下功能基于用户名密码的登录基于JWT的无状态认证角色和权限控制关键代码示例// Shiro配置类 Configuration public class ShiroConfig { Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) { ShiroFilterFactoryBean factoryBean new ShiroFilterFactoryBean(); factoryBean.setSecurityManager(securityManager); MapString, String filterMap new LinkedHashMap(); filterMap.put(/api/user/login, anon); filterMap.put(/api/user/register, anon); filterMap.put(/**, authc); factoryBean.setFilterChainDefinitionMap(filterMap); return factoryBean; } } // JWT工具类 public class JwtUtil { private static final String SECRET your-secret-key; private static final long EXPIRE 7 * 24 * 60 * 60 * 1000L; // 7天 public static String generateToken(String username) { Date now new Date(); Date expire new Date(now.getTime() EXPIRE); return Jwts.builder() .setHeaderParam(typ, JWT) .setSubject(username) .setIssuedAt(now) .setExpiration(expire) .signWith(SignatureAlgorithm.HS512, SECRET) .compact(); } public static boolean verifyToken(String token) { try { Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token); return true; } catch (Exception e) { return false; } } }注意事项在实际部署时SECRET密钥应该从配置文件中读取而不是硬编码在代码中。同时要考虑定期更换密钥的安全策略。3.2 商品管理模块商品管理实现了以下功能商品发布商品编辑商品上下架商品搜索和筛选核心接口设计RestController RequestMapping(/api/goods) public class GoodsController { Autowired private GoodsService goodsService; PostMapping public Result publishGoods(RequestBody GoodsDTO goodsDTO) { return goodsService.publishGoods(goodsDTO); } PutMapping(/{id}) public Result updateGoods(PathVariable Long id, RequestBody GoodsDTO goodsDTO) { return goodsService.updateGoods(id, goodsDTO); } GetMapping(/{id}) public Result getGoodsDetail(PathVariable Long id) { return goodsService.getGoodsDetail(id); } GetMapping public Result searchGoods(RequestParam(required false) String keyword, RequestParam(required false) Long categoryId, RequestParam(defaultValue 0) Integer page, RequestParam(defaultValue 10) Integer size) { return goodsService.searchGoods(keyword, categoryId, page, size); } }前端商品表单关键代码template el-form :modelgoodsForm :rulesrules refformRef el-form-item label商品标题 proptitle el-input v-modelgoodsForm.title/el-input /el-form-item el-form-item label商品分类 propcategoryId el-cascader v-modelgoodsForm.categoryId :optionscategoryOptions :props{value: id, label: name} /el-cascader /el-form-item el-form-item label商品图片 propimages el-upload action/api/upload list-typepicture-card :file-listfileList :on-successhandleUploadSuccess el-iconPlus //el-icon /el-upload /el-form-item el-form-item label商品描述 propdescription el-input typetextarea v-modelgoodsForm.description/el-input /el-form-item /el-form /template开发技巧商品图片上传时前端可以先压缩图片再上传减少带宽占用。可以使用compressorjs等库实现图片压缩。3.3 订单处理模块订单处理流程包括创建订单支付订单发货确认收货评价状态机设计待支付 → 已支付 → 已发货 → 已完成 ↘ 已取消订单服务核心逻辑Service public class OrderServiceImpl implements OrderService { Autowired private OrderMapper orderMapper; Autowired private GoodsMapper goodsMapper; Transactional public Result createOrder(OrderDTO orderDTO) { // 1. 检查商品状态 Goods goods goodsMapper.selectById(orderDTO.getGoodsId()); if (goods null || goods.getStatus() ! GoodsStatus.ON_SALE) { return Result.fail(商品不存在或已下架); } // 2. 创建订单 Order order new Order(); order.setOrderNo(generateOrderNo()); order.setBuyerId(orderDTO.getBuyerId()); order.setSellerId(goods.getUserId()); order.setGoodsId(goods.getId()); order.setAmount(goods.getPrice()); order.setStatus(OrderStatus.WAIT_PAYMENT); orderMapper.insert(order); // 3. 锁定商品 goods.setStatus(GoodsStatus.LOCKED); goodsMapper.updateById(goods); return Result.success(order); } private String generateOrderNo() { // 时间戳随机数 return System.currentTimeMillis() (int)(Math.random() * 1000); } }注意事项订单创建时要加事务注解Transactional确保订单创建和商品状态更新要么都成功要么都失败。同时要考虑并发情况下的商品超卖问题。4. 系统优化与部署4.1 性能优化缓存策略使用Redis缓存热门商品实现二级缓存MyBatis二级缓存Redis缓存分类数据数据库优化添加合适的索引优化慢查询使用读写分离前端优化图片懒加载路由懒加载组件按需引入缓存配置示例Configuration EnableCaching public class CacheConfig { Bean public RedisCacheManager cacheManager(RedisConnectionFactory factory) { RedisCacheConfiguration config RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofHours(1)) .disableCachingNullValues() .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); return RedisCacheManager.builder(factory) .cacheDefaults(config) .transactionAware() .build(); } }4.2 安全防护XSS防护前端使用vue-sanitize过滤输入后端对输出进行转义CSRF防护使用SameSite Cookie添加CSRF TokenSQL注入防护使用MyBatis预编译避免拼接SQL敏感数据保护密码加盐哈希敏感字段加密存储安全配置示例Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter { Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .headers() .xssProtection() .and() .contentSecurityPolicy(script-src self) .and() .authorizeRequests() .antMatchers(/api/public/**).permitAll() .anyRequest().authenticated(); } }4.3 部署方案推荐使用Docker Compose进行容器化部署version: 3 services: mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: secondhand ports: - 3306:3306 volumes: - mysql_data:/var/lib/mysql redis: image: redis:6 ports: - 6379:6379 volumes: - redis_data:/data backend: build: ./backend ports: - 8080:8080 depends_on: - mysql - redis frontend: build: ./frontend ports: - 80:80 volumes: mysql_data: redis_data:部署步骤安装Docker和Docker Compose编写Dockerfile和docker-compose.yml构建镜像docker-compose build启动服务docker-compose up -d部署建议生产环境应该使用Nginx做反向代理和负载均衡并配置HTTPS证书。同时要设置日志轮转和监控告警。5. 常见问题与解决方案5.1 开发环境问题问题1MySQL连接失败时区错误解决方案在连接字符串中添加时区参数jdbc:mysql://localhost:3306/secondhand?useSSLfalseserverTimezoneAsia/Shanghai问题2前端跨域问题解决方案后端添加CORS配置Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOrigins(*) .allowedMethods(*) .allowedHeaders(*); } }5.2 业务逻辑问题问题1商品超卖解决方案使用乐观锁或分布式锁// 乐观锁实现 Transactional public Result createOrderWithOptimisticLock(OrderDTO orderDTO) { Goods goods goodsMapper.selectById(orderDTO.getGoodsId()); if (goods.getStock() 0) { return Result.fail(库存不足); } int updated goodsMapper.reduceStockWithVersion(goods.getId(), goods.getVersion()); if (updated 0) { throw new OptimisticLockingFailureException(并发修改冲突); } // 创建订单... }问题2订单状态混乱解决方案使用状态模式设计订单状态机public interface OrderState { void pay(Order order); void ship(Order order); void receive(Order order); void cancel(Order order); } public class Order { private OrderState state; public void pay() { state.pay(this); } // 其他方法... }5.3 性能问题问题1商品列表查询慢解决方案添加合适的索引使用分页查询实现缓存问题2图片加载慢解决方案使用CDN加速实现图片懒加载使用WebP格式图片6. 项目扩展方向这个基础版本完成后还可以考虑以下扩展方向即时通讯集成WebSocket实现买卖家实时沟通推荐系统基于用户行为实现商品推荐支付集成对接支付宝、微信支付物流跟踪对接快递100等物流查询接口移动端适配开发微信小程序或React Native App即时通讯实现示例ServerEndpoint(/chat/{userId}) Component public class ChatEndpoint { private static final MapLong, Session sessions new ConcurrentHashMap(); OnOpen public void onOpen(PathParam(userId) Long userId, Session session) { sessions.put(userId, session); } OnMessage public void onMessage(String message, Session session) { // 处理消息并转发 } OnClose public void onClose(PathParam(userId) Long userId) { sessions.remove(userId); } }在实际开发这个项目的过程中我最大的体会是设计阶段多花时间编码阶段就能少走弯路。特别是数据库设计和接口定义一旦确定后再修改成本很高。建议同学们在开始编码前先画好ER图和接口文档和导师或组员充分讨论确认。