news 2026/9/24 21:57:51

SSM框架药店进销存系统:前台商城+后台库存管理全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SSM框架药店进销存系统:前台商城+后台库存管理全解析

做毕业设计和课程设计这些年,SSM框架的管理系统我见得实在太多了,但“java_ssm131龙康药店库存进销存管理系统”这个项目,我第一次拿到手的时候还是觉得有点意思。一般的课设系统大多是单后台、纯增删改查,这个项目不一样,它带了一个完整的前台商城,药品分类展示、搜索、购物车、模拟下单全都有,后台还要管采购入库、销售出库、库存预警、统计报表,这已经算是“进销存 + 电商前台”的双端闭环了。

整份源码基于Spring + SpringMVC + MyBatis这套经典SSM组合,开发工具是IntelliJ IDEA,数据库用的MySQL,非常适合Java Web刚入门、想系统看一个完整项目的同学。你在github或网盘上搜“龙康药店”也能找到不少流传版本,但网上大部分资源要么缺文档,要么跑不起来,真正能把项目导入IDEA、配置好环境、把页面调通的人其实不多。这篇文章就围绕这套源码,从项目设计、技术选型、核心业务逻辑、IDEA部署实操到常见报错排查,完整拆一遍。无论你是要做课程设计、毕业设计,还是想练手一套带前台的进销存系统,这篇文章都能帮你少走不少弯路。

1. 项目到底做什么:龙康药店进销存系统的构建思路

1.1 医药零售场景下的库存管理痛点

刚开始看这类系统,很多人会把它当成普通超市进销存来理解,但药店和超市有个本质区别:药品是严格受监管的商品,有批号、有效期、生产日期,而且库存多了会过期,库存少了影响销售,所以对“进出有据、账实相符”的要求比一般商品高得多。龙康药店这套系统虽然没有做GSP(药品经营质量管理规范)级别的复杂效期管理,但从表结构和业务设计上,已经具备了一套进销存系统最核心的骨架。

系统要解决的问题其实很朴素:药店里面每天有采购进来的药品,有顾客买走的药,有退货,有临期处理,如果全用Excel记,日子一久必然对不上账。所以这套系统把“采购入库 -> 库存增加 -> 前台销售 -> 库存扣减 -> 库存预警 -> 报表统计”这条链路用代码串了起来。后台管理员负责维护药品、供应商、采购单、库存;前台用户注册登录之后可以浏览药品、加入购物车、下单,整个流程都是通的。

1.2 功能模块全景图与用户角色

这套系统从前台到后台,核心角色分三类:管理员、员工、普通用户。管理员是后台的最高权限,负责药品分类、药品信息、供应商、采购单、销售单、库存管理;员工可以帮忙处理订单发货,但一般不能动系统基础配置;普通用户在商城前台注册登录,浏览商品、加购物车、确认订单。

功能模块拆开来看,大概是这样:

  • 系统登录与权限控制:后台入口需要管理员/员工登录,前台用户单独注册登录。
  • 药品分类管理:维护中药、西药、医疗器械等分类,方便前台分类展示。
  • 药品信息管理:包括药品名称、规格、生产厂家、批准文号、进价、零售价、库存上下限。
  • 供应商管理:记录供应商名称、联系人、联系电话,采购单要从这里选供应商。
  • 采购入库管理:创建采购单,选择药品、填写数量、进价,入库后自动增加库存。
  • 销售出库管理:前台用户下单生成销售单,后台管理员/员工处理订单,出库后扣减库存。
  • 库存查询与预警:库存列表展示当前数量,低于预警阈值的药品高亮显示。
  • 销售统计报表:按日、按月统计销售金额与数量,用于了解店铺经营情况。

这些模块放在一起,就是一个非常标准的药店进销存闭环。你如果把这个项目吃透,市面上绝大多数后台管理系统的开发套路基本就能摸清了。

2. 技术选型与设计思路:SSM框架为什么至今仍是经典

2.1 SSM三层架构与项目代码结构

