基于SSM框架的校园二手手机交易平台 - 源码深度解析
在高校校园环境中,二手手机交易一直是一个活跃但缺乏规范化管理的市场。学生群体因毕业离校、设备升级换代等原因产生大量闲置手机,同时新生入学和预算有限的学生群体也存在强烈的购买需求。然而,传统的线下交易模式普遍存在信息不对称、交易风险高、缺乏信任保障机制等痛点问题。
针对这一特定场景需求,我们设计并实现了一个基于SSM(Spring + SpringMVC + MyBatis)框架的校园二手手机交易平台。该平台通过技术手段解决了传统交易的痛点,为高校学生提供了安全、便捷、可靠的线上交易环境。
系统架构设计与技术栈选型
本平台采用经典的SSM三层架构模式,结合Maven进行项目构建和依赖管理。前端使用JSP动态页面技术,配合JSTL标签库实现数据渲染,同时采用HTML5、CSS3和JavaScript构建响应式用户界面。
核心技术栈配置示例:
<!-- pom.xml 依赖配置 -->
<dependencies>
<!-- Spring核心依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.8</version>
</dependency>
<!-- Spring事务管理 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.3.8</version>
</dependency>
<!-- MyBatis集成 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.25</version>
</dependency>
<!-- JSTL标签库 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
架构层次解析:
- Spring框架:作为核心IoC容器,负责管理业务逻辑层的对象依赖关系和事务控制,通过AOP实现日志记录和权限验证等横切关注点
- SpringMVC框架:作为Web表现层框架,通过DispatcherServlet统一调度请求,实现参数绑定、数据验证和视图解析
- MyBatis框架:作为持久层框架,通过灵活的XML配置和注解方式将Java对象与数据库记录进行ORM映射
数据库设计亮点与优化策略
商品表(goods)设计优化
CREATE TABLE `goods` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '商品主键',
`catelog_id` int(11) DEFAULT NULL COMMENT '商品分类,外键',
`user_id` int(11) DEFAULT NULL COMMENT '用户外键',
`name` varchar(255) DEFAULT NULL COMMENT '商品名称',
`price` float(11,2) DEFAULT NULL COMMENT '出售价格',
`real_price` float(11,2) DEFAULT NULL COMMENT '真实价格',
`start_time` varchar(255) DEFAULT NULL COMMENT '发布时间',
`polish_time` varchar(255) DEFAULT NULL COMMENT '擦亮时间,按该时间进行查询,精确到时分秒',
`end_time` varchar(255) DEFAULT NULL COMMENT '下架时间',
`describle` text DEFAULT NULL COMMENT '详细信息',
`status` int(11) DEFAULT 1 COMMENT '状态 上架1 下架0',
PRIMARY KEY (`id`),
KEY `catelog_id` (`catelog_id`) USING BTREE,
KEY `user_id` (`user_id`) USING BTREE,
KEY `polish_time` (`polish_time`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=134 DEFAULT CHARSET=utf8
设计亮点深度分析:
时间字段精细化设计
polish_time字段记录商品擦亮时间,支持按时间排序查询,提升商品展示效果- 采用字符串存储时间,避免时区转换问题,简化前端展示逻辑
价格精度与业务逻辑
- 使用
float(11,2)确保价格计算的精确性,避免浮点数精度问题 real_price字段记录商品原价,支持价格对比和折扣计算
- 使用
数据状态管理策略
- 通过
status字段实现商品上架/下架的软删除机制,保留完整的历史交易数据 - 支持商品状态的灵活变更,便于数据统计和分析
- 通过
索引优化与查询性能
- 为
catelog_id和user_id建立BTREE索引,优化分类查询和用户商品列表查询性能 - 新增
polish_time索引,提升按时间排序的查询效率
- 为
图片表与评论表的关联设计
CREATE TABLE `image` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '图片主键',
`goods_id` int(11) NOT NULL COMMENT '商品外键',
`img_url` text NOT NULL COMMENT '图片链接',
`img_order` int(11) DEFAULT 0 COMMENT '图片排序',
PRIMARY KEY (`id`),
KEY `goods_id` (`goods_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=134 DEFAULT CHARSET=utf8
CREATE TABLE `comments` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '评论主键',
`user_id` int(11) DEFAULT NULL COMMENT '用户,外键',
`goods_id` int(11) DEFAULT NULL COMMENT '商品,外键',
`content` varchar(255) DEFAULT NULL COMMENT '评论内容',
`create_at` varchar(250) DEFAULT NULL COMMENT '评论时间',
`parent_id` int(11) DEFAULT 0 COMMENT '父评论ID,支持回复功能',
PRIMARY KEY (`id`),
KEY `goods_id` (`goods_id`) USING BTREE,
KEY `user_id` (`user_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=127 DEFAULT CHARSET=utf8
关联设计技术优势:
- 灵活的一对多关系映射:一个商品对应多张图片和多条评论,完美契合实际业务场景需求
- 外键索引优化策略:为
goods_id建立索引,大幅提升联表查询效率,支持复杂的数据统计 - 字段类型合理规划:评论内容使用
varchar(255)限制长度,图片链接使用text类型支持长URL存储 - 扩展性考虑:图片表增加排序字段,评论表支持回复功能,为后续功能扩展预留空间

核心功能实现深度解析
1. 管理员权限控制与会话安全机制
@Controller
@RequestMapping(value = "/admin")
public class AdminController {
@Resource
private AdminService adminService;
/**
* 管理员登录验证
*/
@RequestMapping(value = "/index", method = RequestMethod.POST)
public String index(HttpServletRequest request, Admin admins,
HttpSession session) {
// 参数验证
if (StringUtils.isEmpty(admins.getPhone()) ||
StringUtils.isEmpty(admins.getPassword())) {
return "/admin/login";
}
Admin myadmin = adminService.findAdmin(admins.getPhone(),
admins.getPassword());
if (myadmin != null) {
// 设置会话超时时间(30分钟)
session.setMaxInactiveInterval(1800);
session.setAttribute("admin", myadmin);
return "redirect:/admin/main";
}
return "/admin/login";
}
/**
* 会话状态验证与刷新
*/
@RequestMapping(value = "/indexs")
public String indexs(HttpServletRequest request) {
HttpSession session = request.getSession(false);
if (session != null) {
Admin admin = (Admin) session.getAttribute("admin");
if (admin != null) {
// 重新加载管理员信息,防止数据过期
Admin myadmin = adminService.findAdminById(admin.getId());
session.setAttribute("admin", myadmin);
return "/admin/index";
}
}
return "redirect:/admin/login";
}
/**
* 统一权限验证拦截器
*/
@ModelAttribute
public void checkAdmin(HttpServletRequest request,
HttpServletResponse response) throws Exception {
HttpSession session = request.getSession(false);
if (session == null || session.getAttribute("admin") == null) {
response.sendRedirect(request.getContextPath() + "/admin/login");
}
}
}
安全机制技术要点:
- 会话超时控制:设置合理的会话超时时间,平衡安全性与用户体验
- 数据重新加载:每次验证时从数据库重新加载管理员信息,有效防止session篡改攻击
- 统一权限验证:通过@ModelAttribute注解实现统一的权限验证拦截
- 参数安全验证:对输入参数进行空值验证,防止SQL注入和空指针异常

2. 商品发布与图片管理的事务一致性
@Service
@Transactional
public class GoodsServiceImpl implements GoodsService {
@Autowired
private GoodsMapper goodsMapper;
@Autowired
private ImageMapper imageMapper;
/**
* 商品发布事务管理
*/
@Transactional(rollbackFor = Exception.class)
public int addGoods(Goods goods, List<String> imageUrls) {
// 参数验证
if (goods == null || StringUtils.isEmpty(goods.getName())) {
throw new IllegalArgumentException("商品信息不完整");
}
// 设置商品默认属性
goods.setStart_time(DateUtil.getCurrentTime());
goods.setPolish_time(DateUtil.getCurrentTime());
goods.setStatus(1); // 默认上架状态
// 插入商品基本信息
int result = goodsMapper.insert(goods);
if (result <= 0) {
throw new RuntimeException("商品信息插入失败");
}
// 批量插入商品图片(事务一致性保障)
if (imageUrls != null && !imageUrls.isEmpty()) {
for (int i = 0; i < imageUrls.size(); i++) {
Image image = new Image();
image.setGoodsId(goods.getId());
image.setImgUrl(imageUrls.get(i));
image.setImgOrder(i); // 设置图片显示顺序
int imageResult = imageMapper.insert(image);
if (imageResult <= 0) {
throw new RuntimeException("商品图片插入失败");
}
}
}
return result;
}
/**
* 商品下架逻辑
*/
@Transactional(rollbackFor = Exception.class)
public int offShelfGoods(Integer goodsId) {
Goods goods = goodsMapper.selectByPrimaryKey(goodsId);
if (goods == null) {
throw new RuntimeException("商品不存在");
}
goods.setStatus(0); // 设置为下架状态
goods.setEnd_time(DateUtil.getCurrentTime());
return goodsMapper.updateByPrimaryKey(goods);
}
}
事务管理关键技术:
- 声明式事务管理:使用@Transactional注解实现声明式事务控制
- 异常回滚机制:配置rollbackFor = Exception.class确保任何异常都会触发事务回滚
- 业务逻辑验证:在事务开始前进行参数验证,避免无效的事务操作
- 数据一致性保障:确保商品基本信息与图片信息的插入操作具有原子性
性能优化与扩展性考虑
缓存策略设计
@Service
public class GoodsCacheService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String GOODS_KEY_PREFIX = "goods:";
private static final long EXPIRATION_TIME = 3600; // 1小时缓存
/**
* 商品信息缓存
*/
public Goods getGoodsWithCache(Integer goodsId) {
String key = GOODS_KEY_PREFIX + goodsId;
Goods goods = (Goods) redisTemplate.opsForValue().get(key);
if (goods == null) {
// 缓存未命中,从数据库查询
goods = goodsMapper.selectByPrimaryKey(goodsId);
if (goods != null) {
redisTemplate.opsForValue().set(key, goods, EXPIRATION_TIME,
TimeUnit.SECONDS);
}
}
return goods;
}
}
数据库连接池优化
# application.properties 数据库配置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/campus_market?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456
# 连接池配置
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.idle-timeout=300000
spring.datasource.hikari.connection-timeout=20000
spring.datasource.hikari.max-lifetime=1200000
总结与展望
本校园二手手机交易平台基于SSM框架实现了完整的电商交易功能,通过精心的数据库设计、严格的安全控制和优化的事务管理,为高校学生提供了安全可靠的二手交易环境。平台具备良好的扩展性,为后续添加移动端支持、推荐算法、在线支付等功能奠定了坚实的技术基础。
技术亮点总结:
- 采用成熟的SSM框架组合,保证系统稳定性和可维护性
- 数据库设计充分考虑业务场景,索引优化提升查询性能
- 完善的事务管理和权限控制机制,确保数据安全
- 模块化设计便于功能扩展和系统维护
该项目的成功实施不仅解决了校园二手手机交易的实际问题,也为类似校园电商平台的开发提供了可借鉴的技术方案。