在高校环境中,二手商品交易具有巨大的市场潜力和实际需求。传统的线下交易模式存在信息不对称、交易效率低下、安全性无法保障等问题,而大型电商平台又无法有效区分校内用户,导致交易环境复杂化。校园闲置交易引擎应运而生,它通过严格的校内身份验证机制,构建了一个封闭而安全的交易环境,有效解决了校园二手交易的核心痛点。
该系统采用经典的B/S架构,基于SSM(Spring + Spring MVC + MyBatis)框架构建,实现了高内聚低耦合的设计理念。Spring框架作为整个系统的核心,通过控制反转(IoC)容器统一管理业务对象,利用面向切面编程(AOP)处理事务管理、日志记录等横切关注点。Spring MVC负责Web请求的分发与控制,实现清晰的MVC分离架构。数据持久化层采用MyBatis框架,通过灵活的XML配置实现对象关系映射,同时保留了对SQL的精细控制能力。
前端技术栈采用JSP作为视图层模板,结合JSTL标签库进行数据渲染,使用jQuery处理页面交互逻辑。项目采用Maven进行依赖管理,确保第三方库版本的统一性。数据库选用MySQL 5.7,通过合理的表结构设计和索引优化保障系统性能。
数据库设计深度解析
数据库设计是系统稳定性的基石,本项目通过22张表的精心设计,构建了完整的业务数据模型。以下重点分析几个核心表的设计亮点:
商品信息表(product)设计分析:
CREATE TABLE `product` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`productno` varchar(255) DEFAULT NULL COMMENT '商品编号',
`productname` varchar(255) DEFAULT NULL COMMENT '商品名称',
`filename` varchar(255) DEFAULT NULL COMMENT '文件名',
`price` decimal(10,2) DEFAULT NULL COMMENT '价格',
`tprice` decimal(10,2) DEFAULT NULL COMMENT '特价价格',
`fid` varchar(255) DEFAULT NULL COMMENT '父分类ID',
`sid` varchar(255) DEFAULT NULL COMMENT '子分类ID',
`content` text DEFAULT NULL COMMENT '内容',
`delstatus` varchar(255) DEFAULT NULL COMMENT '删除状态',
`issj` varchar(255) DEFAULT NULL COMMENT '是否上架',
`istj` varchar(255) DEFAULT NULL COMMENT '是否特价',
`saver` varchar(255) DEFAULT NULL COMMENT '上传者',
`productid` varchar(255) DEFAULT NULL COMMENT '商品ID',
`leibie` varchar(255) DEFAULT NULL COMMENT '类别',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=135 DEFAULT CHARSET=utf8 COMMENT='商品信息表'
该表设计体现了良好的业务抽象能力。价格字段采用decimal类型,精确到小数点后两位,避免浮点数运算误差。delstatus、issj、istj等状态字段采用varchar类型,便于扩展多种状态。商品描述使用text类型,支持大段文字内容。分类设计采用父子ID结构,实现多级分类管理。
订单信息表(ordermsg)的复杂业务建模:
CREATE TABLE `ordermsg` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`ddno` varchar(255) DEFAULT NULL COMMENT '订单号',
`memberid` varchar(255) DEFAULT NULL COMMENT '会员ID',
`productid` varchar(255) DEFAULT NULL COMMENT '商品ID',
`num` int(11) DEFAULT NULL COMMENT '数量',
`total` double(255,2) DEFAULT NULL COMMENT '总计',
`fkstatus` varchar(255) DEFAULT NULL COMMENT '付款状态',
`shstatus` varchar(11) DEFAULT NULL COMMENT '审核状态',
`addr` varchar(255) DEFAULT NULL COMMENT '地址',
`savetime` varchar(255) DEFAULT NULL COMMENT '保存时间',
`delstatus` varchar(255) DEFAULT NULL COMMENT '删除状态',
`shfs` varchar(255) DEFAULT NULL COMMENT '配送方式',
`zffs` varchar(255) DEFAULT NULL COMMENT '支付方式',
`saver` varchar(255) DEFAULT NULL COMMENT '上传者',
`isdd` varchar(255) DEFAULT NULL COMMENT '是否订单',
`fid` varchar(255) DEFAULT NULL COMMENT '父订单ID',
`goodsid` varchar(255) DEFAULT NULL COMMENT '商品ID',
`goodstype` varchar(255) DEFAULT NULL COMMENT '商品类型',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=47 DEFAULT CHARSET=utf8 COMMENT='订单信息表'
订单表的设计充分考虑了电商业务的复杂性。通过fid字段实现父子订单关系,支持拆分订单场景。多种状态字段(fkstatus、shstatus、delstatus)完整跟踪订单生命周期。shfs(配送方式)和zffs(支付方式)字段为后续扩展留有余地。时间字段采用varchar存储,便于灵活格式化显示。
核心功能实现深度解析
商品管理与发布系统
商品管理是平台的核心功能,采用分层架构实现。实体类设计简洁明了:
public class Product {
private int id;
private String productno;
private String productname;
private String filename;
private BigDecimal price;
private BigDecimal tprice;
private String fid;
private String sid;
private String content;
private String delstatus;
private String issj;
private String istj;
private String saver;
private String productid;
private String leibie;
// Getter和Setter方法
public int getId() { return id; }
public void setId(int id) { this.id = id; }
// ... 其他getter/setter方法
}
商品发布功能通过Spring MVC控制器处理表单提交:
@Controller
@RequestMapping("/product")
public class ProductController {
@Autowired
private ProductService productService;
@RequestMapping("/publish")
public String publishProduct(Product product,
MultipartFile file,
HttpServletRequest request) {
// 文件上传处理
if (!file.isEmpty()) {
String filename = file.getOriginalFilename();
String path = request.getSession().getServletContext()
.getRealPath("/upload/");
File destFile = new File(path + filename);
file.transferTo(destFile);
product.setFilename(filename);
}
// 设置商品状态
product.setDelstatus("0"); // 未删除
product.setIssj("1"); // 上架状态
product.setSaver(getCurrentUser(request));
productService.saveProduct(product);
return "redirect:/product/list";
}
@RequestMapping("/list")
public String productList(@RequestParam(defaultValue = "1") int page,
HttpServletRequest request) {
PageInfo<Product> pageInfo = productService.getProductList(page, 10);
request.setAttribute("pageInfo", pageInfo);
return "product/list";
}
}