先聊聊技术栈。现在很多人一谈起Java Web,张嘴就是Spring Boot + Vue,但为什么这套源码还在用SSM?其实理由很简单:大多数高校的Java Web课程、毕业设计,至今仍然以SSM为教学主线。SSM本身并不老旧,它只是把Spring、SpringMVC、MyBatis这三个框架组合起来,各司其职,分工非常清晰。

  • Spring:负责对象管理,把Service层、Mapper层、事务管理等对象交给Spring容器管理。你不用到处new对象,依赖注入就够了。
  • SpringMVC:负责Web层的请求转发与参数绑定。前端页面发来请求,DispatcherServlet分发到对应的Controller方法,处理完再返回视图或JSON。
  • MyBatis:负责持久层 SQL 操作。SQL写在XML文件里面,Mapper接口定义方法,调用时动态拼SQL,既灵活也直观。

这套项目打开之后,典型的目录结构长这样:

src/main/java ├── com.longkang.controller // Controller层 ├── com.longkang.service // Service接口 ├── com.longkang.service.impl // Service实现类 ├── com.longkang.mapper // MyBatis Mapper接口 ├── com.longkang.pojo // 实体类 ├── com.longkang.common // 通用工具、常量 └── com.longkang.interceptor // 拦截器 src/main/resources ├── mapper // MyBatis XML映射文件 ├── jdbc.properties // 数据库连接配置 ├── spring-mybatis.xml // Spring整合MyBatis └── spring-mvc.xml // SpringMVC配置 src/main/webapp ├── jsp / pages // 后台JSP页面 ├── front / 前台页面 ├── static / css, js, images └── WEB-INF / web.xml

新手面对这个结构,最容易犯的一个错误是:拿到源码直接往IDEA里扔,然后找不到启动入口。SSM项目的入口不在某个main方法,而在web.xml配置的DispatcherServlet,以及Spring的ApplicationContext。理解这一点,后面部署排查才有方向。

2.2 数据库表设计:进销存的核心是“流水账”

很多课设项目的数据库就三五张表,但进销存系统如果想做到逻辑自洽,表设计至少要覆盖“主数据 + 单据 + 流水 + 关系表”这四类。龙康药店这套项目的表大致是这个思路:

  • 主数据表:admin(管理员/员工)、user(前台用户)、supplier(供应商)、medicine_type(药品分类)、medicine(药品)
  • 单据表:purchase_order(采购单)、purchase_order_detail(采购单明细)、sale_order(销售单)、sale_order_detail(销售单明细)
  • 购物车表:cart(购物车)
  • 库存与流水表:stock(库存表)、inventory_log(库存流水)

这里最核心的设计点,是“单据和单据明细分离”。为什么不能直接在一张采购表里存药品名称、数量、进价?因为一张采购单可能会同时采购几十种药,一行完全存不下;而且单据有表头信息(供应商、采购员、总金额、下单时间)和明细信息(哪批次、哪种药、多少数量、多少钱),这两者天然是一对多的关系,所以必须拆成主表和子表。

另一个很关键的设计是库存流水表。每次采购入库、销售出库、退货,除了改库存表里的数量,还应该往库存流水表里插一条记录。这样做的好处是,哪天库存对不上了,可以通过流水倒查,是哪个环节出的问题。很多半吊子源码没有流水表,出库就UPDATE一下库存,看起来没问题,但一旦出现并发订单或程序报错,账目就成一锅粥了。

药品表里通常会设几个关键字段:stock_min(最低库存)、stock_max(最高库存)、price_in(进价)、price_out(零售价)。预警功能就是拿当前库存和stock_min做比较,低于阈值就提醒补货。

2.3 前后台分离的设计取舍

既然是“带前台”的药店系统,就涉及前台和后台的展示区分。SSM项目里最常见的做法是:后台用一套JSP放在WEB-INF或者单独/admin目录下面,前台商城用另一套JSP放在根目录下面,两边共用同一套Service和Mapper,但Controller分开。

这样做的好处首先是权限隔离。后台入口设置管理员登录拦截,普通用户访问不了;前台页面则允许游客浏览,只有在加购物车、下单时才要求登录。其次,两套页面的风格完全不同,后台是密集的表格+表单,前台是商品卡片+购物车,放在不同目录下,代码维护起来不会互相干扰。

要注意的是,这套源码的前台和后台,前端渲染都由JSP完成,并没有单独做前后端分离接口。如果你以后想改成Vue前端,可以把Controller改成返回JSON,再配合前端的axios请求,这个改造也不算难,后面我会单独讲。

