news 2026/9/28 13:15:31

SSM+JSP供应链系统部署实战:从解压到二次开发全流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SSM+JSP供应链系统部署实战:从解压到二次开发全流程

简介:面向百货零售行业的供应链管理系统源码,后端采用Java与SSM框架(Spring+SpringMVC+MyBatis)整合,前端使用Vue/JSP技术,围绕采购、入库、库存、销售、供应商管理等供应链核心业务设计,既可作为在校学生的毕业设计,也适合中小型百货中心做信息化改造参考。压缩包共924个文件,大小约9.97MB,主要包含136个Java后端源文件、224个JS逻辑文件、102个CSS样式文件、72个JSP页面、25个HTML页面,以及2个SQL数据库脚本、XML配置和大量PNG/JPG/GIF图片资源,目录结构清晰,导入后即可运行调试。已有3524人浏览学习,项目经过严格调试,确保可直接部署。除了可运行的完整源码,还附带数据库脚本与项目功能介绍文档,能帮助学习者快速理解SSM整合流程、Vue.js与JSP混合前端的数据交互方式,以及供应链系统中订单、库存、供应商管理等模块的代码实现,是学习JavaWeb项目开发和准备毕业设计的实用素材。

1. 先搞明白这个 zip 里装的是谁:一个能跑多模块后台,还是一堆老代码?

下载到“ssm685百货中心供应链管理系统+jsp-lw.zip”这种文件,第一反应往往是:里面到底是一个能直接跑的 Java Web 项目,还是一堆靠运气才能救活的半成品?包名已经说得很直白——基于 SSM 框架(Spring + SpringMVC + MyBatis)的百货中心供应链管理系统,视图层用 JSP 渲染,整体以 zip 压缩包形式分发。这类项目在大学毕设、Java Web 课程设计和刚入行的从业者手里流传极广,价值不在技术新,而在结构完整:商品、采购、销售、库存、供应商、用户权限这些供应链核心模块通常都齐,跑起来就能当一套现成的多模块管理后台来拆解学习。

但真正决定你能不能用的,往往不是业务代码,而是 JDK、Tomcat、MySQL 的版本组合,以及 jdbc.properties 里那一行账号密码。一个跑不起来的 ssm+jsp 项目,跟一堆废码没有区别。这篇文章要做的,就是把这个 zip 从解压、配置、建库、部署到二次开发的完整链路走一遍,把最容易让人卡住的地方提前标出来。

2. 拆开 zip 看结构:SSM 项目到底由哪几块拼起来

2.1 解压后先找三样东西:SQL 脚本、jdbc 配置、web.xml

不管 zip 的名字有多花哨,解压出来第一件事不是急着打开 IDEA,而是先把目录结构摸一遍。常见做法是解压后先看一层目录,再按文件类型向下钻。一个标准的 SSM + JSP 项目,不管里面包了几层文件夹,最终都会长成下面这个样子:

ssm685/ ├── src/main/java/com/ │ ├── controller/ # 控制层,接收页面请求并返回 JSP 或 JSON │ ├── service/ # 业务层,供应链的采购、销售、库存核心逻辑 │ ├── dao/ # MyBatis 数据访问层(接口) │ └── entity/ # 实体类,对应数据库中的表 ├── src/main/resources/ │ ├── jdbc.properties # 数据库连接配置,最常出错的文件 │ ├── spring.xml # 整合配置,或拆成多个 spring-*.xml │ └── mapper/xxx.xml # 每个 DAO 对应的 SQL 映射 ├── src/main/webapp/ │ ├── WEB-INF/jsp/ # JSP 页面,通常按业务模块分目录 │ ├── static/ # CSS/JS/图片等静态资源 │ └── WEB-INF/web.xml # Java Web 入口配置 ├── pom.xml # Maven 依赖与打包配置 └── database/init.sql # 建库建表脚本

拿到文件后,按照“三个优先级”检查:第一,database 目录或任意位置的 .sql 脚本,它是这个项目的数据底座,没有它项目就是空壳;第二,src/main/resources 下的 jdbc.properties,它决定了项目连哪台 MySQL;第三,WEB-INF/web.xml,里面配置了 Spring 容器和 SpringMVC 的启动入口。找不到 SQL 脚本时,直接在解压目录跑一条全局搜索命令find . -name "*.sql",比人肉翻目录快得多。

