1. 项目背景与需求分析
在线药店管理系统作为医药行业数字化转型的典型应用,正在改变传统药品零售模式。这个基于JSP+Java的毕业设计项目,本质上是一个B2C医药电商平台,需要解决药品信息展示、在线交易、处方审核和库存管理等核心业务场景。
从技术选型来看,JSP+Java的组合在高校毕业设计中仍具有广泛适用性。JSP作为视图层技术,其页面动态生成特性非常适合商品展示类系统;Java的强类型和面向对象特性则能很好地处理药品这类需要严格数据校验的业务对象。系统采用SSM(Spring+SpringMVC+MyBatis)框架组合,这种架构在中小型电商系统中表现出良好的分层解耦能力。
提示:医药电商系统需要特别注意药品分类管理,建议参考CFDA的药品分类标准设计数据库字段
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计
2.1 技术栈选型
本系统采用典型的三层架构:
- 表现层:JSP+JSTL+EL表达式
- 业务层:Spring 5.x + SpringMVC
- 持久层:MyBatis 3.x + MySQL 8.0
选择SSM框架而非Spring Boot主要基于以下考虑:
- 毕业设计需要展示对基础框架的理解
- 手动配置更能体现技术掌控能力
- 方便演示各层间的交互过程
2.2 核心功能模块
mermaid复制graph TD
A[用户模块] --> B[药品展示]
A --> C[购物车]
A --> D[订单管理]
E[管理员模块] --> F[药品管理]
E --> G[处方审核]
E --> H[销售统计]
3. 数据库设计要点
3.1 关键表结构
**药品表(medicine)**设计示例:
sql复制CREATE TABLE `medicine` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL COMMENT '药品通用名',
`spec` varchar(50) NOT NULL COMMENT '规格',
`approval_no` varchar(50) COMMENT '批准文号',
`category_id` int(11) COMMENT '分类ID',
`is_rx` tinyint(1) DEFAULT 0 COMMENT '是否处方药',
`price` decimal(10,2) NOT NULL,
`stock` int(11) DEFAULT 0,
`image_url` varchar(255),
`detail` text COMMENT '药品说明书',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_approval` (`approval_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3.2 业务关联设计
处方药销售需要特别设计审核流程:
- 用户提交处方照片
- 系统创建待审核订单
- 药师后台审核通过后订单生效
- 系统扣减库存
对应的订单表需要包含审核状态字段:
java复制public class Order {
private Integer id;
private String orderNo;
private Integer userId;
private BigDecimal amount;
private Integer status; // 0-待审核 1-已通过 2-已发货...
private String prescriptionImg; // 处方照片URL
private Date createTime;
// getters/setters...
}
4. 核心功能实现
4.1 药品展示模块
采用JSP+EL实现动态列表展示:
jsp复制<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<div class="medicine-list">
<c:forEach items="${medicineList}" var="item">
<div class="medicine-item">
<img src="${pageContext.request.contextPath}${item.imageUrl}">
<h3>${item.name}</h3>
<p>规格:${item.spec}</p>
<p class="price">¥${item.price}</p>
<c:if test="${item.isRx eq 1}">
<span class="rx-tag">处方药</span>
</c:if>
<button onclick="addToCart(${item.id})">加入购物车</button>
</div>
</c:forEach>
</div>
4.2 购物车实现
使用Session存储临时购物车数据:
java复制@Controller
@RequestMapping("/cart")
public class CartController {
@PostMapping("/add")
public String addItem(@RequestParam Integer medicineId,
@RequestParam Integer quantity,
HttpSession session) {
// 获取或创建购物车
Map<Integer, Integer> cart = (Map<Integer, Integer>) session.getAttribute("cart");
if(cart == null) {
cart = new HashMap<>();
session.setAttribute("cart", cart);
}
// 合并商品数量
cart.merge(medicineId, quantity, Integer::sum);
return "redirect:/cart/view";
}
}
5. 典型问题解决方案
5.1 处方审核流程
实现带状态转换的订单审核:
java复制@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderMapper orderMapper;
@Transactional
public void approveOrder(Integer orderId, Integer pharmacistId) {
Order order = orderMapper.selectById(orderId);
if(order.getStatus() != 0) {
throw new IllegalStateException("订单当前状态不可审核");
}
// 更新订单状态
order.setStatus(1);
order.setPharmacistId(pharmacistId);
order.setApproveTime(new Date());
orderMapper.updateById(order);
// 扣减库存
List<OrderItem> items = orderItemMapper.selectByOrderId(orderId);
for(OrderItem item : items) {
medicineMapper.reduceStock(item.getMedicineId(), item.getQuantity());
}
}
}
5.2 药品搜索优化
针对药品名称建立模糊查询索引:
sql复制ALTER TABLE medicine ADD FULLTEXT INDEX idx_search(name, spec) WITH PARSER ngram;
对应的MyBatis查询:
xml复制<select id="searchMedicine" resultType="Medicine">
SELECT * FROM medicine
WHERE MATCH(name, spec) AGAINST(#{keyword} IN NATURAL LANGUAGE MODE)
<if test="categoryId != null">
AND category_id = #{categoryId}
</if>
LIMIT #{offset}, #{pageSize}
</select>
6. 项目部署注意事项
6.1 运行环境配置
推荐使用Tomcat 9.x + JDK 8组合,需要注意:
- 设置Tomcat的URIEncoding为UTF-8
- 配置JVM参数处理药品图片上传:
bash复制export JAVA_OPTS="-Xms512m -Xmx1024m -XX:MaxPermSize=256m"
6.2 常见问题排查
中文乱码问题解决方案:
- 确保JSP页面头部有:
jsp复制<%@ page contentType="text/html;charset=UTF-8" language="java" %>
- 在web.xml中添加过滤器:
xml复制<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
7. 项目扩展建议
- 智能推荐功能:基于用户购买历史实现协同过滤推荐
java复制public List<Medicine> recommendMedicines(Integer userId) {
// 获取用户历史订单
List<Order> orders = orderMapper.selectByUser(userId);
// 提取药品特征(此处简化为类别偏好)
Map<Integer, Integer> categoryPref = orders.stream()
.flatMap(order -> order.getItems().stream())
.collect(Collectors.groupingBy(
item -> item.getMedicine().getCategoryId(),
Collectors.summingInt(OrderItem::getQuantity)
));
// 返回同类药品
Integer maxCategory = Collections.max(categoryPref.entrySet(),
Map.Entry.comparingByValue()).getKey();
return medicineMapper.selectByCategory(maxCategory, 10);
}
- 对接医保接口:需要实现医保结算协议(需申请资质)
- 移动端适配:可采用响应式布局或开发微信小程序
这个项目我在实际指导过程中发现,药品库存的并发控制是学生最容易忽视的问题。推荐使用乐观锁机制:
java复制@Update("UPDATE medicine SET stock = stock - #{quantity}, version = version + 1
WHERE id = #{id} AND version = #{version}")
int reduceStockWithLock(@Param("id") Integer id,
@Param("quantity") Integer quantity,
@Param("version") Integer version);
对于毕业设计答辩,建议重点展示处方审核流程和药品分类管理这两个特色模块,这能体现对医药行业特殊性的理解。数据库设计部分要明确展示药品与普通商品在字段设计上的区别,如批准文号、处方药标志等专业字段。
