基于SSM框架的在线药品销售商城系统 - 源码深度解析
在医药零售行业数字化转型的浪潮中,传统药店面临着销售渠道单一、运营成本高企、用户购药便利性不足等核心挑战。医药电商平台应运而生,通过B2C模式为消费者提供安全便捷的药品选购体验,同时帮助药店实现业务数字化升级。本系统采用成熟的SSM(Spring+SpringMVC+MyBatis)框架技术栈,构建了一个功能完备的在线药品销售解决方案。
系统架构与技术栈设计
该平台采用经典的三层架构模式,确保系统的高内聚低耦合特性:
前端展示层
- JSP动态页面技术:实现动态内容渲染
- jQuery+Bootstrap框架:构建响应式用户界面,支持多终端适配
- AJAX异步交互:提升用户体验,实现局部刷新
业务逻辑层
- Spring框架核心:基于IOC容器实现依赖注入,降低组件耦合度
- 声明式事务管理:通过@Transactional注解确保数据一致性
- AOP面向切面编程:统一处理日志、权限等横切关注点
数据持久层
- MyBatis映射框架:提供灵活的SQL定制能力
- 动态SQL支持:根据不同条件生成优化查询语句
- 二级缓存机制:提升数据访问性能
技术栈配置
通过Maven进行依赖管理,关键配置如下:
<dependencies>
<!-- Spring核心依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<!-- MyBatis整合Spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
</dependencies>
Spring配置文件中定义了数据源和事务管理器:
@Configuration
@EnableTransactionManagement
@ComponentScan("com.pharmacy.service")
public class SpringConfig {
@Bean
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mysql://localhost:3306/pharmacy_db?useUnicode=true");
dataSource.setUsername("root");
dataSource.setPassword("password");
return dataSource;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
}
数据库设计亮点分析
商品表设计优化
商品表(item)的设计体现了医药电商业务的特殊性。该表采用垂直分表的思想,将商品基本属性与动态业务数据分离:
CREATE TABLE `item` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`name` varchar(255) DEFAULT NULL COMMENT '商品名称',
`price` varchar(255) DEFAULT NULL COMMENT '商品价格',
`scNum` int(11) DEFAULT NULL COMMENT '收藏数',
`gmNum` int(11) DEFAULT NULL COMMENT '购买数',
`url1` varchar(255) DEFAULT NULL COMMENT '图片URL1',
`url2` varchar(255) DEFAULT NULL COMMENT '图片URL2',
`url3` varchar(255) DEFAULT NULL COMMENT '图片URL3',
`url4` varchar(255) DEFAULT NULL COMMENT '图片URL4',
`url5` varchar(255) DEFAULT NULL COMMENT '图片URL5',
`ms` text DEFAULT NULL COMMENT '商品描述',
`pam1` varchar(255) DEFAULT NULL COMMENT '参数1',
`pam2` varchar(255) DEFAULT NULL COMMENT '参数2',
`pam3` varchar(255) DEFAULT NULL COMMENT '参数3',
`val3` varchar(255) DEFAULT NULL COMMENT '值3',
`val2` varchar(255) DEFAULT NULL COMMENT '值2',
`val1` varchar(255) DEFAULT NULL COMMENT '值1',
`type` int(11) DEFAULT NULL COMMENT '商品类型',
`zk` int(10) DEFAULT NULL COMMENT '折扣',
`category_id_one` int(11) DEFAULT NULL COMMENT '一级分类ID',
`category_id_two` int(11) DEFAULT NULL COMMENT '二级分类ID',
`isDelete` int(2) DEFAULT NULL COMMENT '0否 1是',
`num` int(2) DEFAULT 0 COMMENT '库存数量',
PRIMARY KEY (`id`),
KEY `idx_category` (`category_id_one`,`category_id_two`),
KEY `idx_price` (`price`),
KEY `idx_zk` (`zk`)
) ENGINE=InnoDB AUTO_INCREMENT=86 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='商品表'
设计亮点分析:
多图片存储设计
- url1-url5字段支持商品多角度展示
- 满足药品需要展示说明书、包装等详细信息的需求
- 支持药品外观、规格说明、使用说明等多维度展示
弹性参数结构
- pam1-pam3和val1-val3组成键值对
- 可灵活存储药品规格、剂型、生产厂家等差异化属性
- 支持不同类型药品的参数扩展需求
双重分类索引
- category_id_one和category_id_two建立复合索引
- 支持高效的多级分类查询和商品筛选
- 优化分类导航和商品检索性能
软删除机制
- isDelete字段实现逻辑删除
- 保留历史数据的同时避免物理删除的风险
- 支持数据恢复和审计追踪
购物车表业务逻辑设计
购物车表(car)的设计重点考虑了并发操作和价格一致性问题:
CREATE TABLE `car` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`item_id` int(11) DEFAULT NULL COMMENT '商品ID',
`user_id` int(11) DEFAULT NULL COMMENT '用户ID',
`num` int(11) DEFAULT NULL COMMENT '数量',
`price` decimal(10,2) DEFAULT NULL COMMENT '单价',
`total` varchar(255) DEFAULT NULL COMMENT '总价',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_user_item` (`user_id`,`item_id`),
KEY `idx_user` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='购物车表'
关键设计策略:
价格快照机制
- price字段在加入购物车时存储商品当时价格
- 避免后续价格变动影响已选商品
- 确保购物车价格与用户加入时一致
唯一性约束
- uk_user_item索引防止同一用户重复添加同一商品
- 优化购物车操作体验,避免数据冗余
- 提升购物车管理的效率
十进制精度
- price使用decimal(10,2)类型
- 确保金额计算的精确性
- 符合金融级精度要求

核心功能实现深度解析
用户权限控制与会话管理
系统采用基于拦截器的权限控制机制,确保不同角色用户访问权限的严格分离:
@Component
public class AuthInterceptor implements HandlerInterceptor {
private static final String[] IGNORE_URI = {"/login", "/register", "/index"};
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
String uri = request.getRequestURI();
// 放行静态资源和登录相关请求
for (String ignore : IGNORE_URI) {
if (uri.contains(ignore)) {
return true;
}
}
HttpSession session = request.getSession();
User user = (User) session.getAttribute("user");
if (user == null) {
response.sendRedirect(request.getContextPath() + "/login");
return false;
}
// 基于角色的权限验证
if (!hasPermission(user.getRole(), uri)) {
response.sendRedirect(request.getContextPath() + "/error/403");
return false;
}
return true;
}
private boolean hasPermission(Role role, String uri) {
// 实现基于角色的权限验证逻辑
return true;
}
}
权限控制特色:
细粒度权限管理
- 支持用户、管理员、药师等多角色权限控制
- 基于URL模式的权限验证机制
- 动态权限配置支持
会话安全机制
- Session超时自动处理
- 防止会话固定攻击
- 支持分布式会话管理
拦截器链设计
- 多个拦截器协同工作
- 支持拦截器执行顺序控制
- 灵活的异常处理机制