經典「JSP + JavaBean + Servlet」三層架構入門實戰。本文記錄 JDK 1.4.2、Tomcat 5.0、SQL Server 2000 個人版、Microsoft JDBC 驅動 (msbase.jar/msutil.jar/mssqlserver.jar) 的安裝配置、Tomcat 虛擬目錄與 DataSource 連接池配置 (wool.xml + web.xml)、JSP 測試代碼、**僅供教學入門參考,生產環境請使用成熟連接池 (HikariCP/Druid) 與 ORM (MyBatis/JPA)**。
| 組件 | 版本/來源 | 關鍵點 |
|---|---|---|
| JDK | j2sdk-1_4_2_07 | 安裝路徑無空格,如 C:\jdk |
| Tomcat | jakarta-tomcat-5.0.28.exe | 安裝路徑 D:\tomcat,安裝版自帶服務註冊 |
| SQL Server | 2000 Personal/Developer Edition | Windows XP 必須個人版/開發版,混合認證模式,sa 密碼可為空 |
| JDBC 驅動 | Microsoft SQL Server 2000 Driver for JDBC | 三個 JAR:msbase.jar, msutil.jar, mssqlserver.jar |
# 系統變量
JAVA_HOME=C:\jdk
CLASSPATH=.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar
PATH 追加 %JAVA_HOME%\bin
# Tomcat 相關 (編譯 Servlet 需)
TOMCAT_HOME=D:\tomcat
CLASSPATH 追加 %TOMCAT_HOME%\common\lib\servlet-api.jar;%TOMCAT_HOME%\common\lib\jsp-api.jar
PATH 追加 %TOMCAT_HOME%\bin
CREATE DATABASE test;
GO
USE test;
GO
CREATE TABLE test (
id INT IDENTITY(1,1) PRIMARY KEY,
mark VARCHAR(255),
name VARCHAR(255),
sex VARCHAR(255)
);
GO
INSERT INTO test (mark, name, sex) VALUES ('90', 'Alice', 'F');
INSERT INTO test (mark, name, sex) VALUES ('85', 'Bob', 'M');
E:\wool\ # 虛擬目錄物理路徑
├── test.jsp # 測試頁面
└── WEB-INF\
├── web.xml # 應用級資源引用
├── classes\ # 編譯後類文件
└── lib\ # 應用級 JAR (放入 3 個 JDBC 驅動 JAR)
├── msbase.jar
├── msutil.jar
└── mssqlserver.jar
D:\tomcat\conf\Catalina\localhost\)<Context reloadable="true" docBase="E:\wool" path="/wool" workDir="E:\wool\WEB-INF\classes">
<Resource name="jdbc/sqlserver" type="javax.sql.DataSource"/>
<ResourceLink name="jdbc/sqlserver" type="javax.sql.DataSource" global="jdbc/sqlserver"/>
<ResourceParams name="jdbc/sqlserver">
<parameter>
<name>driverClassName</name>
<value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>
</parameter>
<parameter>
<name>url</name>
<value>jdbc:microsoft:sqlserver://localhost;DatabaseName=test</value>
</parameter>
<parameter>
<name>username</name>
<value>sa</value>
</parameter>
<parameter>
<name>password</name>
<value></value> <!-- 空密碼 -->
</parameter>
<parameter>
<name>maxActive</name>
<value>4</value>
</parameter>
<parameter>
<name>maxWait</name>
<value>5000</value>
</parameter>
<parameter>
<name>maxIdle</name>
<value>2</value>
</parameter>
</ResourceParams>
</Context>
關鍵說明: Tomcat 5.x Context 配置採用 ResourceParams 子元素定義屬性,**XML 註釋會導致解析失敗**,必須刪除所有 <!-- --> 註釋。
E:\wool\WEB-INF\)<web-app>
<resource-ref>
<description>connectDB</description>
<res-ref-name>jdbc/sqlserver</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</web-app>
<%@ page contentType="text/html; charset=gb2312" %>
<%@ page import="javax.naming.*, javax.sql.DataSource, java.sql.*" %>
<%
DataSource ds = null;
try {
Context initCtx = new InitialContext();
ds = (DataSource) initCtx.lookup("java:comp/env/jdbc/sqlserver");
if (ds != null) {
out.println("已獲得 DataSource!<br>");
Connection conn = ds.getConnection();
Statement stmt = conn.createStatement();
ResultSet rst = stmt.executeQuery("SELECT * FROM test");
out.println("以下是從數據庫中讀取出來的數據<br>");
out.println("<table border=1><tr><th>ID</th><th>Mark</th><th>Name</th><th>Sex</th></tr>");
while (rst.next()) {
out.println("<tr><td>" + rst.getString(1) + "</td><td>" + rst.getString(2) + "</td><td>" + rst.getString(3) + "</td><td>" + rst.getString(4) + "</td></tr>");
}
out.println("</table>");
conn.close(); // 必須關閉,歸還連接池,否則洩漏導致枯竭
} else {
out.println("連接失敗!");
}
} catch (Exception ne) {
out.println(ne);
}
%>
https://localhost:8080/wool/test.jsp| 原組件 | 現代替代 | 優勢 |
|---|---|---|
| JSP + Scriptlet | Spring MVC + Thymeleaf / JSP (EL/JSTL) | 關注點分離、可測試、無腳本安全風險 |
| Tomcat ResourceParams 連接池 | HikariCP (Spring Boot 自動配置) | 性能最優、指標豐富、零 XML 配置 |
| Microsoft JDBC 1.0 (舊) | Microsoft JDBC 12+ (mssql-jdbc) | JDBC 4.3、SSL、Always Encrypted、Java 17+ 支持 |
| SQL Server 2000 | SQL Server 2019/2022 / Azure SQL | 安全性、性能、雲原生、Linux 容器支持 |
| 手動環境變量 | SDKMAN! / Docker Compose / Maven Wrapper | 可複現、版本鎖定、CI/CD 一體化 |
三層架構教學版本雖簡陋,但完整展示了「容器管理資源 → JNDI 查找 → 連接池 → JDBC 操作」的核心鏈路。理解這條鏈路,是掌握 Spring 數據訪問抽象、事務管理、連接池調優的基石。建議初學者在跑通教學版後,立即轉向 Spring Boot + HikariCP + MyBatis/JPA 現代棧,避免在過時 API 上投入過多時間。