在农产品流通领域,传统模式长期面临着信息不对称、供应链冗长、交易成本高等痛点。为应对这些挑战,我们设计并实现了一个基于SSM(Spring + SpringMVC + MyBatis)架构的B2B农产品数字化交易平台——“农贸通”。该系统通过整合供应商与采购商资源,构建了从产品展示、在线交易到支付结算的全流程数字化解决方案。
系统采用经典的三层架构设计,实现了高内聚、低耦合的软件工程原则。Spring框架作为核心容器,通过控制反转(IoC)和依赖注入(DI)管理业务对象生命周期,同时利用面向切面编程(AOP)统一处理事务管理、安全控制和日志记录等横切关注点。SpringMVC作为Web层框架,采用前端控制器模式分发用户请求,通过配置的拦截器实现权限验证、参数预处理等通用逻辑。MyBatis作为持久层框架,通过XML映射文件灵活管理SQL语句与对象关系映射,其动态SQL特性特别适合农产品多条件检索场景。
数据库设计围绕22个核心业务表展开,体现了完整的业务逻辑建模。其中,商品信息表(product)的设计尤为关键:
CREATE TABLE product (
product_id INT PRIMARY KEY AUTO_INCREMENT,
product_name VARCHAR(100) NOT NULL,
category_id INT NOT NULL,
supplier_id INT NOT NULL,
original_price DECIMAL(10,2),
current_price DECIMAL(10,2) NOT NULL,
stock_quantity INT DEFAULT 0,
min_order_quantity INT DEFAULT 1,
product_status ENUM('上架', '下架', '缺货') DEFAULT '上架',
production_date DATE,
shelf_life_days INT,
origin_address VARCHAR(200),
product_description TEXT,
main_image_url VARCHAR(500),
detail_images JSON,
view_count INT DEFAULT 0,
monthly_sales INT DEFAULT 0,
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (category_id) REFERENCES product_category(category_id),
FOREIGN KEY (supplier_id) REFERENCES supplier(supplier_id),
INDEX idx_category_status (category_id, product_status),
INDEX idx_price_range (current_price),
INDEX idx_supplier (supplier_id)
);
该表设计涵盖了农产品特有的业务属性,如最低起订量(min_order_quantity)、生产日期(production_date)、保质期(shelf_life_days)和产地信息(origin_address)。JSON类型的详情图片字段(detail_images)支持存储多张商品展示图,而复合索引(idx_category_status)优化了按分类和状态筛选商品的查询性能。
订单表(order)的设计则体现了复杂的交易逻辑:
CREATE TABLE order (
order_id VARCHAR(32) PRIMARY KEY,
user_id INT NOT NULL,
total_amount DECIMAL(10,2) NOT NULL,
actual_payment DECIMAL(10,2) NOT NULL,
discount_amount DECIMAL(10,2) DEFAULT 0,
shipping_address_id INT NOT NULL,
order_status ENUM('待支付', '已支付', '配送中', '已完成', '已取消') DEFAULT '待支付',
payment_method ENUM('支付宝', '微信支付', '银行转账'),
payment_time DATETIME,
delivery_time DATETIME,
completion_time DATETIME,
buyer_notes VARCHAR(500),
after_sales_status ENUM('无', '申请中', '处理中', '已完成') DEFAULT '无',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES user(user_id),
FOREIGN KEY (shipping_address_id) REFERENCES shipping_address(address_id),
INDEX idx_user_status (user_id, order_status),
INDEX idx_create_time (create_time)
);
采用字符串类型的订单号(order_id)便于生成包含时间戳和随机数的业务标识,枚举类型字段确保了状态值的规范统一,而多时间戳字段的设计支持完整的订单生命周期追踪。
在核心功能实现方面,商品检索功能通过MyBatis的动态SQL实现了灵活的多条件查询:
<select id="selectByCondition" parameterType="map" resultMap="ProductResultMap">
SELECT * FROM product
<where>
<if test="categoryId != null">AND category_id = #{categoryId}</if>
<if test="minPrice != null">AND current_price >= #{minPrice}</if>
<if test="maxPrice != null">AND current_price <= #{maxPrice}</if>
<if test="origin != null and origin != ''">AND origin_address LIKE CONCAT('%', #{origin}, '%')</if>
<if test="keyword != null and keyword != ''">
AND (product_name LIKE CONCAT('%', #{keyword}, '%')
OR product_description LIKE CONCAT('%', #{keyword}, '%'))
</if>
AND product_status = '上架'
</where>
<choose>
<when test="sortType == 'price_asc'">ORDER BY current_price ASC</when>
<when test="sortType == 'price_desc'">ORDER BY current_price DESC</when>
<when test="sortType == 'sales'">ORDER BY monthly_sales DESC</when>
<otherwise>ORDER BY create_time DESC</otherwise>
</choose>
</select>
购物车管理模块通过Spring的声明式事务管理确保数据一致性:
@Service
@Transactional
public class CartServiceImpl implements CartService {
@Autowired
private CartItemMapper cartItemMapper;
@Autowired
private ProductMapper productMapper;
@Override
public void addToCart(CartItem cartItem) {
// 检查商品库存
Product product = productMapper.selectById(cartItem.getProductId());
if (product.getStockQuantity() < cartItem.getQuantity()) {
throw new InsufficientStockException("商品库存不足");
}
// 检查购物车中是否已存在该商品
CartItem existingItem = cartItemMapper.selectByUserAndProduct(
cartItem.getUserId(), cartItem.getProductId());
if (existingItem != null) {
// 更新数量
existingItem.setQuantity(existingItem.getQuantity() + cartItem.getQuantity());
cartItemMapper.updateQuantity(existingItem);
} else {
// 新增记录
cartItemMapper.insert(cartItem);
}
}
}

订单处理流程采用状态模式设计,通过SpringMVC控制器接收前端请求:
@RestController
@RequestMapping("/api/order")
public class OrderController {
@Autowired
private OrderService orderService;
@PostMapping("/create")
public ResponseEntity<OrderResult> createOrder(@RequestBody OrderRequest request) {
// 参数验证
if (request.getItems() == null || request.getItems().isEmpty()) {
return ResponseEntity.badRequest().body(OrderResult.error("订单商品不能为空"));
}
try {
Order order = orderService.createOrder(request);
return ResponseEntity.ok(OrderResult.success(order));
} catch (BusinessException e) {
return ResponseEntity.badRequest().body(OrderResult.error(e.getMessage()));
}
}
@PostMapping("/{orderId}/pay")
public ResponseEntity<PaymentResult> payOrder(@PathVariable String orderId,
@RequestBody PaymentRequest request) {
PaymentResult result = orderService.processPayment(orderId, request);
return ResponseEntity.ok(result);
}
}

库存管理模块实现了实时库存监控和预警机制:
@Service
public class InventoryServiceImpl implements InventoryService {
@Autowired
private ProductMapper productMapper;
@Override
@Transactional
public void updateStock(String operationType, Integer productId, Integer quantity) {
Product product = productMapper.selectById(productId);
switch (operationType) {
case "入库":
product.setStockQuantity(product.getStockQuantity() + quantity);
break;
case "出库":
if (product.getStockQuantity() < quantity) {
throw new InsufficientStockException("库存不足,当前库存:" + product.getStockQuantity());
}
product.setStockQuantity(product.getStockQuantity() - quantity);
break;
default:
throw new IllegalArgumentException("不支持的操作类型");
}
// 自动更新商品状态
if (product.getStockQuantity() <= 0) {
product.setProductStatus("缺货");
} else if ("缺货".equals(product.getProductStatus())) {
product.setProductStatus("上架");
}
productMapper.update(product);
// 记录库存变更日志
inventoryLogService.logInventoryChange(productId, operationType, quantity);
}
}
权限控制系统通过自定义拦截器实现细粒度访问控制:
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Autowired
private UserService userService;
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
String token = request.getHeader("Authorization");
if (token == null || !token.startsWith("Bearer ")) {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
return false;
}
String jwtToken = token.substring(7);
User user = userService.validateToken(jwtToken);
if (user == null) {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
return false;
}
// 检查角色权限
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
RequiredPermission permission = handlerMethod.getMethodAnnotation(RequiredPermission.class);
if (permission != null && !user.hasPermission(permission.value())) {
response.setStatus(HttpStatus.FORBIDDEN.value());
return false;
}
}
request.setAttribute("currentUser", user);
return true;
}
}

系统还实现了基于Redis的缓存机制提升性能:
@Service
public class CategoryServiceImpl implements CategoryService {
@Autowired
private CategoryMapper categoryMapper;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private static final String CATEGORY_CACHE_KEY = "product:categories";
@Override
@Cacheable(value = CATEGORY_CACHE_KEY, key = "'all'")
public List<Category> getAllCategories() {
return categoryMapper.selectAll();
}
@Override
@CacheEvict(value = CATEGORY_CACHE_KEY, key = "'all'")
public void updateCategory(Category category) {
categoryMapper.update(category);
}
}

在数据分析方面,系统通过MyBatis的聚合查询实现销售统计:
<select id="selectSalesStatistics" parameterType="map" resultType="map">
SELECT
DATE(create_time) as date,
COUNT(*) as order_count,
SUM(total_amount) as total_sales,
AVG(total_amount) as avg_order_value
FROM order
WHERE create_time BETWEEN #{startDate} AND #{endDate}
AND order_status = '已完成'
GROUP BY DATE(create_time)
ORDER BY date DESC
</select>

针对未来发展方向,系统可在以下几个维度进行优化扩展:
首先,引入智能推荐算法,基于用户行为数据和协同过滤技术实现个性化商品推荐。通过集成Apache Mahout或TensorFlow等机器学习框架,分析用户的浏览历史、购买记录和相似用户偏好,构建推荐模型提升成交转化率。
其次,构建供应链可视化追踪系统,利用区块链技术记录农产品从生产到配送的全流程信息。通过Hyperledger Fabric框架建立分布式账本,实现种植、加工、检验、物流等环节的数据上链,为消费者提供透明的产品溯源服务。
第三,开发移动端原生应用,采用React Native或Flutter跨平台框架构建iOS和Android应用。通过设备原生API调用摄像头扫描二维码查看商品信息,利用GPS定位自动推荐附近供应商,集成推送服务及时通知订单状态变更。
第四,实现大数据分析平台,使用Elasticsearch进行日志分析和用户行为追踪,通过Kibana可视化展示关键业务指标。建立用户画像系统,基于聚类算法细分用户群体,为精准营销和库存预测提供数据支撑。
第五,集成智能客服系统,引入自然语言处理技术实现自动问答和售后支持。通过训练专用的领域语言模型,理解农产品相关的专业术语和常见问题,降低人工客服成本的同时提升用户体验。
系统通过严谨的架构设计和深入的技术实现,为农产品交易提供了完整的数字化解决方案。SSM框架的稳定性和扩展性确保了系统能够支撑高并发访问和复杂的业务逻辑,而模块化的设计为后续功能迭代奠定了坚实基础。随着农业产业数字化的深入推进,该平台有望成为连接农产品供应链各环节的重要基础设施。