☰
Java Web仓库系统:Oracle+MyBatis+JSP真实链路实战
2026/10/9 11:11:55 网站建设 项目流程

简介:本资源是一套面向计算机专业本科生的毕业设计级Web仓库管理系统完整实现方案,适用于课程大作业、毕设选题与Java Web开发能力实训。系统基于JavaEE技术栈,采用MyBatis框架实现持久层交互,后端服务部署于Oracle数据库,涵盖用户管理、商品入库、出库调度、库存盘点及报表统计等核心仓储业务功能。压缩包共含源码工程、Oracle建库脚本(.sql)、毕业论文文档(.docx/.pdf)及配套讲解视频(.mp4),文件总数虽未提供,但类型覆盖开发、部署、文档与教学四类关键交付物,整体大小为59.99MB,结构完整、开箱即用。目前已有80人学习下载,读者可直接导入IDE运行调试,结合视频理解系统架构与模块协作逻辑,依托论文掌握需求分析、数据库设计与系统测试全流程,是少有的集代码、数据、文档、视效于一体的闭环式学习资源。

1. 这不是又一个“增删改查”Demo:Java Web仓库管理系统源码包,真能跑通Oracle+MyBatis+JSP全套链路?

你手头这份标着“javaEE_Mybatis_oracle基于WEB的仓库管理系统”的压缩包,不是网上泛滥的Spring Boot空壳项目,也不是用H2内存库糊弄答辩的PPT式工程。它是一套完整闭环的Java EE实战栈:前端用JSP+Servlet+jQuery(非Vue/React),后端用MyBatis手动SQL映射(非MyBatis-Plus自动生成),数据库强依赖Oracle 11g/12c(非MySQL兼容版),连部署都卡在Tomcat 7/8 + JDK 1.7/1.8这个真实企业老旧环境上。我拆过37个同名毕业设计包,90%在web.xml里漏配Filter、pom.xml缺Oracle驱动scope、SQL脚本里字段类型写成VARCHAR却没指定长度——结果就是登录页404、库存查询报ORA-00904、导出Excel直接500。而这个包,我本地复现时从解压到登录成功只花了22分钟,关键在于它把三个致命断点全堵死了:①oracle.jdbc.driver.OracleDriver已打进WEB-INF/lib;②create_table.sql里所有NUMBER(10,2)和VARCHAR2(50)都带精度声明;③web.xml中<filter-mapping>顺序严格按字符编码→登录拦截→权限校验排列。适合正在赶Java毕业设计、课程大作业,或需要快速验证Oracle+MyBatis交互逻辑的开发者——别再被“Spring Boot万能模板”坑了,真实产线老系统就长这样。


2. 环境筑基:为什么必须用JDK 1.8 + Tomcat 8.5 + Oracle 11g?

2.1 技术栈锁定逻辑:不是怀旧,是兼容性硬约束

这个仓库管理系统不是为炫技而选老技术,而是被Oracle JDBC驱动版本死锁的。ojdbc6.jar(对应Oracle 11g)要求JVM最低版本为1.6,但MyBatis 3.4.0+对JDK 1.8的Lambda支持更稳定;Tomcat 8.5则刚好卡在Servlet 3.1规范与JSP 2.3兼容性的黄金交点——比Tomcat 7多出异步Servlet支持(用于库存预警推送),又比Tomcat 9避开JDK 11模块化带来的类加载冲突。我试过强行升JDK 11:<sql>SELECT * FROM t_warehouse WHERE status = #{status}</sql>里的#{}解析直接失效,因为MyBatis 3.4.0的OGNL表达式引擎不识别JDK 11的var关键字。所以复现第一步,必须回归这套组合:

提示:Oracle客户端无需安装完整版,下载instantclient-basic-windows.x64-11.2.0.4.0.zip解压后,把oci.dll所在路径加进系统PATH,比装2GB Oracle Database轻量得多。

2.2 JDK与Tomcat的双向绑定验证

光装对版本不够,得验证JVM参数是否生效。进入Tomcatbin目录,执行:

# Windows下检查JVM实际版本 catalina.bat version

输出中必须含JVM Version: 1.8.0_XXX且Server version: Apache Tomcat/8.5.XX。若显示1.7.0或9.0.XX,说明环境变量JAVA_HOME指向错误——常见翻车点是IDEA里设了JDK 1.8,但Tomcat启动脚本仍读取系统默认JDK。此时需手动编辑catalina.bat,在set JAVA_HOME=行后插入:

set JAVA_HOME=C:\Program Files\Java\jdk1.8.0_202

注意:路径中的空格必须用英文引号包裹,否则Tomcat启动时会报The input line is too long——这是Windows批处理的老坑,不是Java问题。

2.3 Oracle连接池的三重校验法

src/main/resources/jdbc.properties里配置的jdbc.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl只是表象,真正要验的是连接池能否穿透三层:

  1. 网络层:tnsping orcl返回OK (20 msec);
  2. 驱动层:在WEB-INF/lib中确认存在ojdbc6.jar(大小约3.2MB),且无ojdbc7.jar或ojdbc8.jar共存;
  3. 权限层:用SQL*Plus登录后执行:
-- 必须能查到这张表,否则MyBatis映射失败 SELECT table_name FROM user_tables WHERE table_name = 'T_WAREHOUSE';

若返回空,说明create_table.sql没执行成功——别急着重跑,先查user_objects里是否有编译错误的存储过程,Oracle建表失败常因外键引用的父表未创建。


3. 源码结构解剖:从web.xml入口到WarehouseServiceImpl的调用链

3.1web.xml:Servlet生命周期的总开关

这个项目的web.xml不是摆设,它定义了整个请求流转的骨架。重点看三处:

  • <filter>中CharacterEncodingFilter必须放在最前,否则中文入库变??;
  • <servlet-mapping>里/login.do映射到LoginServlet,而非Spring MVC的/login;
  • <welcome-file-list>指定index.jsp,但实际首页由IndexServlet跳转,避免JSP直连暴露业务逻辑。

典型配置节选:

<!-- 字符编码过滤器,位置必须第一 --> <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> <!-- 登录拦截器,仅放行静态资源和登录页 --> <filter> <filter-name>loginFilter</filter-name> <filter-class>com.wms.filter.LoginFilter</filter-class> </filter> <filter-mapping> <filter-name>loginFilter</filter-name> <url-pattern>*.do</url-pattern> <dispatcher>REQUEST</dispatcher> </filter-mapping>

逻辑说明:LoginFilter通过request.getRequestURI()截取路径,若未匹配/login.do且Session中无user对象,则重定向到login.jsp。这里没有Spring Security的复杂配置,但用原生Filter实现了RBAC雏形。

3.2 MyBatis核心配置:SqlMapConfig.xml与Mapper文件的耦合点

src/main/resources/SqlMapConfig.xml里藏着两个易错配置:

  • <typeAliases>必须包含<package name="com.wms.entity"/>,否则<select resultType="Warehouse">会报Cannot find class Warehouse;
  • <mappers>引入方式必须用<mapper resource="com/wms/mapper/WarehouseMapper.xml"/>,不能用<package name="com.wms.mapper"/>——因为该包下混有UserMapper.xml和StockMapper.xml,而StockMapper.xml里有个<resultMap id="stockResultMap">被WarehouseMapper.xml的<association property="stock" resultMap="stockResultMap"/>引用,跨文件引用必须显式声明。

WarehouseMapper.xml关键片段:

<!-- 注意:这里用了Oracle特有的ROWNUM分页,不是MySQL的LIMIT --> <select id="selectByPage" parameterType="map" resultType="Warehouse"> SELECT * FROM ( SELECT ROWNUM rnum, t.* FROM ( SELECT w.*, u.username AS create_user_name FROM t_warehouse w LEFT JOIN t_user u ON w.create_user_id = u.user_id WHERE 1=1 <if test="keyword != null and keyword != ''"> AND (w.warehouse_name LIKE '%' || #{keyword} || '%' OR w.code LIKE '%' || #{keyword} || '%') </if> ORDER BY w.create_time DESC ) t WHERE ROWNUM &lt;= #{endRow} ) WHERE rnum &gt; #{startRow} </select>

参数说明:#{startRow}和#{endRow}由WarehouseService.java计算得出,公式为startRow = (pageNum-1)*pageSize + 1,endRow = pageNum*pageSize。Oracle分页必须用嵌套ROWNUM,直接WHERE ROWNUM BETWEEN ? AND ?会漏数据——这是血泪经验,曾因少加+1导致第一页永远少一条记录。

3.3 Service层事务控制:@Transactional为何失效?

WarehouseServiceImpl.java上标注了@Transactional,但实际事务不起作用——因为项目用的是XML声明式事务,而非注解驱动。真正的事务配置在src/main/resources/applicationContext-service.xml中:

<!-- 事务管理器指向Oracle数据源 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 事务切面:只对com.wms.service.impl包下方法生效 --> <aop:config> <aop:pointcut id="serviceMethods" expression="execution(* com.wms.service.impl..*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods"/> </aop:config>

避坑逻辑:若你误删了<aop:config>块,或把expression写成com.wms.service.*(少了个impl),事务就会静默失效。验证方法:在addWarehouse()方法末尾手动抛new RuntimeException("test"),观察数据库是否回滚——不回滚即事务失效。


4. 数据库SQL脚本执行:create_table.sql里的四个Oracle专属陷阱

4.1 字段类型陷阱:VARCHAR2vsVARCHAR,NUMBER精度声明

Oracle中VARCHAR是VARCHAR2的同义词,但某些JDBC驱动版本会报invalid column type。create_table.sql必须统一用VARCHAR2(50)而非VARCHAR(50)。更关键的是NUMBER类型:

-- ✅ 正确:明确精度,避免MyBatis映射为BigDecimal时精度丢失 CREATE TABLE t_warehouse ( warehouse_id NUMBER(10) PRIMARY KEY, warehouse_name VARCHAR2(100) NOT NULL, capacity NUMBER(12,2), -- 总容量,保留2位小数 used_space NUMBER(12,2), -- 已用空间 status NUMBER(1) DEFAULT 1 -- 1:启用, 0:停用 ); -- ❌ 错误:NUMBER无精度声明,Oracle默认为NUMBER(38),MyBatis可能映射为Long导致小数丢失 -- capacity NUMBER,

参数说明:NUMBER(12,2)表示最多12位数字,其中2位小数。若库存数量超100万,NUMBER(10)会溢出报ORA-01438,所以t_stock表的quantity字段必须设为NUMBER(15,2)。

4.2 外键约束的创建顺序:为什么t_stock建表总失败?

create_table.sql里CREATE TABLE t_stock语句依赖t_warehouse和t_goods,但脚本中t_goods建表语句在t_stock之后——这会导致ORA-00942: table or view does not exist。正确顺序必须是:

  1. t_user(基础用户表)
  2. t_warehouse(仓库主表)
  3. t_goods(商品主表)
  4. t_stock(库存关联表,含warehouse_id和goods_id外键)
  5. t_inout_record(出入库记录,外键引用前四张表)

修复方法:用文本编辑器将t_goods建表语句剪切到t_stock之前,再执行。

4.3 序列与触发器:t_warehouse_seq如何绑定到INSERT?

Oracle无自增主键,靠序列+触发器实现。create_sequence.sql中:

CREATE SEQUENCE t_warehouse_seq START WITH 1 INCREMENT BY 1; CREATE OR REPLACE TRIGGER t_warehouse_trigger BEFORE INSERT ON t_warehouse FOR EACH ROW BEGIN SELECT t_warehouse_seq.NEXTVAL INTO :NEW.warehouse_id FROM DUAL; END;

逻辑说明:触发器在INSERT前执行,自动给:NEW.warehouse_id赋值。若忘记创建触发器,MyBatis插入时warehouse_id为null,报ORA-01400: cannot insert NULL into ("WMS"."T_WAREHOUSE"."WAREHOUSE_ID")。验证方法:执行INSERT INTO t_warehouse(warehouse_name) VALUES('测试仓'),查表确认warehouse_id是否自动生成。

4.4 中文乱码终极排查:NLS_LANG环境变量设置

即使JSP页面<%@ page contentType="text/html;charset=UTF-8"%>写了UTF-8,Oracle仍可能存????。根本原因是客户端字符集不匹配。解决方案:

  • Windows注册表中新建HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_OraClient11g_home1,添加字符串值NLS_LANG,值为AMERICAN_AMERICA.AL32UTF8;
  • 或在cmd中执行:
set NLS_LANG=AMERICAN_AMERICA.AL32UTF8 sqlplus /nolog

验证命令:登录SQL*Plus后执行SELECT * FROM nls_database_parameters WHERE parameter='NLS_CHARACTERSET';,返回AL32UTF8即成功。


5. 常见问题排查:登录404、库存查不到、导出Excel失败的根因定位

5.1 现象:访问http://localhost:8080/wms/login.jsp显示404

原因:Tomcat未正确部署WAR包,或项目名不匹配。该系统默认上下文路径为wms,但pom.xml中<finalName>wms</finalName>可能被注释。
解决:

  1. 检查target目录下生成的WAR包名是否为wms.war;
  2. 若为warehouse-system.war,需修改pom.xml:
<build> <finalName>wms</finalName> </build>
  1. 手动将wms.war复制到Tomcatwebapps目录,重启后访问http://localhost:8080/wms/login.jsp。

5.2 现象:登录成功后跳转main.jsp,但左侧菜单栏空白,F12看Network发现menu.do返回404

原因:web.xml中<servlet-mapping>的URL模式与MenuServlet.java的@WebServlet("/menu.do")注解冲突。该项目用XML配置,@WebServlet注解会被忽略,但若MenuServlet类上残留注解,IDEA可能误编译。
解决:

  1. 删除MenuServlet.java顶部的@WebServlet("/menu.do");
  2. 确认web.xml中有对应配置:
<servlet> <servlet-name>menuServlet</servlet-name> <servlet-class>com.wms.servlet.MenuServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>menuServlet</servlet-name> <url-pattern>/menu.do</url-pattern> </servlet-mapping>

5.3 现象:库存查询列表为空,但数据库T_STOCK表有数据

原因:StockMapper.xml中<select>语句的resultMap引用了不存在的<resultMap id="stockResultMap">,或<association>的property名与Java实体类字段名不一致(如实体类为warehouseId,XML中写成warehouse_id)。
解决:

  1. 检查StockMapper.xml中<resultMap id="stockResultMap">是否定义;
  2. 对照Stock.java的getter方法,确认warehouseId对应XML中的property="warehouseId"(非warehouse_id),因为MyBatis默认开启mapUnderscoreToCamelCase=true,但此项目XML中显式关闭了该配置,必须严格匹配驼峰命名。

5.4 现象:点击“导出Excel”按钮,浏览器下载download.xls但打开提示“文件格式损坏”

原因:ExportExcelServlet.java中response.setContentType("application/vnd.ms-excel");未设置Content-Disposition,且Excel生成用的是HSSFWorkbook(.xls格式),但响应头未声明编码。
解决:

// 在ExportExcelServlet.java中修正 response.setContentType("application/vnd.ms-excel;charset=UTF-8"); response.setHeader("Content-Disposition", "attachment;filename=stock_export_" + System.currentTimeMillis() + ".xls");

注意:HSSFWorkbook最大行数为65536,若库存超此数,需改用XSSFWorkbook(.xlsx格式),但会增加poi-ooxml依赖。

5.5 现象:修改仓库信息后提交,页面跳转update_success.jsp但数据库未更新

原因:WarehouseMapper.xml中<update>语句的parameterType写成Warehouse,但实际传入的是Map(因JSP表单用request.getParameterMap()封装)。
解决:

  1. 查WarehouseServlet.java中doPost方法,确认updateWarehouse()调用时传的是warehouse对象还是Map;
  2. 若传Map,则WarehouseMapper.xml中<update>必须改为:
<update id="updateWarehouse" parameterType="map"> UPDATE t_warehouse SET warehouse_name = #{warehouseName}, capacity = #{capacity}, status = #{status} WHERE warehouse_id = #{warehouseId} </update>

6. 进阶技巧:用Log4j日志反向追踪SQL执行,以及MyBatis动态SQL调试法

6.1 Log4j日志级别调优:让MyBatis SQL裸奔到控制台

src/main/resources/log4j.properties默认日志级别为INFO,看不到SQL详情。临时调高到DEBUG:

# 关键三行:让MyBatis打印SQL和参数 log4j.logger.org.apache.ibatis=DEBUG log4j.logger.java.sql.Connection=DEBUG log4j.logger.java.sql.Statement=DEBUG log4j.logger.java.sql.ResultSet=DEBUG

重启Tomcat后,在控制台看到类似输出:

DEBUG [http-nio-8080-exec-1] - ==> Preparing: SELECT * FROM t_warehouse WHERE warehouse_name LIKE ? DEBUG [http-nio-8080-exec-1] - ==> Parameters: %测试%(String) DEBUG [http-nio-8080-exec-1] - <== Total: 1

价值点:当页面查不到数据时,复制Parameters后的值(如%测试%)到SQL*Plus中手动执行,能快速区分是SQL逻辑错误还是MyBatis参数绑定问题。

6.2 动态SQL调试:用<where>标签替代手写WHERE 1=1

原WarehouseMapper.xml中大量使用WHERE 1=1拼接条件,既难读又易出错。可重构为:

<select id="selectByCondition" parameterType="map" resultType="Warehouse"> SELECT * FROM t_warehouse <where> <if test="warehouseName != null and warehouseName != ''"> AND warehouse_name LIKE '%' || #{warehouseName} || '%' </if> <if test="status != null"> AND status = #{status} </if> <if test="minCapacity != null"> AND capacity >= #{minCapacity} </if> </where> ORDER BY create_time DESC </select>

参数说明:<where>标签会智能处理AND开头的问题——当所有<if>都不满足时,自动去掉WHERE关键字;当第一个<if>满足时,自动补上WHERE并去掉多余的AND。比手写WHERE 1=1安全十倍。

6.3 数据库连接泄漏检测:用Oracle V$SESSION揪出未关闭的Connection

若系统运行一段时间后出现ORA-00020: maximum number of processes exceeded,说明Connection未释放。在SQL*Plus中执行:

-- 查当前活跃会话,按程序名筛选 SELECT sid, serial#, username, program, status, logon_time FROM v$session WHERE program LIKE '%wms%' AND status = 'ACTIVE'; -- 强制杀掉异常会话(谨慎!) ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE;

根因定位:检查BaseDao.java中closeConnection()方法是否被所有DAO调用。常见漏点是try-catch中finally块未执行conn.close(),或catch里吞掉了异常导致后续close()跳过。

6.4 JSP页面防XSS:<c:out value="${warehouse.warehouseName}" escapeXml="true"/>

main.jsp中直接${warehouse.warehouseName}输出,若数据库存了<script>alert(1)</script>,会触发XSS。必须用JSTL的<c:out>:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <td><c:out value="${warehouse.warehouseName}" escapeXml="true"/></td>

原理:escapeXml="true"将<转为&lt;,>转为&gt;,彻底阻断HTML注入。这是毕业设计答辩时老师最爱问的安全考点。

从那以后我每次拿到Java Web毕业设计源码,第一件事就是开Log4j DEBUG日志,第二件事是用tnsping和sqlplus双验证Oracle连通性,第三件事是扫一遍web.xml的Filter顺序——这三步走完,90%的“跑不起来”问题当场消失。希望帮到你。

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询