3. 核心业务实现详解:从采购入库到前台下单

3.1 采购入库:库存更新与事务控制

采购入库这个功能,表面上就是“填一张采购单,点一下提交,库存增加”,但代码实现上必须保证原子性。我看了源码里的流程,大致是这样:

  1. 管理员在后台选择供应商,填写采购单表头信息。
  2. 在明细列表中添加一种或多种药品,输入采购数量和进价。
  3. 提交时,后端先insert采购单主表,再批量insert采购单明细表。
  4. 最后循环遍历明细,UPDATE库存表,让库存数量加上采购数量。

这个流程里最容易出问题的是第四步。如果三个药品的采购明细,前两个都执行成功,第三个UPDATE库存时报错了,那数据库里就会留下“采购单存在、但库存只加了一半”的脏数据。所以Service层必须加@Transactional事务注解,让这四个步骤要么全部成功,要么全部回滚。

Service实现里大概是这样的写法:

@Transactional(rollbackFor = Exception.class) public boolean addPurchaseOrder(PurchaseOrder order, List<PurchaseOrderDetail> details) { int count = purchaseOrderMapper.insertSelective(order); if (count == 0) { return false; } for (PurchaseOrderDetail detail : details) { purchaseOrderDetailMapper.insert(detail); stockMapper.increaseStock(detail.getMedicineId(), detail.getPurchaseNum()); } return true; }

这里还有一个容易踩的坑:库存表初始数据哪里来?正常系统在第一次采购入库之前,库存表里应该已经有药品的基础库存,或者在采购入库时判断库存不存在则新增一条。很多新手在测试时发现:采购单建成功了,库存却没变,多半就是库存表里根本没有对应药品的初始记录,UPDATE语句影响行数为0。代码里最好处理成“有则加、无则insert”,否则会让人排查很久。

3.2 前台购物:购物车、下单与库存扣减

前台的商城流程比较接近真实电商的简化版:游客浏览药品 -> 点击加入购物车 -> 跳转到购物车页面 -> 确认结算 -> 生成订单 -> 后台订单列表中能看到。这里有几个细节值得说一说。

购物车表的核心设计是userId + medicineId + quantity三要素,一个用户对同一种药品只保留一条记录。用户重复加入同一个药品时,不应该在购物车中新增一行,而是把quantity累加。我见过不少新手源码在这里直接insert,导致购物车里出现两行一模一样的药,这种低级错误很影响体验。

结账生成销售单的时候,要考虑库存是否充足。用户下单数量不能超过当前库存,否则应该提示“库存不足”。严谨一点的写法是在SQL层面做条件更新:

UPDATE stock SET stock_num = stock_num - #{num} WHERE medicine_id = #{medicineId} AND stock_num >= #{num}

这条语句是利用数据库的行锁做并发控制,即使两个人同时下同一款药的订单,也不会把库存扣成负数。先查询库存再在Java里判断,在高并发场景下是有风险的,所以写销售出库的update时最好带上stock_num >= #{num}这个条件,然后判断影响行数是否为0。如果影响行数为0,就说明库存已经被别人抢光了。

3.3 库存预警与销售统计报表

库存预警的实现不复杂,核心还是SQL聚合。后台每个页面加载后,会去查一遍库存表中所有低于最低库存阈值的药品:

SELECT m.medicine_name, s.stock_num, m.stock_min FROM stock s LEFT JOIN medicine m ON s.medicine_id = m.id WHERE s.stock_num <= m.stock_min

这类预警一般放在首页仪表盘,显示一个红色提醒列表,同时在库存管理页面把低库存药品标红。对药店来说,这个功能很重要,因为药品断货会直接影响门店营收,所以做演示的时候一定要把预警做明显一点,答辩时也容易成为加分项。

销售统计报表这块,源码里一般是统计订单的聚合数据,比如当天营业额、本月营业额、销量Top5药品。SQL用GROUP BY + SUM + DATE_FORMAT函数即可。例如统计每天的销售总额:

SELECT DATE_FORMAT(create_time, '%Y-%m-%d') AS day, SUM(total_price) AS total_sales FROM sale_order WHERE order_status = 2 -- 已完成 GROUP BY day ORDER BY day DESC

