程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> 關於MYSQL數據庫 >> 用Tomcat和MySQL生成動態內容詳解

用Tomcat和MySQL生成動態內容詳解

編輯:關於MYSQL數據庫

當因特網開始從教育和政府信息存儲器轉變成國際商業中心起,橫幅廣告就已經出現了。滾動橫幅是 Web 頁面上一塊已分配的空間,每次裝入或重新裝入 Web 頁面時,就用該空間內來顯示廣告 ― 隨機顯示或基於某些業務邏輯來顯示。驅動滾動橫幅廣告的程序雖然相當簡單,但卻是重要的廣告工具。正如它們的同類,如半分鐘廣播和電視廣告一樣,這些動態廣告工具允許單個 Web 頁面顯示不同來源的廣告,並使不同公司針對相同的觀眾建立他們產品和服務的品牌效應。

無論您怎麼看待 Web 橫幅廣告(是的,我們都發現它們有時令人討厭),它們已成為因特網上的一種生活方式。存在這樣的事實:Web 的觀眾由龐大的消費者群體所組成,他們的金錢使電子商務的車輪得以轉動。在因特網市場營銷的短暫歷史中,電子商務所有者已表現出他們願意花大把的錢在熱門站點上做橫幅廣告。

有些公司(如 doubleclick.Net)已經通過擔當應用程序服務供應商(ASP),提供諸如跟蹤對特定橫幅廣告的點擊之類的服務,從 Web 橫幅現象中獲利。隨後這些 ASP 告訴廣告客戶他們的 Web 廣告活動的有效程度。

當然,象 doubleclick.Net 這樣的 ASP 是要收費的。如果您和我們一樣,那麼您不會願意在能夠免費得到服務時還要花錢。稍等一會兒 ― 您可能已經聽過世上沒有免費的午餐這句話。不過別擔心。本文將花費的只是您的時間。事實上,我們將向您演示如何組成一個開放源碼(即 免費)環境來建立您自己的功能強大的 Web 橫幅跟蹤系統。為了完成這一任務,我們挑選的“武器”是 Tomcat、MySQL、一個 Java servlet 和幾個助手類。興奮嗎?那麼,讓我們進行軟件安裝吧。

安裝 Tomcat 和 MySQL

在這一節中,我們將逐步介紹 Tomcat 和 MySQL 的安裝。然後,我們將向您介紹如何安裝支持這兩個應用程序相互通信所需的驅動程序。

安裝 Tomcat

下載並安裝 Tomcat。對於本文,我們使用了 Tomcat 4.1 Windows 版,它有一個很好的安裝軟件包,並且會為您創建圖標和 Start 菜單文件夾。它還創建一個用於啟動和停止 Tomcat 服務器的“Windows 服務(Windows Service)”。安裝應該非常簡單,但如果您遇到麻煩,請查閱 Tomcat 文檔。

安裝了 Tomcat 之後,還要完成幾個步驟以設置我們的滾動橫幅 Web 應用程序。首先,我們將在 [installdir]webaPPS 目錄下創建一個名為 banner 的子目錄。然後在 banner 子目錄下,創建標准的 Web 應用程序目錄結構:

[installdir]webaPPSbanner
[installdir]webaPPSbannerWEB-INF
[installdir]webaPPSbannerWEB-INFclasses
[installdir]webaPPSbannerWEB-INFlib

接下來,我們將添加指向我們 Web 應用程序的 context。context 只是一個別名,它告訴 Tomcat 在哪裡可以訪問 Web 應用程序。我們的 context 路徑將是 /banner ,它將指向我們剛剛創建的 banner 子目錄。在用戶輸入 http://localhost:8080/banner 後,將轉至 webaPPS 下的頂級 banner 目錄。如果他想運行我們的 BannerServlet (將存在於 WEB-INF/classes 目錄中),他可以使用 http://localhost:8080/banner/servlet/BannerServlet 。

要添加 /banner context,首先,我們需要編輯 Tomcat conf 目錄中的 server.XML 文件。在接近該文件底部的位置,您會看到幾個 context 標記。那裡應該有一個用於 /admin 的 context 和一個用於 /examples 的 context。

添加了 context 標記之後,重新啟動 Tomcat 以使對 server.XML 文件所做的更改生效(在我們的示例中,我們只重新啟動 Tomcat 安裝的 Windows 服務)。