商品发布界面设计直观易用,支持图片上传、价格设置、分类选择等完整功能。通过MyBatis的动态SQL实现灵活的商品查询:
<!-- ProductMapper.xml -->
<select id="selectByCondition" parameterType="map" resultType="Product">
SELECT * FROM product
WHERE delstatus = '0' AND issj = '1'
<if test="productname != null and productname != ''">
AND productname LIKE CONCAT('%', #{productname}, '%')
</if>
<if test="fid != null and fid != ''">
AND fid = #{fid}
</if>
<if test="minPrice != null">
AND price >= #{minPrice}
</if>
<if test="maxPrice != null">
AND price <= #{maxPrice}
</if>
ORDER BY
<choose>
<when test="sort == 'price_asc'">price ASC</when>
<when test="sort == 'price_desc'">price DESC</when>
<when test="sort == 'time_desc'">id DESC</when>
<otherwise>id DESC</otherwise>
</choose>
LIMIT #{start}, #{pageSize}
</select>
购物车与订单管理系统
购物车功能采用Session存储临时数据,订单管理则持久化到数据库。订单生成的业务逻辑复杂,需要处理库存校验、价格计算等多个环节:
@Service
@Transactional
public class OrderService {
@Autowired
private OrderDAO orderDAO;
@Autowired
private ProductDAO productDAO;
public String createOrder(OrderDTO orderDTO, HttpServletRequest request) {
// 1. 生成订单号
String orderNo = generateOrderNo();
// 2. 验证商品库存
for (OrderItemDTO item : orderDTO.getItems()) {
Product product = productDAO.findById(item.getProductId());
if (product.getStock() < item.getQuantity()) {
throw new BusinessException("商品库存不足: " + product.getProductname());
}
}
// 3. 计算总金额
BigDecimal totalAmount = calculateTotal(orderDTO.getItems());
// 4. 创建订单主记录
OrderMsg order = new OrderMsg();
order.setDdno(orderNo);
order.setMemberid(orderDTO.getMemberId());
order.setTotal(totalAmount.doubleValue());
order.setFkstatus("待支付");
order.setShstatus("待审核");
order.setSavetime(new Date().toString());
order.setDelstatus("0");
orderDAO.save(order);
// 5. 创建订单明细并扣减库存
for (OrderItemDTO item : orderDTO.getItems()) {
createOrderItem(order.getId(), item);
productDAO.decreaseStock(item.getProductId(), item.getQuantity());
}
return orderNo;
}
private String generateOrderNo() {
return "DD" + System.currentTimeMillis() +
String.format("%04d", new Random().nextInt(10000));
}
}

订单状态管理采用状态模式设计,支持完整的订单生命周期管理:
public interface OrderState {
void pay(OrderMsg order);
void cancel(OrderMsg order);
void confirm(OrderMsg order);
void deliver(OrderMsg order);
}
@Component
public class PendingPaymentState implements OrderState {
@Override
public void pay(OrderMsg order) {
order.setFkstatus("已支付");
order.setShstatus("待发货");
// 更新数据库
orderDAO.update(order);
}
@Override
public void cancel(OrderMsg order) {
order.setFkstatus("已取消");
// 恢复库存
restoreStock(order);
}
}
用户收藏与消息系统
收藏功能通过favbbs表实现用户与帖子的多对多关系:
CREATE TABLE `favbbs` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`bbsid` int(11) DEFAULT NULL COMMENT '帖子ID',
`mid` int(11) DEFAULT NULL COMMENT '会员ID',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT='帖子收藏表'
收藏业务的Service层实现:
@Service
public class FavoriteService {
@Autowired
private FavbbsDAO favbbsDAO;
public boolean addFavorite(int memberId, int bbsId) {
// 检查是否已收藏
Favbbs existing = favbbsDAO.findByMemberAndBbs(memberId, bbsId);
if (existing != null) {
return false; // 已收藏
}
Favbbs favbbs = new Favbbs();
favbbs.setMid(memberId);
favbbs.setBbsid(bbsId);
favbbsDAO.save(favbbs);
return true;
}
public List<Bbs> getFavoriteBbs(int memberId) {
return favbbsDAO.findBbsByMemberId(memberId);
}
}

后台管理系统
后台管理采用RBAC权限控制模型,支持商品审核、订单管理、用户管理等核心功能:
@Controller
@RequestMapping("/admin")
public class AdminProductController {
@RequestMapping("/product/audit")
public String auditProduct(@RequestParam int productId,
@RequestParam String status,
HttpServletRequest request) {
Product product = productDAO.findById(productId);
product.setIssj(status);
productDAO.update(product);
// 记录审核日志
AuditLog log = new AuditLog();
log.setProductId(productId);
log.setAuditor(getCurrentAdmin(request));
log.setAction("审核商品");
log.setResult(status);
auditLogDAO.save(log);
return "redirect:/admin/product/list";
}
@RequestMapping("/order/statistics")
@ResponseBody
public Map<String, Object> getOrderStatistics(
@RequestParam String startDate,
@RequestParam String endDate) {
Map<String, Object> result = new HashMap<>();
result.put("totalOrders", orderDAO.countByDateRange(startDate, endDate));
result.put("totalAmount", orderDAO.sumAmountByDateRange(startDate, endDate));
result.put("categoryStats", orderDAO.getCategoryStatistics(startDate, endDate));
return result;
}
}

实体模型设计精要
系统采用贫血模型设计,实体类主要承载数据属性,业务逻辑集中在Service层。以About实体为例:
package com.entity;
import java.util.*;
public class About {
private int id;
private String content;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "About [content=" + content + ", id=" + id + "]";
}
}
控制器层通过注解方式实现请求映射和依赖注入:
@Controller
@Resource
public class AboutController extends BaseController {
@Resource
AboutDAO aboutDAO;
CategoryDAO categoryDAO;
@Resource
Saveobject saveobject;
@RequestMapping("/admin/showAbout")
public String showAbout(int id, HttpServletRequest request){
String pagemsg = request.getParameter("pagemsg");
About about = aboutDAO.findById(id);
request.setAttribute("about", about);
request.setAttribute("pagemsg", pagemsg);
return "admin/aboutedit";
}
@RequestMapping("/admin/aboutEdit")
public String aboutEdit(About about, HttpServletRequest request){
aboutDAO.update(about);
return "redirect:showAbout.do?id=1";
}
}
功能展望与技术优化方向
基于当前系统架构,未来可从以下几个方向进行深度优化:
1. 引入Redis缓存集群
@Service
public class ProductServiceWithCache {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String PRODUCT_CACHE_KEY = "product:";
private static final long CACHE_EXPIRE = 3600; // 1小时
public Product getProductWithCache(int id) {
String cacheKey = PRODUCT_CACHE_KEY + id;
Product product = (Product) redisTemplate.opsForValue().get(cacheKey);
if (product == null) {
product = productDAO.findById(id);
if (product != null) {
redisTemplate.opsForValue().set(cacheKey, product,
CACHE_EXPIRE, TimeUnit.SECONDS);
}
}
return product;
}
}
2. 微服务架构改造 将单体应用拆分为用户服务、商品服务、订单服务、支付服务等微服务,通过Spring Cloud实现服务治理。商品服务独立部署:
# application.yml for product-service
server:
port: 8081
spring:
application:
name: product-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
3. Elasticsearch搜索优化 实现更强大的商品搜索功能:
@Service
public class ProductSearchService {
@Autowired
private ElasticsearchRestTemplate elasticsearchTemplate;
public SearchResponse<Product> searchProducts(String keyword,
String category,
Double minPrice,
Double maxPrice) {
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
if (StringUtils.hasText(keyword)) {
queryBuilder.withQuery(QueryBuilders.multiMatchQuery(keyword,
"productname", "content", "leibie"));
}
// 添加过滤条件
BoolQueryBuilder filterQuery = QueryBuilders.boolQuery();
if (StringUtils.hasText(category)) {
filterQuery.must(QueryBuilders.termQuery("leibie", category));
}
if (minPrice != null || maxPrice != null) {
RangeQueryBuilder priceRange = QueryBuilders.rangeQuery("price");
if (minPrice != null) priceRange.gte(minPrice);
if (maxPrice != null) priceRange.lte(maxPrice);
filterQuery.must(priceRange);
}
queryBuilder.withFilter(filterQuery);
return elasticsearchTemplate.search(queryBuilder.build(), Product.class);
}
}
4. 消息队列异步处理 使用RabbitMQ处理高并发场景:
@Component
public class OrderMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendOrderCreate