實戰(zhàn):SqlServer連接、選座購票與避坑指南)
簡介這份資源是一套基于JavaEE技術(shù)棧的JSP網(wǎng)絡(luò)版影院管理系統(tǒng)完整項目源碼面向?qū)W習(xí)Java Web開發(fā)、需要企業(yè)級項目實戰(zhàn)參考的在校學(xué)生與初級開發(fā)者。系統(tǒng)圍繞影院日常運營展開涵蓋售票、排片、會員管理、訂單處理等核心業(yè)務(wù)采用Servlet、JSP、JavaBean組件配合SqlServer數(shù)據(jù)庫并可能引入JPA/Hibernate簡化持久化操作遵循MVC模式分離業(yè)務(wù)邏輯、視圖展示與用戶交互同時涉及用戶認(rèn)證與權(quán)限控制等安全設(shè)計。壓縮包共626個文件約7.5MB以398個gif、75個jsp頁面、37個css樣式、30個htm、26個js腳本及25張jpg圖片為主另含jar依賴、db與mdf/ldf數(shù)據(jù)庫文件、xml配置及少量java源碼完整呈現(xiàn)從后端到前端UI的構(gòu)建過程。目前已有93人學(xué)習(xí)下載適合作為課程設(shè)計、畢業(yè)設(shè)計或JavaEE入門練手項目幫助讀者理解企業(yè)級Web應(yīng)用的目錄組織、數(shù)據(jù)庫設(shè)計與前后端協(xié)作方式。1. 從一份 .rar 說起JSP 影院管理系統(tǒng)到底在做什么很多人在搜“基于JavaEE的jsp網(wǎng)絡(luò)版影院管理系統(tǒng)”時手里其實已經(jīng)拿到了一份 .rar 壓縮包或者正在為課程設(shè)計、畢設(shè)選題發(fā)愁。這個標(biāo)題拆開看是三層JavaEE 是技術(shù)棧底座JSP 是頁面渲染方式SqlServer 是數(shù)據(jù)落地的位置合起來就是一個典型的傳統(tǒng) JavaWeb 影院業(yè)務(wù)系統(tǒng)——用戶注冊登錄、瀏覽影片、選座購票、查看訂單后臺管理員維護影廳、排片和會員信息。它不新但它是理解 Servlet 容器、會話管理和關(guān)系型數(shù)據(jù)庫設(shè)計的一條完整鏈路。適合誰適合剛學(xué)完 JSP 入門、想找一個能跑通“瀏覽器到數(shù)據(jù)庫”全流程的練手項目的人也適合需要一套可演示、可答辯、結(jié)構(gòu)清晰的課程設(shè)計的人。真正要解決的問題不是“寫一個影院”而是把 JavaEE 分層、JSP 頁面、SqlServer 表結(jié)構(gòu)和 JDBC 連接這四件事串成一條能復(fù)現(xiàn)的路徑。2. 環(huán)境先跑通IDEA 新建 JSP 項目與 SqlServer 連接2.1 為什么選 IDEA Tomcat SqlServer 這套組合傳統(tǒng) JSP 項目最怕環(huán)境玄學(xué)。Eclipse 配 Tomcat 在老教程里常見但 IDEA 對 JavaEE 的支持更集中新建項目時能直接勾選 Web Application省去手動改 web.xml 的麻煩。SqlServer 這邊很多人卡在安裝和驅(qū)動上尤其是“sqlserver安裝程序遇到以下錯誤 句柄無效”這類報錯本質(zhì)是安裝包解壓路徑帶中文或權(quán)限不足。我的習(xí)慣是IDEA 用社區(qū)版加手動配置 TomcatSqlServer 用 2019 或 2022 開發(fā)者版JDBC 驅(qū)動走 Maven 坐標(biāo)不手動丟 jar 包。這樣換機器時pom.xml 一拉就能恢復(fù)。先看項目結(jié)構(gòu)。一個能跑的 JSP 影院系統(tǒng)目錄大致是這樣cinema-system/ ├── src/main/java/ │ ├── com/cinema/dao/ // 數(shù)據(jù)庫訪問 │ ├── com/cinema/service/ // 業(yè)務(wù)邏輯 │ ├── com/cinema/servlet/ // 控制器 │ └── com/cinema/entity/ // 實體類 ├── src/main/webapp/ │ ├── WEB-INF/web.xml │ ├── index.jsp │ ├── user/ │ ├── admin/ │ └── static/ └── pom.xml這個分層不是擺設(shè)。JSP 只負(fù)責(zé)展示Servlet 接請求Service 做業(yè)務(wù)判斷DAO 碰數(shù)據(jù)庫。后面排錯時你能快速定位是頁面?zhèn)鲄㈠e了還是 SQL 寫錯了。2.2 用 Maven 拉 SqlServer JDBC 驅(qū)動并寫連接工具類IDEA 里新建 Maven Web 項目后pom.xml 加三樣?xùn)|西Servlet API、JSP API、SqlServer JDBC。注意 SqlServer 的驅(qū)動坐標(biāo)和 MySQL 不一樣版本要對齊 JDK。dependencies !-- Servlet APITomcat 提供scope 用 provided -- dependency groupIdjavax.servlet/groupId artifactIdjavax.servlet-api/artifactId version4.0.1/version scopeprovided/scope /dependency !-- JSP API -- dependency groupIdjavax.servlet.jsp/groupId artifactIdjavax.servlet.jsp-api/artifactId version2.3.3/version scopeprovided/scope /dependency !-- SqlServer JDBC 驅(qū)動注意版本與 JDK 匹配 -- dependency groupIdcom.microsoft.sqlserver/groupId artifactIdmssql-jdbc/artifactId version9.4.1.jre8/version /dependency /dependencies參數(shù)說明scope為provided的包由 Tomcat 運行時提供打包 war 時不會重復(fù)帶入mssql-jdbc的版本號里jre8表示適配 JDK8如果你用 JDK11 以上換成jre11或更高。很多人搜“intellij idea sqlserver jdbc 自動下載 download from maven failed”多半是倉庫地址被墻或版本寫錯換成阿里云鏡像倉庫再刷新 Maven 即可。連接工具類不要每個 Servlet 都寫一遍 DriverManager。用一個靜態(tài)塊加載驅(qū)動方法返回 Connectionpublic class DBUtil { private static final String URL jdbc:sqlserver://localhost:1433;databaseNamecinemaDB;encryptfalse; private static final String USER sa; private static final String PASSWORD 你的密碼; static { try { Class.forName(com.microsoft.sqlserver.jdbc.SQLServerDriver); } catch (ClassNotFoundException e) { throw new RuntimeException(SqlServer 驅(qū)動加載失敗, e); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } }邏輯說明encryptfalse在本地開發(fā)時避免證書握手報錯databaseName指向你建好的庫。參數(shù)上端口默認(rèn) 1433如果安裝時改了實例名URL 要寫成jdbc:sqlserver://localhost:1433;instanceName你的實例名。這一步跑通的標(biāo)準(zhǔn)是寫一個 main 方法調(diào)getConnection()能打印出連接對象不拋異常。2.3 建庫建表用戶信息表與影院業(yè)務(wù)表的最小集合數(shù)據(jù)庫設(shè)計是這個項目的骨架。搜“第1關(guān):數(shù)據(jù)庫表設(shè)計 - 用戶信息表”的人往往只需要一個能支撐登錄注冊的最小表。但影院系統(tǒng)至少還要影片、影廳、排片、訂單四張表。先看用戶表CREATE TABLE users ( user_id INT IDENTITY(1,1) PRIMARY KEY, username NVARCHAR(50) NOT NULL UNIQUE, password NVARCHAR(100) NOT NULL, phone NVARCHAR(20), role INT DEFAULT 0, -- 0 普通用戶1 管理員 create_time DATETIME DEFAULT GETDATE() );參數(shù)說明IDENTITY(1,1)是 SqlServer 的自增寫法對應(yīng) MySQL 的 AUTO_INCREMENTNVARCHAR支持中文別用 VARCHAR 存用戶名否則中文昵稱會變問號。role字段用整數(shù)區(qū)分權(quán)限比字符串省空間也快。影片表和排片表這樣設(shè)計CREATE TABLE movies ( movie_id INT IDENTITY(1,1) PRIMARY KEY, title NVARCHAR(100) NOT NULL, duration INT, -- 時長分鐘 poster_url NVARCHAR(255), status INT DEFAULT 1 -- 1 上映0 下架 ); CREATE TABLE schedules ( schedule_id INT IDENTITY(1,1) PRIMARY KEY, movie_id INT FOREIGN KEY REFERENCES movies(movie_id), hall_name NVARCHAR(50), start_time DATETIME, price DECIMAL(10,2) );邏輯說明FOREIGN KEY REFERENCES保證排片不會掛到不存在的影片上。DECIMAL(10,2)存票價別用 FLOAT否則 0.10.2 這種精度問題會在訂單金額里翻車。建完表后用 Navicat 或 SqlServer Management Studio 插幾條測試數(shù)據(jù)確認(rèn)SELECT能出結(jié)果。3. JSP 頁面與 Servlet 怎么配合從登錄到選座3.1 登錄注冊JSP 表單提交與 Session 會話保持JSP 頁面本身是 HTML 加 Java 片段。登錄頁login.jsp核心是一個 formform actionLoginServlet methodpost 用戶名input typetext nameusernamebr 密碼input typepassword namepasswordbr input typesubmit value登錄 /form注意action指向 Servlet 的映射路徑不是 jsp 文件。Servlet 里接參數(shù)、查庫、寫 Sessionprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username req.getParameter(username); String password req.getParameter(password); UserDao dao new UserDao(); User user dao.findByUsernameAndPassword(username, password); if (user ! null) { req.getSession().setAttribute(currentUser, user); resp.sendRedirect(index.jsp); } else { req.setAttribute(msg, 用戶名或密碼錯誤); req.getRequestDispatcher(login.jsp).forward(req, resp); } }邏輯說明getSession()默認(rèn)創(chuàng)建會話把用戶對象放進(jìn)去后續(xù)頁面用session.getAttribute(currentUser)判斷是否登錄。參數(shù)上sendRedirect是客戶端跳轉(zhuǎn)地址欄會變forward是服務(wù)器內(nèi)部跳轉(zhuǎn)能帶 request 屬性。登錄失敗用 forward 回登錄頁并顯示錯誤成功用 redirect 防止刷新重復(fù)提交。3.2 影片列表與選座JSP 遍歷數(shù)據(jù)和表單傳參首頁index.jsp要展示影片列表。常見做法是在 Servlet 里查完數(shù)據(jù)req.setAttribute(movies, list)然后 forward 到 JSPJSP 用 JSTL 遍歷c:forEach items${movies} varm div classmovie-card img src${m.posterUrl} alt${m.title} h3${m.title}/h3 a hrefScheduleServlet?movieId${m.movieId}查看排片/a /div /c:forEach參數(shù)說明${m.movieId}是 EL 表達(dá)式對應(yīng)實體類的 getter。如果頁面顯示空白先檢查實體類屬性名和數(shù)據(jù)庫列名是否一致再看 Servlet 有沒有把 list 放進(jìn) request。選座頁面通常用二維數(shù)組生成座位圖每個座位一個 checkbox提交時把選中的座位號拼成字符串傳給訂單 Servlet。這里容易翻車的是中文亂碼在 Servlet 里加req.setCharacterEncoding(UTF-8)JSP 頁頭加% page contentTypetext/html;charsetUTF-8 %。3.3 訂單生成事務(wù)控制與 SqlServer 的坑下單涉及兩張表訂單主表和訂單明細(xì)。必須用事務(wù)否則可能出現(xiàn)訂單建了但座位沒鎖。JDBC 事務(wù)寫法Connection conn null; try { conn DBUtil.getConnection(); conn.setAutoCommit(false); // 關(guān)閉自動提交 // 插入訂單主表 // 插入訂單明細(xì) conn.commit(); } catch (Exception e) { if (conn ! null) conn.rollback(); throw e; } finally { if (conn ! null) conn.close(); }邏輯說明setAutoCommit(false)后所有 SQL 要么一起成功要么一起回滾。參數(shù)上SqlServer 默認(rèn)隔離級別是 READ COMMITTED一般夠用。如果并發(fā)選座多考慮在座位表加唯一約束防止同一座位被賣兩次。搜“sqlserver 存儲記錄時觸發(fā)”的人可能想用觸發(fā)器做庫存扣減但觸發(fā)器調(diào)試麻煩新手建議先在 Service 層用事務(wù)控制。4. 避坑與排查JSP SqlServer 最常見的五類翻車4.1 現(xiàn)象Tomcat 啟動報 ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver原因Maven 依賴沒下載成功或者 war 包里沒帶驅(qū)動。IDEA 里看 External Libraries 有沒有 mssql-jdbc。解決刷新 Maven確認(rèn)scope不是provided如果手動丟 jar放到WEB-INF/lib下。4.2 現(xiàn)象SqlServer 連接報“用戶 sa 登錄失敗”原因sa 賬戶沒啟用或者沒開混合驗證模式。解決用 Windows 身份登錄 SqlServer Management Studio在安全性里啟用 sa 并設(shè)密碼服務(wù)器屬性里選“SQL Server 和 Windows 身份驗證模式”重啟服務(wù)。4.3 現(xiàn)象JSP 頁面中文顯示問號原因頁面編碼、請求編碼、數(shù)據(jù)庫排序規(guī)則三者不一致。解決JSP 頁頭指定 UTF-8Servlet 里setCharacterEncoding數(shù)據(jù)庫列用 NVARCHAR連接 URL 加characterEncodingUTF-8。4.4 現(xiàn)象sqlserver 無法導(dǎo)入數(shù)據(jù) 數(shù)據(jù)無效原因?qū)氲?CSV 或 Excel 里日期格式、數(shù)字格式和表結(jié)構(gòu)不匹配。解決先用SELECT查空表結(jié)構(gòu)確認(rèn)每列類型導(dǎo)入時把日期列映射成 DATETIME數(shù)字列別混入文本。實在不行用BULK INSERT指定格式文件。4.5 現(xiàn)象選座后刷新頁面重復(fù)下單原因表單提交后直接 forward 到結(jié)果頁刷新會重復(fù)提交。解決下單成功后用sendRedirect跳轉(zhuǎn)到訂單列表或者用 token 機制防重。這是典型的 PRG 模式JSP 項目里手動實現(xiàn)一下就行。5. 進(jìn)階把傳統(tǒng) JSP 項目打包成 war 并做一層簡單驗證項目跑通后下一步是打包部署。IDEA 里 Maven 面板執(zhí)行package會在 target 下生成 war 文件。搜“傳統(tǒng)jsp項目打包war”的人多半是要丟到獨立 Tomcat 里跑。把 war 復(fù)制到 Tomcat 的 webapps 目錄啟動 bin/startup.bat訪問http://localhost:8080/項目名/即可。注意 war 包名就是上下文路徑想改成根路徑把 war 重命名為 ROOT.war。驗證數(shù)據(jù)庫設(shè)計是否合理我一般做三件事第一用SELECT加JOIN查一次“某用戶的所有訂單及影片名”能出結(jié)果說明外鍵關(guān)系正確第二在 SqlServer 里開事務(wù)日志查看搜“sqlserver事務(wù)日志查看”的人可以用DBCC LOG或fn_dblog確認(rèn)下單操作有完整記錄第三模擬兩個用戶同時選同一個座位看唯一約束或事務(wù)是否攔住。如果攔不住說明隔離級別或約束沒到位。最后說一個具體技巧JSP 里盡量少寫 Java 代碼用 JSTL 和 EL 替代% %。這樣頁面干凈排錯時不用在 HTML 里找分號。我早期做影院系統(tǒng)時把數(shù)據(jù)庫連接直接寫在 JSP 里結(jié)果改密碼要翻十幾個文件血淚經(jīng)驗就是DBUtil 只留一份所有 DAO 調(diào)它。希望幫到你。本文還有配套的精品資源點擊獲取