如果页面需要更直观的图表展示,通常会引入ECharts,把聚合结果转成JSON返回前端,画折线图或柱状图。基础课设做到这一步已经绰绰有余了。

3.4 权限控制与会话管理

后台访问控制通常靠拦截器实现。写一个LoginInterceptor,实现HandlerInterceptor接口,在preHandle方法里判断session里有没有登录用户,没有就重定向到登录页。

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Object user = request.getSession().getAttribute("admin"); if (user == null) { response.sendRedirect(request.getContextPath() + "/login.jsp"); return false; } return true; }

然后在spring-mvc.xml里配置拦截规则,最核心的一条是要把登录页、静态资源、前台页面放行,否则会出现“登录页都进不去”的尴尬。我见过有同学把拦截器配置成/**,结果静态CSS、JS全部被拦,页面样式全丢了,排查半天才发现是拦截器放行路径没写好。

<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/admin/**"/> <mvc:exclude-mapping path="/admin/login"/> <mvc:exclude-mapping path="/static/**"/> </mvc:interceptor> </mvc:interceptors>

前台部分则相对宽松,游客可以浏览药品,但加入购物车和结算时Controller判断用户是否登录。session里没有userId时,直接跳回登录页,登录成功再返回购物车。

4. 源码落地:IDEA导入部署的完整实操记录

4.1 环境准备清单

拿到源码,第一件事不是急着打开IDEA,而是先把环境准备好。这套项目属于传统SSM,依赖的运行时环境跟Spring Boot不太一样,Java版本、Tomcat版本、Maven版本如果对不上,启动时会冒出各种奇奇怪怪的错误。

建议环境如下:

  • JDK 1.8:SSM的老项目几乎都基于JDK8开发,用太高版本反而可能编译不过。
  • Maven 3.6.x:用于拉取Spring、MyBatis等依赖,版本太新偶尔会跟旧插件不兼容。
  • Tomcat 8.5或9.0:重要的事说三遍,不要直接用Tomcat 10,Tomcat 10把javax.包改成了jakarta.,老SSM项目会直接报ClassNotFoundError。
  • MySQL 5.7或8.0:最好版本不低于5.5,另外连接MySQL8要记得用新驱动。
  • IntelliJ IDEA:社区版或正式版都可以,社区版装个Tomcat插件就能跑。

注意:不要在这类老项目上强行追求“所有版本最新”。JDK17 + Tomcat10 + MySQL8.0 + 最新Maven组合,对于SSM项目来说不仅没有性能提升,反而会让你在环境配置上耗费大量时间。

4.2 IDEA导入源码到运行

IDEA导入SSM项目,最高效的方式是直接打开项目的pom.xml,让IDEA识别为Maven项目。具体步骤很简单:

  1. 打开IDEA,选择File -> Open,找到项目根目录下的pom.xml,点击OK。
  2. IDEA询问“Open as Project or File?”时,选择Open as Project。
  3. 确认Project SDK选择1.8,如果没有JDK1.8,先在Project Structure -> SDKs里添加。
  4. 等待右侧Maven面板把依赖全部下载完毕。这一步取决于网络环境,依赖下载失败的话,后面启动就会疯狂报错。
  5. 配置Tomcat:下拉框选择Edit Configurations -> Add New -> Tomcat Server -> Local,在Deployment选项卡里添加Artifact: xxx:war exploded

这里有个细节,如果是第一次用IDEA跑传统Web项目,很可能发现Deployment里没有Artifact可选。这是因为项目还没有被识别为Web项目。解决办法是打开Project Structure -> Facets,点击加号添加Web,把Web Resource Directory指定到src/main/webapp,然后在Artifacts里新建一个Web Application: Exploded。配好之后,IDEA才能把项目打成可部署的war包。

Tomcat配置中,Application context通常设置为/,这样访问地址直接是http://localhost:8080,不用额外拼接项目名。如果项目里用相对路径写了很多跳转,context设置为空会省很多麻烦。

4.3 数据库初始化与连接配置

接下来要创建数据库并导入表结构和初始数据。一般源码包里会带一个db.sqllongkang.sql文件。打开Navicat或MySQL命令行:

mysql -uroot -p CREATE DATABASE longkang DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; USE longkang; SOURCE D:/path/to/longkang.sql;

导入成功之后,修改项目里的jdbc.properties,把数据库的账号密码改成你自己的。这里有两个非常典型的版本差异:

MySQL 5.7版本:

jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/longkang?characterEncoding=utf8 jdbc.username=root jdbc.password=123456

MySQL 8.0版本:

jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/longkang?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true jdbc.username=root jdbc.password=你的密码

MySQL8的密码加密规则是caching_sha2_password,老驱动连接时会报Public Key Retrieval is not allowed,所以URL里必须带上allowPublicKeyRetrieval=trueuseSSL=false。如果密码配置不对,启动时日志里会出现Access denied for user 'root'@'localhost',这时候不要去改代码,先去确认密码。

4.4 启动验证与关键节点检查

配置完成后,点击Tomcat旁边的绿色三角启动。第一次启动成功后,浏览器会自动打开首页。这时候建议按下面几个节点做一次完整验证:

  1. 前台首页能不能打开:正常的药店前台应该有分类菜单、药品列表、搜索框。
  2. 用户注册/登录:能注册新账号,登录后session能正常写入。
  3. 加入购物车并下单:能生成销售订单,库存数量对应扣减。
  4. 后台登录:用admin账号进入后台,看能否看到带预警信息的首页仪表盘。
  5. 新增一笔采购单:后台增加供应商、选择药品、提交采购单,库存能不能同步增加。

如果这些流程都通了,说明项目已经完整跑起来了。但现实往往是,第一次启动就会卡在某个报错上。所以接下来这部分,我把跑项目过程中最常见的坑整理出来,你对照排查即可。

5. 从0到1跑通项目的各类坑与排查技巧

5.1 数据库连接类问题

这类报错是启动时出现频率最高的。常见问题与定位手段如下:

  • Access denied for user 'root'@'localhost' (using password: YES):连接数据库的账号密码不对。用Navicat测试能否用同一个账号密码连上数据库。
  • UnknownHostExceptionCommunications link failure:数据库服务没启动,或者URL里的localhost写错,检查3306端口是否被占用。
  • Public Key Retrieval is not allowed:MySQL8的URL里少了allowPublicKeyRetrieval=true
  • Unknown database 'longkang':数据库没有创建成功,或者名字跟jdbc.properties里的不一致。
  • Table 'xxx' doesn't exist:说明.sql文件没有完全导入,或者导到了别的库。用SHOW TABLES;检查一遍。

排查数据库问题的黄金命令:复制jdbc.properties里的URL、用户名、密码,在Navicat新建连接里试一次。如果Navicat能连,项目连不上,大概率是驱动或URL问题;如果Navicat都连不上,那就是MySQL服务或密码问题。

5.2 Tomcat启动与404问题

  • 启动报java.lang.NoClassDefFoundError: javax/servlet/...:Tomcat版本太高,换成Tomcat 8.5或9.0。
  • 启动报ClassNotFoundException: org.springframework.web.context.ContextLoaderListener:Spring的jar包没打包进Artifact。打开Project Structure -> Artifacts -> Output Layout,把Available Elements里的Maven依赖全部加入。
  • 启动正常但访问后台404:检查Application context是不是/,同时确认Controller里的请求映射路径和前端跳转路径是否一致。SSM项目经常出现前端写/admin/toAdd.jsp,但实际Controller映射是/admin/add的情况,这类路径问题只能靠仔细对比。
  • 页面能打开但样式全丢:多半是JSP里引入CSS用了绝对路径,但项目部署context没带项目名,或者在拦截器里把静态资源拦截了。建议统一用${pageContext.request.contextPath}拼接静态资源路径。

5.3 中文乱码问题

中文乱码在这个项目里很容易出现,因为涉及的环节太多:JSP页面编码、数据库编码、请求编码、响应编码,任何一个环节不一致都会乱。

  • 数据库层面:建库时用DEFAULT CHARACTER SET utf8,表字段也统一用utf8。
  • JSP页面:pageEncoding="UTF-8"contentType="text/html; charset=UTF-8"都写上。
  • 请求参数乱码:在web.xml里配置Spring自带的CharacterEncodingFilter,强制请求和响应都走UTF-8。
<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> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

如果上述都配置了还是乱码,再看看数据库连接URL里有没有characterEncoding=utf8,SQL文件导入时是否选择了正确的字符集。

5.4 Maven依赖与构建问题

SSM项目常见的Maven报错,一是依赖迟迟下载不下来,二是jar包冲突。

依赖下载慢,在settings.xml里配置阿里云镜像:

<mirror> <id>aliyunmaven</id> <mirrorOf>central</mirrorOf> <name>阿里云公共仓库</name> <url>https://maven.aliyun.com/repository/public</url> </mirror>

jar包冲突最常见的是javax.servlet-api和Tomcat自带的servlet-api冲突,会报ClassCastExceptionNoSuchMethodError。解决办法是把pom.xml里servlet-api的scope改成provided,让它只在编译时存在,运行时不打包进war。

<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency>

我当时跑的时候还遇到过一个问题:IDEA里Maven面板一片红,所有依赖都显示invalid。后来发现是项目里pom.xml的groupId和artifactId有特殊字符,加上本地Maven仓库里有坏包,删掉C:\Users\xxx\.m2\repository下对应的目录重新下载就好了。

6. 常见问题速查表与避坑清单

这里把部署和运行时最常见的问题整理成一张表,方便你直接对照。这些内容都是我在实际跑这套源码时踩过的坑,网上很多教程不会提到。

现象根本原因解决方案
启动报NoClassDefFoundError: javax/servletTomcat 10不兼容旧servlet包换Tomcat 8.5/9.0
访问后台404Application context或Controller路径不对将context设为/,检查请求映射
前端样式丢失静态资源被拦截或路径写死拦截器放行static目录,用${pageContext.request.contextPath}
数据库中文乱码字符集不一致统一UTF-8,URL加characterEncoding=utf8
MySQL8连接报Public Key RetrievalMySQL8新加密协议JDBC URL加allowPublicKeyRetrieval=true
事务不生效忘了加@Transactional或类没被Spring扫描Service实现类加事务注解与@Component
库存为负扣减库存未加数量条件UPDATE带stock_num >= #{num}
采购单成功但库存没变库存表无对应药品初始记录入库逻辑处理为“有则加、无则insert”
页面提示包不存在Maven依赖未完整下载配置阿里云镜像后重新reimport

避坑清单总的来说就三条:第一,不要盲目追求最新版本,Tomcat选对,JDK老老实实用8;第二,外部资源要先确认可用再启动,数据库能连上再点运行;第三,改任何配置前先备份,尤其是jdbc.properties和web.xml,这两个文件是系统能跑起来的命根子。

7. 个人经验与项目扩展思考

7.1 这类管理系统最容易忽略的几个设计细节

把这套系统完整跑通之后,我回过头想了一下,其实进销存类项目要做得好,“能跑”只是第一步,真正拉开差距的是几个容易被忽略的细节。

第一个是幂等性。用户连续点两次提交订单,系统不应该生成两笔一模一样的订单。严谨做法是在后端生成唯一订单号,并在数据库订单表中给订单号加唯一索引,重复提交时直接报错或忽略。

第二个是库存流水可追溯。有的版本没有库存流水表,销售出库后无法知道历史库存变动。我建议你在这个项目里自己加一张inventory_log表,每次出入库都记录操作时间、操作类型、变动数量、操作人,哪怕只是给答辩加分,这个表都很值。

第三个是搜索和筛选条件。药品列表页如果只能翻页,没有任何条件筛选,系统会显得特别业余。加一个按药品名称模糊查询、按分类下拉筛选,代码量不大,但用户体验提升非常明显。

第四个是前端校验与后端校验的结合。我在测试这个项目的时候,试着在价格输入框里填了负数,如果后端没有做校验,进价是-100的药也能入库。正规系统必须做“前端提示 + 后端校验”双重保障,后端的校验绝对不能省。

7.2 如果重新做一遍,我会怎么升级

如果你已经把这套SSM源码跑通,想进一步练手,我建议可以往这几个方向升级,难度逐渐递增:

  • 引入Maven多模块拆分:把pojo、mapper、service、controller拆成独立模块,虽然工程结构变复杂,但能让你对分层架构的理解更深刻。
  • 把JSP替换成前后端分离:后端只返回JSON,前端用Vue或纯HTML+Ajax。改造过程中你会更清楚Controller返回数据与返回视图的区别。
  • 增加药品效期管理:给药品加生产日期、有效期字段,在库存查询时自动计算临期药品并预警,这才是药店系统真正的业务难点。
  • 引入Redis缓存热点药品:前台首页的爆款药品列表可以缓存起来,体验一下传统SSM项目集成Redis的过程。
  • 用Spring Boot重写一遍:这是最经典的进阶路线,把XML配置改成注解和application.yml,你会发现Spring Boot对开发者有多友好。

做了这么多套管理系统,我个人最深的体会是:SSM框架本身并不难,难的是把“数据在页面、Controller、Service、Mapper、数据库之间完整流转”这件事理解透。龙康药店这套项目虽然代码量不算少,但胜在业务链路完整,从前台购物车到后台库存管理,每一步都有真实的业务动机。你能把它完整跑起来、能说清每个表为什么存在、每个事务为什么加,这套系统才算真正变成你自己的东西。第一次跑不通过很正常,不要急着删代码,先看日志、再查配置、最后看路径,绝大部分问题都是这三个环节里的低级错误。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 21:57:48

“多动症”提示词真能省Token?揭秘AI输出压缩机制

“我跟 AI 说自己『有多动症』&#xff0c;竟然能节省 Tokens&#xff1f;&#xff01;”这标题是不是有点标题党&#xff1f;我第一次看到这个说法的时候也嗤之以鼻&#xff0c;心想这不就是找个借口让 AI 少说点废话吗。但等我亲自把同样的任务&#xff0c;分别用“普通提问”…

作者头像 李华
网站建设 2026/9/24 21:57:47

正负频率与收发变频方向:星座图镜像的根源解析

前两年调试一套 SDR 收发链路&#xff0c;遇到一个非常“邪门”的现象&#xff1a;发射端基带星座图明明正常&#xff0c;接收端解调出来的 QPSK 信号却永远报错&#xff0c;无论怎么调载波同步、符号同步都没用。后来把接收基带数据拉下来一分析&#xff0c;发现收到的根本不是…

作者头像 李华
网站建设 2026/9/24 21:57:29

听错信息不必慌:从大脑补全机制到高效纠错与防错全攻略

会议室里&#xff0c;领导交代完下周的工作安排&#xff0c;语速不慢&#xff0c;思路很快。你坐在那里点头&#xff0c;回工位一坐下突然愣住——他说的是周五之前还是下周一之前&#xff1f;打开聊天窗口想问&#xff0c;又怕显得自己没认真听&#xff0c;纠结半天还是算了&a…

作者头像 李华
网站建设 2026/9/24 21:56:28

pyspider爬虫框架入门:从环境搭建到完整项目实战

刚接触 Python 爬虫那会儿&#xff0c;我的第一反应是打开 requests 对着页面一顿猛写&#xff0c;然后被翻页、去重、断点续抓、异常重试这些事反复折磨。后来换到 pyspider&#xff0c;第一次打开它的 Web 控制台时&#xff0c;说实话有点恍惚&#xff1a;这玩意儿居然自带一…

作者头像 李华
网站建设 2026/9/24 21:55:56

用DeepSeek做AI短视频:从脚本到变现的全流程实操

做短视频副业这件事&#xff0c;我见过太多人卡在同一个死循环里&#xff1a;刷到别人一条带货视频赚了多少、一条知识口播涨了多少粉&#xff0c;热血上涌决定开干&#xff0c;结果真要动手时&#xff0c;面对的是不会写脚本、不会拍镜头、不会剪辑这三座大山。我自己的经验是…

作者头像 李华
网站建设 2026/9/24 21:55:55

Python实战:用python-pptx实现PPT自动化生成与批量处理

1. 为什么我想用Python折腾PPT先交代一下背景&#xff1a;我平时的工作里&#xff0c;做汇报PPT属于高频动作。季度总结、项目复盘、方案评审、培训材料……一个月下来怎么也有五六次。一开始我也和大多数人一样&#xff0c;老老实实手动排版、对齐、调字号、加动画&#xff0c…

作者头像 李华