安裝 MySQLs

MySQL 因其價格(免費)而成為一種強有力的數據庫,許多公司都使用 MySQL 來處理它們的數據。由於許多公司都想以較低的預算進入 Web 市場,所以使用 MySQL 的公司的數量每天都在增加。開放源碼社區已張開雙臂歡迎 MySQL。有關這個功能強大的數據庫的文檔十分豐富,而且同時有 Linux 和 Windows 版本。

下載並安裝 MySQL,采用“Typical”安裝選項進行安裝(對於本文,我們假定您使用 MySQL 的 WinNT 版本)。完成安裝後,您將注意到 MySQL 一個惱人的方面:它沒有在 Start 菜單中放入任何東西。您需要到數據庫的安裝目錄(缺省情況下是 c:mysql )下,然後轉至 bin 目錄,在那裡您會找到運行 MySQL 的可執行文件。

首先,雙擊 winmysqladmin.exe 文件。首次打開該文件時,會要求您輸入用戶名和密碼。接下來,在任務欄中出現的紅綠燈圖標上單擊鼠標右鍵。轉至 WinNT 並選擇“Start the service”以使 MySQL 在後台運行。最後,雙擊“mysql.exe”圖標以啟動“MySQL Monitor”,您將在此使用 MySQL。

使 MySQL 和 Tomcat 共同工作

使 MySQL 和 Tomcat 相互通信可能有些困難。然而,通過使用 JDBC API,我們將能夠相對容易地從 Java 類使用 SQL 與 MySQL 數據庫通信。

我們將使用 MM MySQL JDBC 驅動程序(一個開放源碼驅動程序),使 MySQL 和 Tomcat 之間的通信變得容易。(在撰寫本文時,2.0.14 是其最新版本。)

遺憾的是,安裝該驅動程序略微有些麻煩。首先,要從 這裡下載該驅動程序的合適的 JAR 文件。我們下載了名為 mm.mysql-2.0.14-you-must-unjar-me.jar 的文件。接下來,將文件解壓縮(unjar 或 unzip)至一個臨時目錄。最後,將包含驅動程序的文件從解壓縮的目錄結構復制到 WEBAPPS/BANNER/WEB-INF/lib 目錄中,然後重新啟動 Tomcat。在我們下載的驅動程序版本中,文件的名稱是 mm.MySQL-2.0.14-bin.jar 。

我們本可以使用 JDBC/ODBC 橋驅動程序與 MySQL 通信,但我們認為本機驅動程序在性能上有更大優勢(盡管我們沒有運行任何基准測試程序來證實我們的假設)。對於這個應用程序,在性能上它可能不會有很大區別,但我們決定演示如何使用本機 JDBC 驅動程序,以便您不必在設計較大的應用程序時才去了解它。

滾動橫幅應用程序

既然我們已經安裝了所有的軟件,就讓我們來看一下這個應用程序能夠做什麼以及我們是如何組織其架構和開發它的。

實質上,您可以使用我們的橫幅 servlet 執行兩個操作。首先,您可以用它查看 Web 頁面上的隨機橫幅圖像,每次裝入包含橫幅廣告的 Web 頁面時,該隨機橫幅圖像就會出現。其次,您可以點擊橫幅圖像,這將使您轉至與裝入的這個圖像對應的鏈接。

如果希望裝入隨機圖像,那麼顯然圖像標記不能指向靜態圖像文件,因此我們將指示它運行 servlet,本例中將調用 BannerServlet。我們將使用 HTTP GET 方法參數來指示 servlet 為我們提供圖像。

該標記調用 servlet 並傳入參數鍵值對 type=image 。servlet 的 service() 方法會解釋該請求,然後向浏覽器返回隨機圖像。當然,servlet 必須以某種方式記住將哪個圖像發送給了客戶機,這樣當客戶機點擊該圖像時,它就知道應鏈接至何處。我們會把與發送的圖像相關的元數據存儲在客戶機的會話上,這樣,當用戶點擊圖像時,將從他的會話裝入元數據,並重新導向至適當的 URL。

當用 type=link 鍵值對調用 servlet 時,servlet 抓取橫幅的元數據並將用戶重新路由至適當的 URL。

代碼和 CLASSPATH 設置

