网上购物系统 jsp+mysql+tomcat 环境搭建与源码运行指南
2026/9/23 12:33:50 网站建设 项目流程

简介:这是一份面向Java Web初学者与电商系统开发练习者的完整网上购物系统源码,采用JSP+MySQL+Tomcat技术栈实现,适合用于课程设计、毕业设计参考或Java Web入门实战。压缩包共787个文件,约11.02MB,包含75个java源文件与75个class编译文件、63个jsp页面、38个jar依赖包、31个xml配置及20个css样式文件,另有gif、jpg等图片素材与sql脚本,覆盖用户注册登录、商品分类展示与搜索、购物车增删改与总价计算、订单下单支付与状态管理、商品评论等核心模块,后端通过Servlet与JavaBean处理业务逻辑,MySQL负责数据存储,Tomcat承载页面与应用通信。已有113人学习下载,读者可借此理解Java Web开发流程、数据库表结构设计与前后端交互方式,积累电商项目实战经验与常见问题解决思路。

1. 网上购物系统 jsp+mysql+tomcat:一套能跑通的 JavaWeb 骨架长什么样

很多人搜「网上购物系统 jsp+mysql+tomcat」的时候,其实心里想的不是「我要做个淘宝」,而是「我手上有一份 java 源码,怎么让它在本地跑起来,顺便把 javaweb 这套东西弄明白」。这套组合是典型的 Model1/Model2 时代的 JavaWeb 技术栈:JSP 负责页面渲染,Servlet 或 JSP 自身处理请求,MySQL 存商品、用户、订单,Tomcat 当 Web 容器。它不新,但它是理解 javaweb 请求流转最直白的一条路——没有 Spring 的自动装配,没有 MyBatis 的映射黑盒,每个请求从浏览器到数据库再回来,链路是裸露的。

这篇文章面向三类人:一是拿到一份 java 课程设计案例源码、想跑通网上购物系统的学生;二是想用 jsp+mysql+tomcat 这套老组合复习 javaweb 基础、准备面试八股文的开发者;三是需要快速搭一个能演示「浏览商品→加购物车→下单」闭环的从业者。下面按「环境怎么搭→数据库怎么建→源码怎么读→坑在哪→怎么验证」的顺序推,每一步都落到能复现的命令和参数上。

2. 环境搭建:JDK、Tomcat、MySQL 三件套的版本对齐

2.1 为什么版本对齐比装最新版更重要

jsp+mysql+tomcat 这套组合翻车,十次里有六次不是代码问题,是版本没对齐。JSP 的编译依赖 JDK,Tomcat 的 Servlet 版本依赖 JDK 版本,MySQL 的驱动包版本又依赖 MySQL 服务端版本。常见做法是:JDK 用 8 或 11,Tomcat 用 8.5 或 9,MySQL 用 5.7 或 8.0,驱动包用 mysql-connector-java 5.1.x(配 5.7)或 8.0.x(配 8.0)。如果你拿到的源码里WEB-INF/lib下是mysql-connector-java-5.1.47.jar,那就别硬上 MySQL 8.0,否则连接时会报Unknown system variable 'query_cache_size'这类玄学错误。

我一般会先看源码的lib目录和web.xml里的servlet版本声明,再倒推该装哪个 Tomcat。web.xml里写version="3.1"就对应 Tomcat 8.5/9,写version="2.5"就对应 Tomcat 7 甚至更早。这一步花两分钟,能省后面两小时排错。

2.2 JDK 安装与环境变量配置

先确认本机有没有 JDK:

java -version javac -version

如果两条命令版本不一致,说明 PATH 里混了多个 JDK。Windows 下配置JAVA_HOME指向 JDK 根目录(不是 bin),再把%JAVA_HOME%\bin加到 PATH 最前面。Linux 下在/etc/profile里写:

export JAVA_HOME=/usr/local/jdk1.8.0_301 export PATH=$JAVA_HOME/bin:$PATH export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

JAVA_HOME是给 Tomcat 的启动脚本读的,Tomcat 的catalina.shcatalina.bat会用它找 JVM。CLASSPATH里的.表示当前目录,少了它编译时可能找不到同目录的类。改完source /etc/profileecho $JAVA_HOME验证。

2.3 Tomcat 安装与 IDEA 配置

Tomcat 解压即用,关键是conf/server.xml里的端口。默认 8080,如果被占用就改成 8081:

<Connector port="8081" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />

connectionTimeout是连接超时毫秒数,redirectPort是 HTTPS 跳转端口。改完启动:

# Linux ./bin/startup.sh # Windows bin\startup.bat

浏览器访问http://localhost:8081,看到 Tomcat 默认页就算通了。IDEA 里配置 Tomcat 的路径是 Run → Edit Configurations → + → Tomcat Server → Local,在 Server 选项卡里指定 Tomcat 安装目录,在 Deployment 选项卡里添加项目的 war 或 war exploded。注意:war exploded 支持热更新,调试阶段优先用它。

2.4 MySQL 安装与建库建表

