Tomcat + JSP + SQL 快速入門


Tomcat 設定

Tomcat 是一種 JSP 容器,它不僅是最熱門的 JSP 伺服器,而且無須安裝與設定,下載解開就能隨點隨用。即使不當作 JSP 伺服端系統,純粹只是要架個 HTTP 伺服器,Tomcat 也是非常輕巧的選擇~


下載、安裝、執行

下載

請至 http://tomcat.apache.org 下載 Apache Tomcat,建議使用免安裝的版本。

安裝

解壓後無須安裝即可執行,但你必須注意是否安裝 JDK,並且設定 JAVA_HOME 環境變數指向你 JDK 所安裝的路徑,否則無法啟動 Tomcat。

啟動

直接點擊 Tomcat 裡面 bin 資料夾的 startup.bat 即可啟動,要關閉的話則是 shutdown.bat

或者使用命令提示字元,切換路徑到 Tomcat 的 bin 資料夾,輸入 catalina start 來啟動,然後用 catalina stop 關閉。


修改網站的預設網頁路徑

修改 conf 目錄裡面的 server.xml,在 <Host></Host> 裡面插入:

<Context path="" docBase="存放網頁的目錄路徑" reloadable="false" />

存檔後重新啟動 Tomcat。


新增網頁路徑

修改 conf 目錄裡面的 server.xml,在 <Host></Host> 裡面插入:

<Context path="/名稱" docBase="存放網頁的目錄路徑" reloadable="true" />

存檔後重新啟動 Tomcat,在網頁瀏覽器輸入 127.0.0.1:8080/名稱。


取消 8080 埠號

不希望每次輸入網址要打埠號的話,請修改 conf 目錄中 server.xml 裡面 <Connector /> 的 port 為 "80",存檔後重新啟動 Tomcat 即可。

因為 80 是預設的埠號,不輸入埠號的話會自動填入 80,所以達到不用輸入埠號的效果!

需要注意的是,如果其它程序已經佔用 80 埠號,將無法連線到 Tomcat 伺服器。

Linux 的話,必須以 root 權限啟動 Tomcat 伺服器,否則無法連接小於 1024 埠號的傳輸服務。


設定管理者帳號密碼

修改 conf 目錄裡面的 tomcat-users.xml 檔案,然後加入如下敘述:

<user name="帳號" password="密碼" roles="standard, manager" />


主控台亂碼

修改 conf 目錄裡面的 logging.properties 檔案,將 java.util.logging.ConsoleHandler.encoding 改為 Big5


JSP 語法


使用 JSP 的理由

雖然 Java 已經有 Servlet 可以實現動態網頁的程式設計,但因為以輸出字串的方式來呈現 HTML 標籤,並不好判讀網頁本身的結構…


如果用 JSP 的話,則是以 HTML 語法為主,再把 Java 語法也當作標籤混夾在一起…


開發動態網頁的話,直接以網頁本身來設計與修改,是比較直覺的。顯然將 Java 程式碼插入 HTML 語法的 JSP,要比將 HTML 語法混在 Java 程式碼裡的 Servlet,更能提高開發效率!1


基本語法結構

以 JSP 設計 Dynamic HTML 的基本結構


<%= %> 相當於 <% out.print() %>

把 JSP 當 Servlet 寫的基本範例

註解掉某塊 JSP 程式碼


內建預設物件

JSP 預先宣告了幾個物件,可以讓我們直接在 <% %> 裡使用:

application在 Servlet 常用的 ServletContext 物件。
config在 Servlet 常用的 ServletConfig 物件。
outJSP 自帶的 JspWriter 物件。
page基本上是個 Object 的物件。
pageContextJSP 自帶的 PageContext 物件。
request在 Servlet 常用的 HttpServletRequest 物件。
response在 Servlet 常用的 HttpServletResponse 物件。
session在 Servlet 常用的 HttpSession 物件。
exception基本上是個 Throwable 的物件。

application

用來保存所有瀏覽這個站點(web-app)的使用者共用的訊息,像是聊天室就能以這個機制簡單架設,只要使用 setAttribute("屬性名稱","屬性內容") 紀錄訊息,然後用 getAttribute("屬性名稱") 取得「屬性內容」即可,也可用 removeAttribute("屬性名稱") 刪除。更多

其它還有一些有趣、但不常用的功能,像是可將初始化設定值寫在 web.xml 裡面當作參數,然後透過 application 的 getInitParameter() 取出來使用:

[ WEB-INF\web.xml ]

[ helloworld.jsp ]

[ browser ]
world

config

可以取得在 web.xml 為 Servlet 設定的初始化參數,基本上用不到,因此略過;不想略過的話,請按我