為了使用與本文一起提供的代碼,您必須首先解壓縮這個 zip 文件(在 參考資料中),然後用命令行 javac 編譯器或您喜歡的 IDE 編譯這個 .Java 文件。要編譯該代碼,請設置 CLASSPATH 以包含這兩個 JAR 文件。

mm.mySQL-2.0.14-bin.jar (或從 MM MySQL 網站獲取的其它任何版本)


servlet.jar (如果它沒有和您使用的 JDK 打包在一起)
將已編譯的 .class 文件復制到先前創建的 [tomcat_installdir]webappsbannerWEB-INFclasses 目錄中。必須將作為示例提供的圖像文件和 .htm 文件放入 [tomcat_installdir]webaPPSbanner 目錄。

數據庫設置

我們應用程序的數據庫部分只是用來持久存儲系統中每個橫幅的元數據。換句話說,我們實際上並不在數據庫中存儲圖像文件,而只是存儲指向每個圖像文件的引用。在我們的數據庫中,我們將使用七個列來描述每個橫幅廣告。

表 1 中的描述說明了每條記錄將包含的內容。我們實際上將在應用程序中只使用這七個數據庫列中的五個。我們的版本中沒有使用 CustomerName 和 NumberOfClicksPurchased ,但我們把它們作為占位符放置在這裡以用於擴展。您可以很容易地擴展這個應用程序,並把它用於現實的商業應用程序,其中客戶為每個橫幅的點擊次數付款。

表 1. 數據庫字段

字段名稱 描述  示例
ImageFile 對橫幅圖像物理位置的引用 /images/sitea.gif
URL  站點用戶點擊橫幅之後,應重新路由他們的目標  URL http://www.sitea.com
CustomerName 購買橫幅的客戶名稱  John Doe
NumberOfClicksPurchased 用戶購買的點擊次數 140
NumberOfClicksRemaining 客戶剩余的點擊次數 139
NumberOfImpressions 橫幅已被顯示的次數 23
BannerWeight 正在顯示的這一橫幅的權重  10


當然,在現實環境中,您會有一個以上的站點橫幅。根據您的橫幅“贊助商”支付的金額與其他贊助商的比較,您可能希望較多地或較少地顯示他的橫幅。 BannerWeight 字段將被用來實現這一功能。我們已經實現了一個非常簡單的加權系統,每個要顯示的橫幅所具有的百分比概率為:

(BannerWeight / Sum of all BannerWeights) * 100

將剛才所說的內容轉換成 SQL,您可以使用 MySQL Monitor 輸入以下語句:

MySQL> create database BANNER;

要連接到數據庫,您可以輸入:

MySQL> use BANNER;

接下來,我們創建表:

MySQL> create table ADS
(IMAGEFILE VARCHAR(50) NOT NULL,
URL VARCHAR(50) NOT NULL,
CUSTOMERNAME VARCHAR(50),
NUMBEROFCLICKSPURCHASED INT(4),
NUMBEROFCLICKSREMAINING INT(4) NOT NULL,
NUMBEROFIMPRESSIONS INT(4) NOT NULL,
BANNERWEIGHT INT(4) NOT NULL);

您需要用一些樣本值來填充數據庫以便確定所構建的數據庫是否正確。該項目的 zip 文件中包括一些樣本橫幅(GIF 格式),可以使用它們以了解應用程序運行時的情況。當然,對於 Web 橫幅 URL,需要聲明您決定放置橫幅文件的位置。可以按照下面的 SQL 語法將橫幅“注冊”到數據庫中:

MySQL> insert into ADS values('/sitea.gif','http://www.cnn.com',
'John Doe',100,100,0,10);

IMAGEFILE sitea.gif siteb.gif sitec.gif sited.gif
URL http://www.cnn.com http://www.news.com http://www.ibm.com http://www.yahoo.com
CUSTOMERNAME John Doe Albert Einstein Jane Doe Madonna
NUMBEROFCLICKSPURCHASED 100 20 30 20
NUMBEROFCLICKSREMAINING 100 20 30 20
NUMBEROFIMPRESSIONS 0 0 0 0
BANNERWEIGHT 10 10 30 10

注:Web 橫幅 URL 位於本地主機,僅供測試之用。在生產環境中,URL 會指向 GIF 文件的實際位置。該 URL 實際上可以是因特網上的任何位置。