MySQL 8.0 安装后先设 root 密码,然后建库:

CREATE DATABASE shop DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE shop;

utf8mb4utf8多支持 emoji 和部分生僻字,商品名里如果有特殊字符不会乱码。接着导入源码里的.sql文件:

mysql -u root -p shop < shop.sql

如果源码没带 sql 文件,就得自己根据实体类反推表结构。常见网上购物系统的表至少包括:user(用户)、product(商品)、category(分类)、cart(购物车)、orders(订单)、order_item(订单明细)。建表时主键用int AUTO_INCREMENT,金额字段用decimal(10,2)而不是float,否则算总价时会出现0.30000000000000004这种浮点误差。

3. 源码结构拆解:从 web.xml 到 DAO 的请求链路

3.1 先看 web.xml 和目录结构

拿到一份 jsp+mysql+tomcat 的 java 源码,别急着跑,先看目录:

src/ com/shop/dao/ # 数据库访问 com/shop/entity/ # 实体类 com/shop/servlet/ # 控制器 com/shop/util/ # 工具类,通常有 DBUtil WebContent/ 或 web/ WEB-INF/ web.xml lib/ index.jsp product.jsp cart.jsp

web.xml里注册了 Servlet 映射和过滤器。典型配置:

<servlet> <servlet-name>ProductServlet</servlet-name> <servlet-class>com.shop.servlet.ProductServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>ProductServlet</servlet-name> <url-pattern>/product</url-pattern> </servlet-mapping>

这段的意思是:浏览器请求/product时,Tomcat 把请求交给ProductServlet处理。url-pattern决定访问路径,改它就能改 URL。如果源码用的是注解@WebServlet("/product"),那web.xml里可能没有这段,两者选其一,同时存在会冲突。

3.2 DBUtil:数据库连接的黑匣子

DBUtil通常是全项目最该先读的类,因为连不上数据库后面全白搭。典型写法:

public class DBUtil { private static final String URL = "jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai"; private static final String USER = "root"; private static final String PASSWORD = "123456"; public static Connection getConnection() throws SQLException { try { Class.forName("com.mysql.cj.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } return DriverManager.getConnection(URL, USER, PASSWORD); } }

URL里的serverTimezone=Asia/Shanghai是 MySQL 8.0 必须的,不写会报时区错误。characterEncoding=utf8保证中文不乱码。Class.forName加载驱动,MySQL 8.0 用com.mysql.cj.jdbc.Driver,5.7 用com.mysql.jdbc.Driver,写错会报ClassNotFoundExceptionUSERPASSWORD要和你本机 MySQL 一致,这是最常见的翻车点——源码里写的是作者的密码,你得改成自己的。

3.3 一个完整的 Servlet 请求处理

以商品列表为例,看请求怎么流转:

@WebServlet("/product") public class ProductServlet extends HttpServlet { private ProductDao productDao = new ProductDao(); protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String categoryId = request.getParameter("categoryId"); List<Product> products; if (categoryId == null || categoryId.isEmpty()) { products = productDao.findAll(); } else { products = productDao.findByCategory(Integer.parseInt(categoryId)); } request.setAttribute("products", products); request.getRequestDispatcher("/product.jsp").forward(request, response); } }

doGet处理 GET 请求,request.getParameter取 URL 参数,productDao查数据库,setAttribute把结果放进请求域,forward转发到 JSP 渲染。注意forward是服务器内部跳转,浏览器地址栏不变;sendRedirect是让浏览器重新请求,地址栏会变。购物车增删一般用 redirect,避免刷新重复提交。

对应的product.jsp里用 JSTL 遍历:

<c:forEach items="${products}" var="p"> <div class="product"> <h3>${p.name}</h3> <p>价格:${p.price}</p> <a href="cart?action=add&id=${p.id}">加入购物车</a> </div> </c:forEach>

${products}取的就是 Servlet 里setAttribute放进去的。JSTL 需要在WEB-INF/lib下有jstl.jarstandard.jar,并在 JSP 顶部声明<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>,少一个都会报The absolute uri cannot be resolved

3.4 DAO 层与 SQL 参数

DAO 层负责拼 SQL,看一个查询:

public List<Product> findByCategory(int categoryId) { List<Product> list = new ArrayList<>(); String sql = "SELECT * FROM product WHERE category_id = ? ORDER BY id DESC"; try (Connection conn = DBUtil.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setInt(1, categoryId); ResultSet rs = ps.executeQuery(); while (rs.next()) { Product p = new Product(); p.setId(rs.getInt("id")); p.setName(rs.getString("name")); p.setPrice(rs.getBigDecimal("price")); list.add(p); } } catch (SQLException e) { e.printStackTrace(); } return list; }

PreparedStatement而不是Statement拼接,是为了防 SQL 注入。?是占位符,setInt(1, categoryId)把第一个问号替换成参数值。ORDER BY id DESC让新商品排前面。rs.getBigDecimal("price")对应实体类的BigDecimal字段,和数据库decimal类型匹配,别用getDouble

4. 避坑与排查:jsp+mysql+tomcat 最常见的 5 个翻车现场

4.1 现象:启动 Tomcat 报 404,访问任何页面都是空白

原因通常是项目没部署成功,或者web.xmlurl-pattern和访问路径不一致。先看 Tomcat 控制台有没有Deployment of web application archive ... has finished,没有就是 war 没打进去。再看 IDEA 的 Deployment 选项卡,Application context 是不是/,如果是/shop,那访问路径就得是http://localhost:8080/shop/product。解决:把 Application context 改成/,或者访问时带上 context 路径。

4.2 现象:页面中文乱码,数据库里存进去也是问号

原因有三层:JSP 页面编码、请求编码、数据库编码。JSP 顶部要写<%@ page contentType="text/html;charset=UTF-8" language="java" %>;POST 请求要在取参数前request.setCharacterEncoding("UTF-8");数据库连接 URL 要带characterEncoding=utf8;建库建表要用utf8mb4。四层缺一层就乱码。GET 请求的中文参数在 Tomcat 8 以后默认 UTF-8,但老版本要在server.xml的 Connector 里加URIEncoding="UTF-8"

4.3 现象:报No suitable driver found for jdbc:mysql://...

原因:驱动 jar 没放进WEB-INF/lib,或者放进去但没加到项目的 classpath。IDEA 里要在 Project Structure → Modules → Dependencies 里确认mysql-connector-java在列。另一个原因是驱动类名写错,MySQL 8.0 必须用com.mysql.cj.jdbc.Driver,写成com.mysql.jdbc.Driver会报Loading class ... deprecated然后连接失败。解决:换驱动类名,或者把驱动 jar 换成 5.1.x 配 5.7。

4.4 现象:购物车加不进去,或者刷新后数量翻倍

原因:加购物车用了 forward 而不是 redirect,刷新页面时浏览器重复提交上一次请求。解决:加购、删除、下单这类写操作,处理完用response.sendRedirect("cart")跳回列表页,让浏览器重新发 GET 请求。另外购物车如果存在 session 里,要注意 session 超时时间,web.xml<session-config><session-timeout>30</session-timeout></session-config>是 30 分钟,太短会导致用户还没下单 session 就没了。

4.5 现象:MySQL 8.0 连接报Public Key Retrieval is not allowed

原因:MySQL 8.0 默认用caching_sha2_password认证插件,JDBC 连接时如果不允许公钥检索就会报这个。解决:在连接 URL 后面加allowPublicKeyRetrieval=true&useSSL=false。完整 URL 变成:

jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false

useSSL=false是本地开发关掉 SSL,生产环境别这么干。或者改 MySQL 用户认证插件:ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '123456';,但这样安全性降低,本地开发图省事可以用。

5. 验证与进阶:怎么确认这套系统真的跑通了

5.1 用一条 SQL 验证数据库连通性

在写 Java 代码之前,先用命令行确认数据库能连、表能查:

SELECT COUNT(*) FROM product; SELECT p.name, c.name AS category FROM product p LEFT JOIN category c ON p.category_id = c.id WHERE p.price > 100 ORDER BY p.price DESC;

第一条确认商品表有数据,第二条验证关联查询和排序。如果这两条在 MySQL 客户端里跑不通,Java 里更跑不通。LEFT JOIN保证没有分类的商品也能查出来,ORDER BY p.price DESC按价格降序。这一步能提前暴露表名写错、字段名写错、外键没建的问题。

5.2 用浏览器开发者工具看请求链路

系统跑起来后,按 F12 打开 Network 面板,点一次「加入购物车」,看请求:

检查项正常表现异常表现与含义
Request URLhttp://localhost:8080/cart?action=add&id=3路径少了 context 或参数没带上
Request MethodGET 或 POST写操作用 GET 容易被重复提交
Status Code302 后跟 200直接 500 说明 Servlet 抛异常
Response HeadersLocation: cart没有说明没 redirect
CookiesJSESSIONID没有说明 session 没建起来

302 是重定向状态码,浏览器收到后会再发一次请求到Location指定的地址。如果看到 500,去 Tomcat 控制台看堆栈,通常是空指针或 SQL 异常。JSESSIONID是 session 的标识,购物车数据靠它关联到具体用户,没有它购物车就是空的。

5.3 一个我常用的排查习惯

每次改完DBUtilweb.xml,我不会直接重启整个 Tomcat,而是先单独跑一个 JDBC 测试类:

public class TestConn { public static void main(String[] args) throws Exception { Connection conn = DBUtil.getConnection(); System.out.println("连接成功:" + conn.getMetaData().getURL()); conn.close(); } }

getMetaData().getURL()会打印实际连接的 URL,能确认参数有没有生效。这个习惯让我少走了很多弯路——很多次以为是 Servlet 写错了,其实是数据库根本没连上。jsp+mysql+tomcat 这套东西不复杂,复杂的是环境之间的依赖关系,把每一层单独验证过,再串起来就不会互相甩锅。希望帮到你。

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

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

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

立即咨询