使用 getInitParameter("屬性名稱"),取得 web.xml 中以 <init-param><param-name>屬性名稱</param-name><param-value>屬性內容</param-value></init-param> 設定的「屬性內容」,例如:

[ WEB-INF\web.xml ]

[ helloworld.jsp ]

[ browser ]
world
可以使用 getInitParameterNames() 取得所有參數名稱。

out

print()println() 輸出字串資料給 HTML 網頁。

page(基本上用不到)

既然是個 Object,也就表示沒什麼功能可以操作,純粹用來表示 JSP 網頁本身的物件。

pageContext(原則上別用到)

可以使用 setAttribute("鍵", "值") 將資料紀錄在網頁中保存,再用 getAttribute("鍵") 把「值」取出來。

request

負責接收 HTTP 通訊的物件,通常用來取得經由 HTTP 通訊所夾帶的訊息,例如前一張網頁遞交的 form 填表資料,通常使用 getParameter("元件名稱") 取得填表資料,或者在那之前使用 SetCharacterEncoding("字元編碼") 設定以哪一種編碼來取得資料,避免亂碼。更多

除此之外,還可用 getRemoteAddr() 取得 IP、getRemoteHost() 取得主機名稱、getHeader("屬性名稱") 取得使用者操作環境與 HTML 中 HEADER 的訊息,像是以 request.getHeader("user-agent") 來判斷使用者的作業系統與瀏覽器。

response

負責發送 HTTP 通訊的物件,主要透過其 sendRedirect("網址") 重新導向網頁。

雖然在 Servlet 這是非常實用的物件,不過在基本上是 HTML 的 JSP 有直接做法,變得很少用到。通常需要進階描述發送出去的訊息時才會使用,像是遞交 File 物件時以 setContextType() 描述 MIME、或者希望能確認遞交動作是否完成而使用 isCommitted()、甚至最佳化 HTTP 發送的緩衝大小而使用 setBufferSize()

session

用來保存使用者瀏覽期間的訊息,裡面的資料會在關閉瀏覽器後才清除,資料存在期間,使用者在網站開啟的每張 JSP 網頁,都能共用 session 物件的資料。適合跨網頁保存資料的場合,例如是否已登錄帳戶的訊息。

你可以在 A.jsp 中使用 session.setAttribute("屬性名稱","屬性內容") 將訊息保存在 session,然後在 B.jsp 使用 session.getAttribute("屬性名稱") 取得「屬性內容」。

與 application 物件的差別是,session 只有使用者能存取資料,其他瀏覽同一個網站的使用者並沒有共用這些資料。

exception

可用 getMessage() 取得前一張網頁所 throw 出的 Exception 訊息,必須搭配 <%@ page isErrorPage="ture" %> 將用到 exception 物件的 JSP 網頁,設為錯誤處理專用的頁面。

通常會在前一張網頁使用 <%@ page errorPage="" %> 指令,指向含有 exception.getMessage() 的 JSP 網頁,再用 <% throw new Exception("") %> 丟出錯誤訊息,讓 exception.getMessage() 的 JSP 網頁接收~


指令

JSP 使用 <%@ 指令 %> 格式的「指令」,來設定 Servlet 容器或 JSP 物件的屬性:

<%@ page contentType="" %>指定文件格式與編碼。
<%@ page import="" %>載入套件。
<%@ page extends="" %>指定該 JSP 繼承自哪個類別。
<%@ page errorPage="" %>指定處理錯誤訊息的頁面。
<%@ page isErrorPage="true" %>設定該 JSP 為錯誤處理頁面。
<%@ page buffer="" %>設定緩衝資料大小,請使用 8kb 的倍數。
<%@ include file="" %>載入檔案。

其它特殊情況才會使用的指令設定:

<%@ page buffer="none" %> 關閉緩衝區。
<%@ page autoFlush="false" %> 禁止自動送出緩衝資料。
<%@ page isThreadSafe="false" %> 不以執行緒方式啟動,而是以獨立的程序執行。
<%@ page session="false" %> 不使用 session 物件。
<%@ taglib uri="" prefix="" %> 載入標籤庫,可使用像是 <jsp:forward page=""/> 之類的標籤,來取代 response.sendRedirect() 這樣的 Java 程式設計。

如果懂得善用各家標籤庫,來解決各種開發動態網頁的工作,達到不用撰寫 Java 程式碼的地步,那整張 JSP 等於全部由「標籤(Tag)」組成,這會更像 HTML 網頁!因此一般認為「標籤庫」是使用 JSP 的最理想方式,所以也是目前各家開放原始碼團隊最有興趣貢獻的領域。


SQL 實例

本文介紹如何搭配 Tomcat 與 MySQL,建立可用 JSP 來練習 SQL 的程式設計環境。


MySQL

MySQL 是最容易安裝與使用的關聯性資料庫伺服器,尤其被 Sun Microsystems 收購後,相當於 Java 家族的成員之一。

下載

請至 http://www.mysql.com 下載 MySQL Community Server,為了方便設定伺服器環境,建議下載 Installer 的版本。

安裝

不要安裝在 C:\Program Files 底下,建議改安裝在 D 槽,避免 Windows 系統保護權限問題,安裝後無法正常啟動 MySQL 服務。

安裝後第一次執行 MySQL 時,會出現設定精靈,過程中,建議設定為「Install As Windows Service」,交由作業系統啟動 MySQL 服務,並且允許帳號可以從遠端登入伺服器。

執行

安裝 MySQL 資料庫伺服器的主要目的,是為了從外部操作環境(例如 JDK 或 Tomcat)登入伺服器,來存取 MySQL 內部資料,因此應用上比較沒有「如何執行 MySQL」的問題。只要將 MySQL 啟動為 Windows 的「服務」即可。

但你還是可以透過 MySQL Command Line Clent 來輸入 SQL 指令,直接從 MySQL 內部操作資料庫。


Connector/J

要讓 Java 操作 MySQL,你必須下載一種叫做 JDBC 的驅動程式。

下載

請至 http://dev.mysql.com/downloads/connector/j/ 下載 Connector/J。

安裝

解壓後,將 mysql-connector-java-5.1.22-bin.jar 放到 Tomcat 所在資料夾底下的 lib 資料夾,然後重新啟動 Tomcat。

5.1.22 是版本號碼,視年份日期而有不同。


Hello, world!

建立程式檔案

請建立一份純文字文件,檔名為 hello.jsp,然後丟到 Tomcat 所在資料夾的 webapps 資料夾的 ROOT 資料夾裡面3

程式碼

在 hello.jsp 文件裡面,輸入如下程式碼:

執行程式

開啟瀏覽器,輸入如下網址:

http://127.0.0.1:8080/hello.jsp

順利的話,會看到網頁顯示 Hello, world!:

msedge('http://127.0.0.1:8080/hello.jsp','Hello, world!')

但是這個範例重新整理的話,會顯示 ERROR,因為重複建立名為 mytable 的資料表。

你必須用 MySQL 的 Command Line Client 輸入:

DROP TABLE mytable

將資料表刪除,才能再執行成功一次。


在 JSP 使用 SQL 指令

Java 使用 java.sql.Statement 提供的三個方法來操作 SQL 指令:

java.sql.Statement

executeUpdate("SQL 指令")用來操作 INSERT、DELETE、UPDATE 指令。
executeQuery("SQL 指令")用來操作 SELECT 指令。
execute("SQL 指令")其它 SQL 指令。

在 JSP 取用 SQL 資料

Java 使用 java.sql.ResultSet 來保存 java.sql.Statement.executeQuery() 所傳回 SELECT 指令的資料,讓我們在程式中可以更靈活操作資料。

ResultSet 提供的操作方式

getRow()取得游標位置
next()向下移動游標
previous()向上移動游標
relative(int)上下移動游標,以正負值控制。
absolute(int)設置游標位置。
beforFirst()游標移到最前一筆的位置。
afterLast()游標移到最後一筆的位置。
first()游標移到資料開始的位置。
last()游標移到資料結束的位置。
isBeforFirst()游標是否在最前一筆的位置。
isAfterLast()游標是否在最後一筆的位置。
ifFirst()游標是否在資料最開始的位置。
ifLast()游標是否在資料已結束的位置。
deleteRow()刪除欄位資料。
refreshRow()更新前的資料。
getFetchSize()取得可包含最大資料筆數。

但在那之前,你必須知道 java.sql.Connection 的 createStatement() 可接受 resultSetType 和 resultSetConcurrency 兩個參數,前者用來設定游標的移動方式,後者用來設定資料是否可以改寫。

經過適當的設定,才有辦法使用前面所列的功能。

ResultSet 的 resultSetType 常數

TYPE_FORWARD_ONLY游標只能向下移動。
TYPE_SCROLL_INSENSITIVE游標可上下移動,當其它 ResultSet 搬動資料時同步影響游標位置。
TYPE_SCROLL_SENSITIVE游標可上下移動,當其它 ResultSet 搬動資料時不影響游標位置。

ResultSet 的 resultSetConcurrency 常數

CONCUR_READ_ONLYResultSet 的資料唯讀。
CONCUR_UPDATABLEResultSet 的資料可更改。