既然我們有了數據庫,就需要使用剛剛填入其中的數據。我們將用 Java servlet 做到這一點。下面描述 Java servlet 代碼,它將“推動”我們的努力。您或許希望花一些時間來通讀該項目 zip 文件中的 BannerServlet.Java 代碼。如果您覺得困難,別擔心;我們將花一些時間解釋代碼是如何工作的。

橫幅體系結構

這個橫幅廣告 servlet 的體系結構十分簡單。我們將使用四個類:

通用的 Logger 類,一個將日志消息寫到文本文件的類。

名為 BannerServlet 的 servlet,每次顯示橫幅圖像(即每次裝入頁面)和每次點擊橫幅圖像時,將調用它。該 servlet 是我們應用程序的核心。

通用的 DBHandler 類, BannerServlet 將用它與 MySQL 數據庫進行通信。

Banner 類,我們用它來創建對象,這些對象包含數據庫中每個橫幅所擁有的所有元數據。
該 BannerServlet 類和 Banner 類特定於我們的應用程序。它們相當簡單,您可以方便地擴展它們來添加更復雜的特性。

DBHandler 和 Logger 類的好處在於:您可以在任何您實際編寫的、需要與數據庫通信或寫入日志文件的應用程序中重用這兩個類。

我們將更詳細地討論所有這四個類,這樣您就可以理解 servlet 是如何工作的,以及它如何使用 DBHandler 與 MySQL 數據庫通信。

Logger 類

Logger 類非常簡單。它有單個字段,代表我們正在寫入日志的 File 對象。您可以將對單個 Logger 對象的引用傳遞給幾個類,讓這些類都寫入同一個日志文件。 Logger 類允許您做以下事情。您可以:

創建日志記錄器(logger)對象
向日志文件添加分隔符(“------”字符串)
通過傳入調用方法的名稱和日志消息添加一條日志項
添加方法啟動的缺省消息
添加方法結束的缺省消息
刪除日志文件
返回由日志記錄器對象使用的 File 對象
我們將同時在 DBHandler 類和 BannerServlet 中使用 Logger 對象。

DBHandler 類

DBHandler 是非常多用途的類,可用來通過 JDBC 與幾乎任何數據庫進行相互操作。它需要一個具有 JDBC/ODBC 驅動程序(我們正用此驅動程序來連接到數據庫)名稱的字符串、一個具有數據庫(我們為其設置了 DSN)名稱的字符串和一個 Logger 參數。 Logger 參數在 DBHandler 完成其“神奇”任務時告訴它在哪裡打印輸出消息。 DBHandler 的構造器打開到數據庫的連接。在使用 DBHandler 完成任務後,必須用 close() 方法關閉它。

在創建了 DBHandler 對象之後,必須創建查詢來執行。使用 setQueryString() 方法傳入包含查詢的字符串,查詢可以是 PreparedStatement 類的形式。

PreparedStatement 是 JDBC 的一個很好的功能。它允許您定義一個查詢字符串,使用問號字符替代查詢中的變量標准。隨後可以使用 PreparedStatement 類的 setter 方法來設置查詢中未知元素的值。幸運的是, DBHandler 類為我們處理所有這些事情。我們只需設置想要執行的查詢,然後調用 DBHandler 的某個方法,如下所示:

public Banner getBannerByName(String name) {
...
...
dbHandler.setQueryString("SELECT * FROM ADS WHERE NAME=?");
ResultSet rs = dbHandler.lookup(name);
dbHandler.close();
...
...
}

可以使用 lookup() 方法來執行 SELECT 查詢,使用 executeUpdate() 方法來執行 UPDATE 查詢,以及使用 insert() 方法來執行 INSERT 查詢。還有一個 execute() 方法,它不需要參數,可以執行任何沒有 PrepareStatement 參數的查詢。

Banner 類

Banner 類只是一組直接對應於 ADS 數據庫表中各列的值的 setter 和 getter 方法。

BannerServlet 類

BannerServlet 是我們這個應用程序的核心。我們將把該類分成幾個不同部分來向您講解。通過浏覽代碼,您將對如何用 DBHandler 類連接到數據庫更加熟悉。

字段
BannerServlet 使用五個字段:

String _databaseUrl:要訪問數據庫的名稱( jdbc:odbc:localhostBANNER )。

String _driverName:用來與數據庫通信的驅動程序的名稱。正如上面所描述的那樣,我們將使用 MM MySQL JDBC 驅動程序。該驅動程序的名稱是 org.gjt.mm.MySQL.Driver 。

Logger _logger: Logger 類的名稱,用此類來記錄我們應用程序中發生的所有事件。

HashMap _banners:所有 Banner 對象的 HashMap。用 servlet 的 init() 方法填充該 HashMap。將數據庫表中的每一行轉換成存儲在 HashMap 中的一個 Banner 對象。我們過一會兒將詳細說明這一點。

int _totalWeight:所有 Banner 權重之和。該值也是在 init() 方法中設置的;我們將很快討論這一點。
init()
任何 servlet 的 init(ServletConfig) 方法都在容器首次裝入該 servlet 時被調用。在這裡,容器就是 Tomcat。Tomcat 生成並傳入 ServletConfig 對象,該對象包含容器設置的缺省配置信息以及開發人員(您)在 servlet 的配置文件中可以進行設置的定制配置信息。對於我們的用途,不需要傳入任何配置信息,但您有時可能需要擴展 servlet,並使用這一功能。

我們調用 super.init() 之後在 init() 中所做的第一件事是初始化 HashMap 變量 _banners ,並將 _totalWeight 設置為 0。然後,連接到數據庫,以 ResultSet 的形式從 ADS 表獲取所有行。我們使用 for 循環對 ResultSet 進行循環遍歷,從每行構造一個 Banner 對象,接著,把 for 循環的索引作為散列值,將 Banner 對象添加到 HashMap。(我們也可以方便地使用 Vector 或其它一些 Collection 類來完成同樣的任務。)

現在,內存中有了一個包含所有 Banner 的 HashMap。如果更新數據庫,那麼只需調用 init() 方法就可重新裝入 HashMap。我們將在 increaseImpressions() 和 decreaseClicksRemaining() 方法中用到這一點。

service()
service() 方法是在我們的 BannerServlet 繼承的 HttpServlet 類中定義的,可以處理任何請求,不管它是 GET 方法還是 POST 方法。對於 service() 方法的實現有兩個核心部分。第一個部分處理 Web 頁面發送圖像請求時 servlet 的行為,第二部分處理鏈接請求。

最後,我們看一下從客戶機發送來的 type 參數。如果 type 的值是 image ,那麼我們從數據庫獲取一個隨機的 Banner 對象,將該 Banner 對象添加到用戶的會話,同時增加這一給定橫幅的已顯示次數,並將用戶路由至 Banner 對象的圖像字段中所引用的圖像。

如果 type 的值是 link ,那麼我們從會話中除去 Banner 對象,減少該橫幅的剩余點擊次數,並將用戶重定向至 Banner 對象的 URL 字段中指定的鏈接。

其它方法
getRandomBanner() 、 increaseImpressions() 和 decreaseClicksRemaining() 都是助手方法,從 service 方法中調用它們。 getRandomBanner() 使用一個簡單的算法從 _banners HashMap 隨機地選擇一個橫幅。 increaseImpressions() 和 decreaseClicksRemaining() 使用 DBHandler 連接到數據庫並更新給定 Banner 的信息。在這兩個方法的結束部分,我們調用 init() 方法將已更新的 Banner 信息重新裝入到 HashMap。

結束語

我們已經創建一個應用程序,該應用程序演示了 apache Tomcat 和 MySQL 相互之間如何通信,並向您提供了一個能為您處理大多數數據庫工作的、非常有用的可重用工具。您可以以幾種方式來擴展這個應用程序,這些已超出本文的范圍。正如我們前面描述的那樣,您可以把這個應用程序擴展成一個系統,在這個系統中,您可以根據特定點擊次數或者甚至是特定的顯示次數向客戶收費。可以很容易地用某個其它字段替代數據庫中的 CustomerName 字段,這個字段可以是另一個包含所有客戶信息的表中的主鍵。

您可以擴充 DBHandler 類以處理數據庫連接合用。此外,可以將希望用於應用程序的查詢具體化成文本、特性或 XML 文件,從而允許擴充或更改查詢定義而無需編寫更多代碼。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved