基于JSP与SQL Server的网上书店系统搭建实战:从环境配置到存储过程优化

发布时间:2026/10/4 15:06:15
基于JSP与SQL Server的网上书店系统搭建实战:从环境配置到存储过程优化 简介基于JSPSQL Server的网上书店系统实现源码附带项目说明文档面向Java Web学习者、课程设计及毕业设计参考人群可快速了解在线图书销售管理系统的完整业务流程。包内共有731个文件以JSP页面、Java源码、CSS样式、JS脚本为主另含SQL Server数据库文件mdf/ldf及文档说明整体压缩包大小约9.26MB目录结构清晰便于定位关键模块。已有94人学习下载。资源覆盖用户登录身份验证、购物车与订单处理、管理员对图书和订单及友情链接的管理等核心功能选择页面结合用户信息表展示按用户名称和密码校验合法用户、通过权限编号控制功能、读取用户编号注入Session等典型实现手法。对于想要掌握JSPSQL Server项目搭建、用户权限控制与购物流程编码的读者是一份可直接运行的参考资料。1. JSP SQL Server网上书店系统到底能给你什么一个比 Demo 更值得跑通的全栈样本很多人在某个资源站或师兄的 U 盘里拿到过这种“网上书店系统实现源码”压缩包里是 src、WebRoot、数据库脚本和一份说明文档标题写着 java-jsp-SQLserver。第一反应通常是“太老了”但真去部署时才发现一套看似简单的 JSP SQL Server 项目反而比网上那些纯 CRUD Demo 更能暴露问题TCP/IP 协议没开、JDBC 驱动没进 lib、数据库排序规则不对导致中文乱码、页面能打开但数据死活加载不出来。这个技术组合放在今天看前端确实不算新潮但它把 Java Web 开发里最核心的三层结构、会话跟踪、JDBC 操作、结果集分页全都串了起来对做课程设计、毕业设计或者想补 Java Web 项目经历的人来说仍然是一条值得完整复现、然后有东西可写进简历的路径。这篇文章就是按这个目标来拆怎么把它跑起来、参数怎么配、坑在哪里、以及怎么改出一个能让面试官多说两句的版本。2. 搭建可复现的开发环境JDK、Tomcat、SQL Server 与 JDBC 驱动一个都不能少2.1 为什么这个组合今天还值得装一次刚接触 Java Web 的时候不少人把精力放在学 Spring Boot 上反而把 JSP/Servlet 这条老链路看得太简单。等到真去运行一套“JSP SQL Server”源码时才会发现自己根本没弄明白Tomcat 是怎么把 JSP 编译成 Servlet 的SQL Server 的登录方式跟 MySQL 有什么不同Java 程序连接 SQL Server 时驱动从哪来。这些恰恰是很多 Java 面试题里爱往深处问的点比如“三层架构里表现层怎么调业务层”“Session 和 Cookie 怎么维持登录态”。所以这套网上书店系统与其说是一个过气项目不如说是一个训练环境。常见的源码包结构一般是 src 放 Java 类、WebRoot 或 webapp 放 JSP 页面、一个 .sql 文件放建表和测试数据、一份说明文档描述部署步骤。说明文档通常默认你已经装好了数据库和服务器会把最关键的环境要求写在最前面。可现实里大多数翻车不是代码问题而是环境问题JDK 版本太新、Tomcat 版本太新、SQL Server 装完没配置、JDBC 驱动拷贝错位置。我一般会建议在动手改代码之前先把环境按照一套保守但稳定的版本组合搭好再谈跑通。2.2 安装与版本匹配一张清单讲清楚谁和谁能配版本选择上用国产经验来说就是“别追新”。很多老源码基于 javax.* 命名空间而 Tomcat 10 起把包名切成了 jakarta.*旧源码不改 import 直接编译报错。与其花整晚改包名不如退到 Tomcat 9。JDK 建议用 8 或 11SQL Server 用 Developer 版或 Express 版足够本地学习。下面是我常用的匹配参考组件推荐版本理由JDK8 或 11兼容 Tomcat 9 和大量 JSP 老项目的语法Tomcat9.0.x 解压版仍是 javax 命名空间省去改包名的麻烦SQL Server2016 / 2019 Developer 或 Express学生和单机学习足够用OFFSET FETCH 分页可用JDBC 驱动mssql-jdbc-x.x.jar8.4 或 9.x 均可向下兼容 SQL Server 2012 及以上版本数据库管理工具SSMS 或 Azure Data Studio执行脚本、排查报错比命令行直观注意 JDK 一个就够了不要在同一台机器上装多个再去改环境变量很容易把 Tomcat 启动脚本搞晕。SQL Server 安装时如果选了默认实例实例名是 MSSQLSERVER如果自定义了实例名后面 JDBC 连接串里要写成“localhost\实例名”这是新手最容易忽略的细节。SQL Server 配置管理器这个图形化工具安装后默认就有后面排查 TCP/IP 全靠它。2.3 用一段最小 Java 代码验证 SQL Server 连通性我建议拿到源码之后先不要急着启动 Tomcat先写一个只有二十行的 Java 类去连一下 SQL Server把“代码还没跑、环境先通”这件事确认下来。新建一个文件夹 TestDB把 mssql-jdbc 的 jar 放进去再写这个文件import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class TestDB { public static void main(String[] args) throws Exception { // 1. 加载驱动类老写法主要验证 jar 是否在 classpath Class.forName(com.microsoft.sqlserver.jdbc.SQLServerDriver); // 2. 连接串库名 bookstore关闭加密信任服务器证书 String url jdbc:sqlserver://localhost:1433; DatabaseNamebookstore; encryptfalse;trustServerCertificatetrue; Connection conn DriverManager.getConnection(url, sa, 123456); // 3. 最简单的查询确认能出数 Statement stmt conn.createStatement(); ResultSet rs stmt.executeQuery(SELECT 1 AS ok); while (rs.next()) { System.out.println(connect ok, value rs.getInt(ok)); } conn.close(); } }这段代码的逻辑分三步Class.forName 负责让 JVM 认识 SQL Server 驱动类出的问题一般是“No suitable driver”十有八九是 jar 没放进编译运行时的 classpathDriverManager.getConnection 用的协议头是 jdbc:sqlserver这是微软驱动的固定写法不可能替换成别的最后的 SELECT 1 只验证连通性不依赖业务表是否存在。注意 URL 里的 encryptfalse 是本地开发用的生产环境应该启 TLS 并把 trustServerCertificate 去掉。运行前先确认 SQL Server 服务已启动否则会报连接超时或 “Connection refused”。这段跑通了就说明驱动和数据库两件事都干净了接下来可以放心进入建库和接项目的阶段。3. 从建库到登录数据表设计、JDBC 连接与 JSP 页面的调用链路3.1 书店系统的三张核心表怎么设计网上书店系统的模型一般不会复杂核心就三块用户、图书、订单。设计数据库时不要一上来把表建得很碎先把用户表、图书表、订单表和订单明细表立起来购物车可以用 Session 实现也可以单独建表课程设计级别用前三种比较多。SQL Server 里我习惯把字符串字段统一用 NVARCHAR因为 SQL Server 的 VARCHAR 在不同排序规则下对中文处理的坑更多NVARCHAR 配合正确的代码页会省掉一部分乱码问题。-- 创建数据库 CREATE DATABASE bookstore; GO USE bookstore; GO -- 用户表 CREATE TABLE users ( user_id INT IDENTITY(1,1) PRIMARY KEY, username NVARCHAR(50) NOT NULL UNIQUE, password NVARCHAR(100) NOT NULL, email NVARCHAR(100) NULL, created_at DATETIME DEFAULT GETDATE() ); GO -- 图书表 CREATE TABLE books ( book_id INT IDENTITY(1,1) PRIMARY KEY, book_name NVARCHAR(200) NOT NULL, author NVARCHAR(50) NULL, price DECIMAL(10,2) NOT NULL, stock INT NOT NULL DEFAULT 0, category NVARCHAR(50) NULL, image_url NVARCHAR(255) NULL ); GO -- 订单表 CREATE TABLE orders ( order_id INT IDENTITY(1,1) PRIMARY KEY, user_id INT NOT NULL REFERENCES users(user_id), total_amount DECIMAL(10,2) NOT NULL, create_time DATETIME DEFAULT GETDATE() ); GO -- 订单明细表 CREATE TABLE order_items ( item_id INT IDENTITY(1,1) PRIMARY KEY, order_id INT NOT NULL REFERENCES orders(order_id), book_id INT NOT NULL REFERENCES books(book_id), quantity INT NOT NULL, price DECIMAL(10,2) NOT NULL ); GO这里几个参数值得说明IDENTITY(1,1) 相当于 MySQL 的 AUTO_INCREMENT让 SQL Server 自己维护主键DECIMAL(10,2) 表示整数部分 8 位、小数 2 位金额字段别用 FLOAT否则算总价会出现一堆小数点GETDATE() 取的是数据库服务器当前时间比在 Java 代码里用 new Date() 再传参数更不容易碰到时区问题。顺序上也有讲究先订单表再订单明细表因为明细表的外键依赖订单主键如果一次性执行整个脚本SQL Server 的 GO 批处理符号必须保留SSMS 或 sqlcmd 能识别但有些图形化工具可能不吃这一套。3.2 JDBC 直连还是连接池两种写法和一个取舍课程设计来源的商城项目里最常见的写法不是连接池而是一个 DBUtil 或 DBHelper 工具类类里写死数据库地址、用户名、密码每次需要数据库操作就调一次 getConnection()用完再 close()。这种写法在并发量很小的学习项目里完全够用而且逻辑直白适合讲清楚 JDBC 的生命周期。Tomcat 连接池是更接近生产的方案JSP/Servlet 通过 JNDI 拿到 DataSource连接由容器管理但配置复杂度高一截。import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DBUtil { private static final String URL jdbc:sqlserver://localhost:1433;DatabaseNamebookstore; encryptfalse;trustServerCertificatetrue; private static final String USER sa; private static final String PASSWORD 123456; static { try { Class.forName(com.microsoft.sqlserver.jdbc.SQLServerDriver); } catch (ClassNotFoundException e) { throw new ExceptionInInitializerError(请把 mssql-jdbc jar 放到 WEB-INF/lib 下); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } }这段工具类的关键点有两处静态代码块只执行一次所以驱动类加载失败会立刻抛出异常而不是等到第一次查库才报 ClassNotFoundExceptiongetConnection 每次调用都新建物理连接在高并发下这是性能瓶颈但学习阶段反而方便观察“连接被关闭”的问题通常出在哪。很多老源码会在 JSP 页面里直接写 Class.forName每访问一次页面就加载一次驱动浪费资源不说时序上还容易出现奇怪的偶发报错。我一般会把驱动加载挪到静态块里然后把获取连接的逻辑收敛到这一个类后面的 Servlet 和 JSP 都只调 DBUtil.getConnection()这样排查数据库问题只需要看一个文件。3.3 登录页面里 JSP、Servlet 和 JDBC 是怎么串起来的登录功能是所有带用户体系的系统里最值得先跑通的模块。典型流转是用户在 login.jsp 输入用户名密码表单提交给 LoginServletServlet 里调 DBUtil 拿连接用 PreparedStatement 查 users 表比对通过后把用户信息放进 Session然后重定向到 index.jsp比对失败则返回 login.jsp 并带一个错误参数。注意流程里不应该把密码明文到处传但课程设计源码很多就是这样写的作为复现先跑通再接改进。% page importjava.sql.* % % request.setCharacterEncoding(UTF-8); String username request.getParameter(username); String password request.getParameter(password); Connection conn null; PreparedStatement ps null; ResultSet rs null; try { Class.forName(com.microsoft.sqlserver.jdbc.SQLServerDriver); String url jdbc:sqlserver://localhost:1433;DatabaseNamebookstore; encryptfalse;trustServerCertificatetrue; conn DriverManager.getConnection(url, sa, 123456); String sql SELECT * FROM users WHERE username? AND password?; ps conn.prepareStatement(sql); ps.setString(1, username); ps.setString(2, password); rs ps.executeQuery(); if (rs.next()) { session.setAttribute(loginUser, rs.getString(username)); response.sendRedirect(index.jsp); } else { out.print(scriptalert(用户名或密码错误);history.back();/script); } } finally { if (rs ! null) rs.close(); if (ps ! null) ps.close(); if (conn ! null) conn.close(); } %这段是很多老项目里真实存在的写法直接放在 JSP 里而不是拆成 Servlet它演示了三件事request.setCharacterEncoding 必须放在取参数之前否则中文用户名会乱码PreparedStatement 用 ? 占位符再 setString 传参这种写法能防掉最常见的字符串拼接注入问题finally 里关闭顺序是从 ResultSet 到 Connection 倒着关避免连接没释放把 SQL Server 的连接数占满。这段代码同时暴露了它的上限业务逻辑写在 JSP 里难以维护。所以它适合用来“先跑通”不适合当作最终架构。熟练之后把它改成 Servlet DAO 是性价比最高的重构方向也是后续能让面试官认可你“不只会复制”的关键差异。4. 部署跑通阶段的避坑排查TCP/IP、sa 密码、中文乱码与重复提交四个翻车点4.1 部署顺序没有想象中那么随意用源码包部署网上书店系统我常用的是一个非常朴素的顺序SQL Server 建库导数据再把整个项目目录复制到 tomcat/webapps 下改数据库连接参数然后启动 Tomcat 访问 http://localhost:8080/项目名/。如果是 Eclipse 或 IDEA 导出的 WAR 包放进 webapps 就行Tomcat 启动时会自动解压。这套流程里最容易出问题的并不是最后一步而是建库时没有按说明文档里的排序规则和登录方式执行导致后面连接串怎么写都不对。4.2 四个翻车点的现象、原因和解决第一个坑SQL Server 装了但 Java 连不上。现象是驱动明明加载成功报 “The TCP/IP connection to the host localhost, port 1433 has failed”。原因多半不是代码而是 SQL Server 配置管理器里 TCP/IP 协议默认处于禁用状态。解决方法是打开 SQL Server 配置管理器找到“SQL Server 网络配置”里的实例双击 TCP/IP协议状态改成“已启用”然后到“SQL Server 服务”里重启实例。这个坑十个里能遇到六个连字符串写一万遍都没用。第二个坑sa 账号登录失败。现象是连数据库时提示 “Login failed for user sa”或者 18456 错误。原因通常是安装 SQL Server 时选了“Windows 身份验证模式”没有启用 SQL Server 身份验证。解决方法是先用 Windows 身份验证连进 SSMS在服务器属性里的“安全性”页选择“SQL Server 和 Windows 身份验证模式”再找到 sa 账号重新设置一个强密码并开启登录映射。顺手再把服务器属性里的密码策略暂时关掉否则密码复杂度不够一样会失败。第三个坑部署后页面中文乱码。现象是图书名称、作者名显示成??。原因是 JSP 页面、Java 代码和数据库三处的字符编码没有统一。步骤上是先在 JSP 顶部加 pageEncodingUTF-8再在取参数前执行 request.setCharacterEncoding(UTF-8)最后在 JDBC 连接串里加上 characterEncodingUTF-8三处一致后重启 Tomcat。SQL Server 建库时我用的是 NVARCHAR这类中文问题基本能兜住但注意数据库排序规则如果选错了区域可能仍然会出现排序和显示不一致的怪现象。第四个坑购物车或订单数据被重复提交。现象是用户下单后发现订单数量翻倍尤其很多教材喜欢把按钮动作绑定在一个超链接上页面刷新一次就重新提交一次。原因是前端用了 GET 请求触发下单动作浏览器刷新会原样重放请求。解决方法是把购物车加购和提交订单改成 POST并在提交成功后用 response.sendRedirect 跳转到新的结果页也就是 PRG 模式刷新结果页时不会把上一次提交操作再执行一次。这个问题在一些 JSP 教材的“页面上线后自动刷新”示例里尤其常见。4.3 页面能打开但数据加载不出来的排查清单如果 Tomcat 起来了、网页也能显示但是列表页没有数据问题通常不在业务代码而在下面几个位置第一看 Tomcat 的 localhost.yyyy-MM-dd.log今天日期对应的日志文件里如果出现 ClassNotFoundException是驱动 jar 没复制到项目的 WEB-INF/lib 目录如果出现 “Cannot create PoolableConnectionFactory”是连接串或数据库服务问题。第二确认你访问的项目路径是对的Tomcat 默认端口是 8080项目名不要拼错。第三用 F12 看浏览器请求返回的状态码500 说明服务端代码抛异常404 说明路径没对上。第四SQL Server 2019 以后的驱动默认要求加密连接如果驱动版本太旧连接时还会报 SSL 相关错误方案是在 URL 里临时加 encryptfalse;trustServerCertificatetrue把加密层的变量先排除掉。这步做完数据还是不出来就去 SSMS 里单独执行一遍查询脚本确认不是 SQL 语法的问题。5. 把图书检索改成存储过程调用给这套网上书店加一个能写进简历的加分项5.1 在 SQL Server 里创建一个图书检索的存储过程这套网上书店如果只能做登录和下单那它在简历里就是最普通的 CRUD 项目。想让它有差异化第一个值得动手的点是把图书列表页那个拼接 LIKE 的 SQL 改造成存储过程。这不只是把字符串换个位置而是把“数据库结构”和“页面表现层”做了一个切割。存储过程写好后JSP 页面不需要知道 books 表里有哪些字段只需要调用过程名和传入参数。USE bookstore; GO CREATE PROCEDURE dbo.SearchBooks keyword NVARCHAR(50) AS BEGIN SET NOCOUNT ON; SELECT book_id, book_name, author, price, stock FROM books WHERE book_name LIKE % keyword % OR author LIKE % keyword % ORDER BY book_id OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY; END GO这段脚本里 OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY 是 SQL Server 2012 之后的标准分页写法比老式的 ROW_NUMBER() 子查询可读性好很多。如果换成 MySQL分页语法是 LIMIT 10 OFFSET 0很多从 MySQL 转过来的人第一次写 SQL Server 都会在这里翻车。存储过程里 SET NOCOUNT ON 是习惯不让 SQL Server 在返回结果集之前先发一条受影响行数的消息Java 这边拿 ResultSet 会更干净。LIKE 的写法这里不多做优化实际大量数据下不要用前置百分号会阻挡索引利用。5.2 在 JSP/Servlet 里调用存储过程并验证结果Java 调用存储过程用的是 CallableStatement不是普通 PreparedStatement。差别在于调用语法是 {call 过程名(?)}并且参数下标从 1 开始和 PreparedStatement 一致。拿到源码后我把原来直接在 DAO 里写 SQL 的地方先替换成 5.1 这个存储过程再验证页面检索是否返回相同的数据。String sql {call SearchBooks(?)}; try (Connection conn DBUtil.getConnection(); CallableStatement cs conn.prepareCall(sql)) { cs.setString(1, keyword); try (ResultSet rs cs.executeQuery()) { while (rs.next()) { // 每行数据封装成 Book 对象或直接输出到 JSP String name rs.getString(book_name); // 业务代码填充列表交给页面渲染 } } }这段代码的核心价值是调用路径变简单了页面层只依赖过程名和参数不暴露表字段。验证时先在 SSMS 里执行 EXEC SearchBooks NJava确认能返回 Java 相关书目再用浏览器访问检索页面对比结果。这个改动做完你简历里写这个项目的时候就多了一个“用存储过程封装图书检索分离数据访问与页面逻辑”的描述面试官顺着这个点往下聊你也能从索引、分页、参数化三个方向接住话。我早期学习时有一个教训拿到老项目不要急着整个推倒重写先把一个最常用功能从 JSP 内嵌 SQL 改成存储过程调用跑通后再逐步把其他模块挪进 Servlet DAO。这种小步重构的方式比一次性重写二十个 JSP 更稳妥也更能让你理解每层到底是做什么的。希望这篇对你有帮助。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询