2.2 SSM 整合的最小可运行配置:数据源、SqlSessionFactory、Mapper 扫描

SSM 项目的核心整合逻辑可以压缩成一句话:Spring 管对象,SpringMVC 管请求路由,MyBatis 管 SQL。三个框架黏合的关键配置通常在 spring.xml 或由它引入的 spring-mybatis.xml 里。看一个最小可运行配置,就能明白大部分翻车点出在哪里:

<!-- 1. 数据源:驱动、地址、账号密码全在这里 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <!-- 2. 让 MyBatis 知道去哪拿 SQL 映射文件 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="mapperLocations" value="classpath:mapper/*.xml" /> <property name="typeAliasesPackage" value="com.demo.entity" /> </bean> <!-- 3. 扫描所有 DAO 接口,自动生成代理对象 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.demo.dao" /> </bean>

这三段配置是 SSM 整合的骨架,缺一不可。数据源里的 driverClassName 要跟 MySQL 版本匹配,用 MySQL 8 就必须是com.mysql.cj.jdbc.Driver,老项目里常见的com.mysql.jdbc.Driver只适用于 MySQL 5.x。第二个 bean 里的 mapperLocations,如果配成classpath:mapper/*.xml,那就要求所有 XML 映射文件都在 resources/mapper 下;路径写错,启动时不报错,一调用 DAO 方法就抛 Invalid bound statement。第三个 bean 的 basePackage 必须和 DAO 接口所在包完全一致,多一个字母都会导致扫描不到。

SpringMVC 那一侧的配置同样有一个高频关注点——视图解析器。很多项目里长这样:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> </bean>

这段配置的意思很直接:Controller 里return "goods/list",最终渲染的是/WEB-INF/jsp/goods/list.jsp。这就是 JSP 项目的黑匣子——很多人把页面放错目录,或者把 prefix 改错,导致所有页面集体 404。只要看到“登录成功后跳不过去”这类问题,先怀疑视图解析器的前缀和实际文件路径对不上。

2.3 能跑和能改是两回事:先看清三层代码是否完整

判断一个 SSM 项目是好是坏,不能只看能不能启动,还要看代码分层是否完整。一个合格的 SSM 后台,Controller、Service、DAO 三层要层层分明,每个 DAO 接口边上要有一个对应的 Mapper XML。检查方法其实很简单,用两条命令就能看个大概:

# 统计 Mapper XML 文件数量 find . -name "*Mapper.xml" | wc -l # 统计 DAO 接口文件数量 find . -path "*/dao/*.java" | wc -l

两个数字接近,说明映射文件基本齐全;如果 XML 数量明显少于接口数量,说明这个包很可能缺了关键 SQL,跑到一半就会报方法找不到。另一种常见情况是接口和 XML 都存在,但 namespace 没对准,这种问题命令查不出来,只能打开 XML 文件看一眼namespace="com.demo.dao.GoodsDao"是否和接口的全限定名一致。这种“能跑但一调就挂”的项目,比直接报错更消耗耐心,提前摸清底细能省不少时间。

3. 供应链业务拆解:从表结构到 JSP 页面的数据流向

3.1 百货中心的供应链在管什么:模块边界与数据流

百货中心供应链管理系统听起来很大,拆开看其实就是六个模块打转:系统管理管用户和权限,商品管理管商品档案,供应商管理管供货方,采购管理负责进货,销售管理负责卖出,库存管理负责中间所有的进出记录。典型的业务闭环是:先建商品档案,再给商品关联供应商,然后创建采购单,采购单审核后入库,库存随之增加;消费者下单后创建销售单,销售单出库,库存随之减少。

这个数据流向决定了模块之间的依赖关系。商品模块是地基,没有商品档案,采购和销售都无从谈起;供应商模块和采购模块是上下游关系,一个采购单必须落到一个具体供应商上;库存模块是所有变动的中转站,采购入库和销售出库都在这里留下流水。很多 SSM 毕设项目做不完整,就是因为库存流水表被省掉了,只留一个商品表里的库存数字。表面看功能没缺,实际上数据一乱再也查不清楚,所以拿到项目后先确认有没有独立的库存变动记录表。

数据库设计直接决定二次开发的成本。比如商品表里存一个冗余的 stock 字段,方便列表页直接展示当前库存;但真正的库存变动明细要记在 stock_record 表里。这种“冗余字段 + 流水表”的组合在中小型管理后台里非常普遍,好处是查询快,坏处是更新时要保证两个地方一致,否则库存会越跑越偏。

3.2 数据库表设计:从商品到采购单的六张核心表

SSM 项目跑起来的第一个前置条件是库能建出来。绝大多数 zip 包都会带 SQL 脚本,但脚本里表名、字段名五花八门。下面这六张表是我见过最典型的百货中心供应链底座,字段做了精简,去掉了不重要的备注列,保留了业务闭环必须的关键信息:

-- 用户表,权限校验的基础 CREATE TABLE sys_user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(64) NOT NULL COMMENT '建议存 MD5 或加盐值', role VARCHAR(20) NOT NULL COMMENT 'admin/manager/operator' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 商品表,冗余当前库存字段 CREATE TABLE goods ( id INT PRIMARY KEY AUTO_INCREMENT, goods_no VARCHAR(30) NOT NULL UNIQUE COMMENT '商品编码', goods_name VARCHAR(100) NOT NULL, unit_price DECIMAL(10,2) NOT NULL, stock INT NOT NULL DEFAULT 0, status TINYINT NOT NULL DEFAULT 1 COMMENT '1 上架 0 下架' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 供应商表 CREATE TABLE supplier ( id INT PRIMARY KEY AUTO_INCREMENT, supplier_name VARCHAR(100) NOT NULL, contact_phone VARCHAR(20), address VARCHAR(200) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 采购单主表,一个采购单对应一次进货 CREATE TABLE purchase_order ( id INT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(30) NOT NULL UNIQUE, supplier_id INT NOT NULL, total_amount DECIMAL(12,2) NOT NULL, status TINYINT NOT NULL COMMENT '0 草稿 1 已入库', create_time DATETIME NOT NULL, CONSTRAINT fk_po_supplier FOREIGN KEY (supplier_id) REFERENCES supplier(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 采购明细表,一单多商品 CREATE TABLE purchase_item ( id INT PRIMARY KEY AUTO_INCREMENT, purchase_id INT NOT NULL, goods_id INT NOT NULL, quantity INT NOT NULL, price DECIMAL(10,2) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 库存流水表,所有入出库的痕迹都在这里 CREATE TABLE stock_record ( id INT PRIMARY KEY AUTO_INCREMENT, goods_id INT NOT NULL, change_type TINYINT NOT NULL COMMENT '1 入库 2 出库 3 盘点', change_qty INT NOT NULL, before_stock INT NOT NULL, after_stock INT NOT NULL, create_time DATETIME NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

这套表结构里,purchase_order 和 purchase_item 是一对多的主从关系;goods 表里的 stock 字段是冗余值,最终依据是 stock_record 里的流水差额。销售模块在简化版里通常只做销售单主表和销售明细表,出库时往 stock_record 写一条 change_type=2 的记录。拿到手的 SQL 脚本如果少了销售相关表,不用太慌,等跑通之后再按这套结构把表补上,二次开发的第一步就是补表。

3.3 JSP 页面与 Controller 的对应关系:改一个页面前先找三条线

JSP 项目里最大的认知门槛是“页面请求到底怎么流转”。一个标准流程是:浏览器访问/goods/list,Tomcat 把请求交给 DispatcherServlet,SpringMVC 根据@RequestMapping("/goods/list")找到 Controller 里的方法,方法调用 Service,Service 调 DAO,拿到数据后放入 Model,最后通过视图解析器拼接出 JSP 文件路径并渲染成 HTML。改页面之前,先顺着这三条线找齐代码:URL 映射在 Controller 里,数据获取在 Service/DAO 里,页面显示在 JSP 里。

权限校验是这类项目的另一个标配。供应链系统不可能让所有用户都能删商品、做采购审核,所以典型做法是用 SpringMVC 拦截器统一检查 session。一个最简的登录拦截器长这样:

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

拦截器要在 spring 配置文件里注册:

<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <mvc:exclude-mapping path="/login"/> <mvc:exclude-mapping path="/static/**"/> <bean class="com.demo.interceptor.LoginInterceptor"/> </mvc:interceptor> </mvc:interceptors>

/**表示拦截所有请求,/login和/static/**放行登录接口和静态资源。这里有个很容易踩到的坑:exclude 没配静态资源,导致登录页的 CSS、JS 全被拦截器挡住,页面看起来完全没样式,还以为是浏览器缓存问题。拿到项目后先看拦截器配置了哪些放行路径,比在页面上猜原因高效得多。

4. 本地跑通全流程:从环境选型到 war 包部署

4.1 环境选型:JDK 1.8 + Tomcat 8.5 + MySQL 5.7/8.0 是少走弯路组合

SSM + JSP 是十年前开始流行的技术栈,到了今天,环境版本就成了第一个分水岭。用太新的 JDK 和 Tomcat,老项目分分钟编译不过;用太老的数据库,新驱动又不兼容。推荐组合先列成表:

组件推荐版本说明
JDK1.8(8u202+)SSM 项目最稳的编译运行环境
Tomcat8.5.x 或 9.0.x兼容 Servlet 3.1,JSP 渲染无压力
MySQL5.7 或 8.05.7 最省心,8.0 需配 cj 驱动
Maven3.6.x与 JDK 1.8 兼容最好
IDEA2020 之后任一版本主要用来编辑和调试

不要拿 JDK 17 去跑老 SSM 项目,常见的 cglib 代理、旧版本 Spring 在 JDK 9+ 会出现模块访问限制,报错信息对新手极不友好。Tomcat 10 也要避开,它把 Servlet 的包名从 javax 改成了 jakarta,SSM 项目的依赖还是 javax,部署上去直接 ClassNotFoundException。

MySQL 在 Windows 上最常见的安装方式是下载 zip 免安装版,这正是网上一搜“mysql8.0 zip windows10 安装教程”频出的大坑来源。zip 包解压后没有安装程序,要手动初始化服务,步骤比较多,但可控性比 exe 安装版强,重装也方便。

4.2 初始化 MySQL 8 zip 免安装版并导入数据库

MySQL 8 的 zip 免安装版初始化,核心就三步:生成 data 目录、注册 Windows 服务、启动并改密码。用管理员身份打开 cmd,进入 MySQL 解压目录的 bin 文件夹,执行:

# 初始化数据目录,生成一个空密码的 root 用户 mysqld --initialize-insecure --basedir="D:\mysql-8.0.31-winx64" --datadir="D:\mysql-8.0.31-winx64\data" # 注册成 Windows 服务,下次开机自动启动 mysqld --install mysql8 # 启动 MySQL 服务 net start mysql # 空密码登录 mysql -uroot

--initialize-insecure是 MySQL 8 的初始化参数,它生成 data 目录同时把 root 初始密码设为空;如果用了--initialize(不带 insecure),会生成一串随机密码,藏在 data 目录的 .err 日志文件里,翻起来很费劲。注意初始化命令只能执行一次,data 目录已经存在时会直接报错。路径里的反斜杠要用双引号包住,路径带空格或中文容易让命令解析失败。登录进去之后立刻改密码:

ALTER USER 'root'@'localhost' IDENTIFIED BY '你的密码'; FLUSH PRIVILEGES;

密码不要用太复杂的特殊字符,尤其是 &、单引号,后面写进 jdbc.properties 和 URL 时会牵连出一堆转义问题。改完密码退出,用新密码试一次连接确认没问题,再导入项目自带的数据库脚本:

mysql -uroot -p你的密码 -e "CREATE DATABASE baihuo DEFAULT CHARACTER SET utf8mb4;" mysql -uroot -p你的密码 baihuo < database\init.sql

导入时如果报错说表已存在,说明脚本里带了 CREATE DATABASE,或者上次导过一部分数据。最省事的做法是把脚本文件打开,确认它到底建了哪些库,避免重复建表报错。字符集指定 utf8mb4 而不是 utf8,因为 utf8 在 MySQL 里存不了 emoji 和部分生僻字,老脚本里经常埋这个雷。

4.3 IDEA 导入项目并修改 jdbc.properties:四个参数一个都不能少

IDEA 里导入 SSM 项目,推荐直接选 pom.xml 而不是选文件夹,这样 Maven 能按依赖树把项目结构拉起来。导入后等右下角索引跑完,先别急着启动,先把 jdbc.properties 改掉:

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

这四行参数里,driver 必须是com.mysql.cj.jdbc.Driver,这是 MySQL 8 的官方驱动类;URL 里的 useSSL=false 是为了跳过 SSL 握手检查,否则控制台会刷一堆警告;allowPublicKeyRetrieval=true 专门解决 MySQL 8 的 caching_sha2_password 认证插件导致连接失败的问题;serverTimezone=Asia/Shanghai 不写的话,驱动会把本地时区当成 UTC,查出来的时间会差八个小时。这四个参数少一个,启动时都可能碰到莫名其妙的连接报错。

如果 Maven 下载依赖慢到无法忍受,打开 Maven 安装目录下 conf/settings.xml,在 mirrors 节点里加阿里云镜像:

<mirror> <id>aliyunmaven</id> <mirrorOf>central</mirrorOf> <url>https://maven.aliyun.com/repository/public</url> </mirror>

配好之后,pom.xml 里的依赖会从阿里云镜像拉取,下载速度有肉眼可见的差别。这里的坑是 settings.xml 有两个,Maven 安装目录一份,用户目录 .m2 下一份,IDEA 默认用的是用户目录那份,改错了地方等于白改。

4.4 打包 war 并部署到 Tomcat:命令行的方式看日志最清楚

首次跑通这类项目,建议不要直接依赖 IDEA 的启动按钮,而是用命令行打包部署。原因很简单,IDEA 启动失败时的控制台输出是截断的,而 Tomcat 的 catalina.out 日志完整得多,能看清是哪一行配置出了问题。先执行 Maven 打包:

mvn clean package -DskipTests # 查看打包产物 ls -lh target/*.war # 把 war 复制到 Tomcat 的 webapps 目录 cp target/ssm685.war D:\apache-tomcat-8.5.100\webapps\ # 启动 Tomcat D:\apache-tomcat-8.5.100\bin\startup.bat # 实时看日志,确认启动过程 tail -f D:\apache-tomcat-8.5.100\logs\catalina.out

war 直接放进 webapps 目录,Tomcat 启动时会自动解压并部署,这是传统 JSP 项目打包 war 后的标准动作。启动日志里看到Deployment of web application archive [ssm685.war] has finished就算部署成功。访问路径要注意,war 包文件名默认就是 context path,ssm685.war对应http://localhost:8080/ssm685/;如果把 war 改名成 ROOT.war,访问根路径就是http://localhost:8080/。这个 context path 的差异,是很多新手卡在“明明启动了却打不开”的第一个原因。

8080 端口被占用的处理也属于必踩坑之一。Windows 下执行netstat -ano | findstr 8080找到占用进程 PID,再用taskkill /f /pid 进程号结束它。改端口也是一种思路,编辑 Tomcat 的 conf/server.xml,把 Connector 的 port 改成 8081,但要记得把访问 URL 里的端口同步改掉,不然又会陷入“为什么 Tomcat 起不来”的迷惑里。

5. SSM 项目启动与运行排查:五个高频坑的现象、原因与处理

5.1 Tomcat 启动即报 ClassNotFoundException:缺依赖还是没打进 war 包

现象:Tomcat 启动后访问页面,控制台抛ClassNotFoundException: org.springframework.web.context.ContextLoaderListener,或者后台日志里出现 NoClassDefFoundError。原因:项目依赖不在运行时类路径里。用 IDEA 直接跑的时候,依赖由 IDE 加到 classpath;但部署到独立 Tomcat 时,依赖必须打包进 war 的 WEB-INF/lib 目录。如果 pom.xml 里没有<packaging>war</packaging>,打出来的包格式就是错的。

解决:先用打包产物验证依赖到底在不在:

jar tf target/ssm685.war | grep spring-webmvc

如果这条命令查不到 spring-webmvc 的 jar,说明依赖没进包。检查 pom.xml 的 packaging 是不是 war,再执行mvn clean package -DskipTests重新打包。另外注意 scope 为 provided 的依赖不会进 war,比如 servlet-api,这类 jar 由 Tomcat 自己提供,不需要也不应该打包。

5.2 数据库连不上:Communications link failure 与密码特殊字符

现象:项目启动时日志报Communications link failure,或直接Access denied for user 'root'@'localhost'。原因分为两类:一类是 MySQL 8 驱动与 URL 参数不匹配,导致握手阶段就失败;另一类是密码里有特殊字符,比如 &、%、#,在 properties 文件或 XML 解析时被转义,实际连库用的密码已经不是你以为的那个。

解决:把 jdbc.properties 的 URL 补全参数,useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&characterEncoding=utf8,驱动换成com.mysql.cj.jdbc.Driver;密码有特殊字符的,优先在 MySQL 里改成一个纯字母数字密码,别跟转义规则较劲。如果连接配置写在 XML 里而不是 properties 里,URL 中的&必须写成&amp;,否则 XML 解析直接报错,项目都起不来。

5.3 登录成功跳转 404:视图解析器的前缀与实际路径对不上

现象:登录页能打开,输入账号密码后页面跳到/index,结果返回 404,地址栏 URL 看着没错,就是没内容。原因:Controller 返回的逻辑视图名和 InternalResourceViewResolver 拼出来的物理路径不存在。比如视图解析器配置了 prefix=/WEB-INF/jsp/,但项目里 JSP 实际放在webapp/pages/下,拼出来的路径根本找不到文件。

解决:打开配置文件确认 prefix 和 suffix,再打开 webapp 目录看 JSP 实际位置。路径对不上的,要么改配置,要么把 JSP 移动过去。还要注意 Controller 的@RequestMapping和方法返回值大小写,Linux 上部署时路径大小写敏感,goods/list和Goods/list是两个完全不同的路径,Windows 本地跑得好不代表服务器上没问题。

5.4 一调接口就报 Invalid bound statement:Mapper XML 没被识别

现象:登录正常,页面也打开了,但点“商品列表”后后台抛Invalid bound statement (not found): com.demo.dao.GoodsDao.listGoods。原因:MyBatis 的 Mapper 接口和 XML 映射没有正确绑定。最常见两种:namespace 跟接口全限定名不一致,或者 mapperLocations 路径没扫到 XML 文件。接口编译成 class 后,MyBatis 靠 namespace 找 XML,NameSpace 错了就找不到 SQL。

解决:打开 Mapper XML 检查头部:

<mapper namespace="com.demo.dao.GoodsDao"> <select id="listGoods" resultType="com.demo.entity.Goods"> SELECT * FROM goods </select> </mapper>

namespace 必须和 DAO 接口全限定名完全一致,select 的 id 必须和接口方法名完全一致,resultType 可以改成 resultMap,但如果不建 resultMap 就保持实体类全限定名。同时确认 spring-mybatis.xml 里的 mapperLocations 写的是classpath:mapper/*.xml,而且 resources/mapper 目录下真的有文件。还有一种隐蔽情况:DAO 方法加了@Param注解但 XML 里没对应#{参数名},或者 XML 里的parameterType写错,也会报类似错误。

5.5 zip 解压要密码或提示损坏:伪加密和第二次压缩惹的祸

现象:从下载站拿到的 zip 双击时提示输入密码,分享页却没给;或者解压到一半报“CRC 失败”“文件头损坏”。原因:分享者打包时用了带密码的压缩工具,或者网盘二次压缩时给 zip 加上了伪加密标记。伪加密的实际表现是文件头里有一个加密标志位,但数据本身并没有真正加密,只是解压软件看到标志位就要密码。

解决:先确认是不是伪加密,用 7-Zip 打开压缩包,如果能看到文件名列表但提取时要求密码,试着直接拖拽文件到文件夹,部分伪加密包能绕过。WinRAR 则可以用“工具 → 修复压缩文件”重新生成一个可解压的副本。命令行下也可以强行指定空密码尝试:

unzip -P "" ssm685百货中心供应链管理系统+jsp-lw.zip

如果确实是真加密且没有密码,这个包基本可以放弃了,找分享者重新要一份才是正路。压缩包里的文件如果用 Windows 自带工具解压时中文文件名乱码,优先用 7-Zip 并设置 UTF-8 编码名,能避免解压后一堆看不懂的目录结构。这类 zip 本身的问题,跟项目代码质量无关,但卡在这一步会让人误以为包里的代码有问题,先排除压缩包层面的故障再去碰 Java 配置。

6. 二次开发前先做一遍验收:验证会话与部署边界的两个技巧

先别急着加功能,跑通之后先做一遍“业务闭环验收”:用管理员账号登录系统,按“建商品 → 建供应商 → 建采购单 → 入库 → 建销售单 → 出库”走一遍,每一步之后查一次数据库对应表。这是检验项目是否值得二次开发的最快方法,如果某一步的数据没落库,说明这个环节的逻辑是断的,后期扩展等于在流沙上盖楼。

会话验证可以用命令行做,不依赖页面,适合快速判断登录和拦截器是否正常:

# 登录并保存会话 cookie curl -c cookies.txt -d "username=admin&password=123456" http://localhost:8080/ssm685/login # 携带 cookie 访问商品列表页面 curl -b cookies.txt http://localhost:8080/ssm685/goods/list

如果第二个请求返回的是完整的 HTML 而不是重定向到登录页,说明登录会话生效;如果返回 302 跳到登录页,问题大概率在 session 存储或拦截器的放行路径上。这种黑匣子验证法,比打开浏览器反复刷新要快得多。

最后提一个部署层面的边界:JSP 项目能不能直接用 Nginx?本身不行,JSP 页面必须经过 Tomcat 的 JspServlet 渲染才能产生 HTML,Nginx 只能做反向代理转发请求。典型配置是:

server { listen 80; server_name demo.example.com; location /ssm685/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }

注意 proxy_pass 后面只写到http://127.0.0.1:8080,不要带/ssm685/后缀,否则 Nginx 会把路径拼接成/ssm685/ssm685/xxx,又变成一个 404 的深坑。把 war 改名成 ROOT.war 后,location / 直接反代就能让访问路径变成根路径,省得带一串 context path。我自己的习惯是每次接手这种老项目,先把环境版本写进 README 里,免得过两个月再看时又试错一遍。希望帮到你。

本文还有配套的精品资源,点击获取

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

OpenCV交通路口红绿灯控制系统:HSV识别与状态机实战解析

简介&#xff1a;一套基于Python和OpenCV的交通路口红绿灯控制系统源码&#xff0c;面向计算机视觉初学者及需要实战项目的开发者&#xff0c;也可作为课程设计或毕业设计的参考。资源以完整工程形式组织&#xff0c;压缩包共三十四个文件&#xff0c;主体为py脚本&#xff0c;…

作者头像 李华
网站建设 2026/9/28 13:14:15

1515张YOLO人脸检测冷启动数据集face.zip实战指南

简介&#xff1a;本资源是一套专为YOLO系列目标检测算法&#xff08;包括YOLOv5/v7/v8/v9/v10/v11&#xff09;优化的人脸检测训练数据集&#xff0c;面向计算机视觉初学者、算法工程师及模型调优实践者&#xff0c;解决人脸检测任务中高质量标注数据匮乏、格式适配繁琐等实际问…

作者头像 李华
网站建设 2026/9/28 13:14:04

PostgreSQL连接从入门到排障:报错分析与连接池实践

装好PostgreSQL之后&#xff0c;第一件让人血压升高的事就是"连不上"。我这些年帮人排过太多这种问题&#xff1a;明明安装顺利、服务也在跑&#xff0c;但客户端就是报错&#xff0c;一会儿"password authentication failed"&#xff0c;一会儿"Conn…

作者头像 李华
网站建设 2026/9/28 13:13:05

AO3401软启动设计:MOS管电源开关的生存必修课

1. 为什么软启动不是“可选项”&#xff0c;而是MOS管开关电路的生存底线我第一次把AO3401直接焊进电源通路时&#xff0c;板子刚上电就冒烟——不是芯片烧了&#xff0c;是后级的电解电容鼓包了。当时以为是接反了&#xff0c;反复核对原理图&#xff0c;最后发现根本问题出在…

作者头像 李华
网站建设 2026/9/28 13:12:46

ESP-01s供电不稳定根源与三种实战解决方案

1. 为什么ESP-01s总在半夜掉线&#xff1f;——供电不足不是玄学&#xff0c;是电路设计的硬伤你拆开那个刚买的温湿度监测盒子&#xff0c;焊上杜邦线&#xff0c;烧录完固件&#xff0c;满怀期待地按下复位键——LED闪了两下&#xff0c;串口打印出“Connecting...”&#xf…

作者头像 李华
网站建设 2026/9/28 13:11:13

Go实现MCP只读服务:让Claude Code安全查询GaussDB生产库

1. 为什么我要给 Claude Code 配一个只读的 GaussDB 通道先说结论&#xff1a;我写了一个用 Go 实现的 MCP 服务&#xff0c;把 GaussDB 的查询能力以只读的方式暴露给 Claude Code。它解决的核心问题很具体——我想让 AI 帮我查生产库的数据、分析表结构、定位慢查询&#xff…

作者头像 李华