創建自己的基於 Java 的滾動橫幅廣告
站長注
<?xml version=
<!DOCTYPE web
<web
<servlet>
<servlet
<servlet
</servlet>
<servlet
<servlet
<url
</servlet
</web
dbHandler
改為
dbHandler
dbHandler
改為
dbHandler
象 這樣的公司依靠在 Web 上提供橫幅廣告服務已經賺了很多錢
當因特網開始從教育和政府信息存儲器轉變成國際商業中心起
無論您怎麼看待 Web 橫幅廣告(是的
有些公司(如 )已經通過擔當應用程序服務供應商(ASP)
當然
安裝 Tomcat 和 MySQL
在這一節中
安裝 Tomcat
下載並安裝 Tomcat
安裝了 Tomcat 之後[installdir]\webapps
目錄下創建一個名為 banner
的子目錄banner
子目錄下
[installdir]\webapps\banner
[installdir]\webapps\banner\WEB
接下來/banner
banner
子目錄webapps
下的頂級 banner 目錄。tW.Wingwit.cOM如果他想運行我們的 BannerServlet
(將存在於 WEB-INF/classes
目錄中),他可以使用 /localhost:8080/banner/BannerServlet。
要添加 /banner
context,首先,我們需要編輯 Tomcat conf
目錄中的 server.xml 文件。 在<Host>和</host>之間加上
<!-- BannerAd Context -->
<Context path="/banner" docBase="banner"
debug="0" reloadable="true" crossContext="true"/>
添加了 context 標記之後,重新啟動 Tomcat 以使對 server.xml 文件所做的更改生效.
安裝 MySQL
MySQL 因其價格(免費)而成為一種強有力的數據庫,許多公司都使用 MySQL 來處理它們的數據。由於許多公司都想以較低的預算進入 Web 市場,所以使用 MySQL 的公司的數量每天都在增加。開放源碼社區已張開雙臂歡迎 MySQL。有關這個功能強大的數據庫的文檔十分豐富,而且同時有 Linux 和 Windows 版本。
下載並安裝 MySQL(站長下載了mysq 5.0.28 )
使 MySQL 和 Tomcat 共同工作
使 MySQL 和 Tomcat 相互通信可能有些困難。然而,通過使用 JDBC API,我們將能夠相對容易地從 Java 類使用 SQL 與 MySQL 數據庫通信。
首先,要從這裡下載驅動程序的合適的 JAR 文件。下載名為mysql-connector-java-5.0.0-beta.zip 的文件。接下來,將文件解壓縮(unjar 或 unzip)至一個臨時目錄。最後,將包含驅動程序的文件從解壓縮的目錄結構復制到 WEBAPPS/BANNER/WEB-INF/lib
目錄中,然後重新啟動 Tomcat。在我們下載的驅動程序版本中,文件的名稱是mysql-connector-java-5.0.0-beta-bin.jar
我們本可以使用 JDBC/ODBC 橋驅動程序與 MySQL 通信,但我們認為本機驅動程序在性能上有更大優勢(盡管我們沒有運行任何基准測試程序來證實我們的假設)。對於這個應用程序,在性能上它可能不會有很大區別,但我們決定演示如何使用本機 JDBC 驅動程序,以便您不必在設計較大的應用程序時才去了解它。
滾動橫幅應用程序
既然我們已經安裝了所有的軟件,就讓我們來看一下這個應用程序能夠做什麼以及我們是如何組織其架構和開發它的。
實質上,您可以使用我們的橫幅 servlet 執行兩個操作。首先,您可以用它查看 Web 頁面上的隨機橫幅圖像,每次裝入包含橫幅廣告的 Web 頁面時,該隨機橫幅圖像就會出現。其次,您可以點擊橫幅圖像,這將使您轉至與裝入的這個圖像對應的鏈接。
按照 HTML,其代碼類似於:
<a >
<img src="...Random Image..."/>
</a>
如果希望裝入隨機圖像,那麼顯然圖像標記不能指向靜態圖像文件,因此我們將指示它運行 servlet,本例中將調用 BannerServlet。我們將使用 HTTP GET
方法參數來指示 servlet 為我們提供圖像。因此,圖像標記類似於:
<img src=//localhost:8080/banner/servlet/BannerServlet?type=image"/>
該標記調用 servlet 並傳入參數鍵值對 type=image
。servlet 的 service()
方法會解釋該請求,然後向浏覽器返回隨機圖像。當然,servlet 必須以某種方式記住將哪個圖像發送給了客戶機,這樣當客戶機點擊該圖像時,它就知道應鏈接至何處。我們會把與發送的圖像相關的元數據存儲在客戶機的會話上,這樣,當用戶點擊圖像時,將從他的會話裝入元數據,並重新導向至適當的 URL。
鏈接標記看起來幾乎與圖像標記相同:
<a >
<img src=//localhost:8080/banner/servlet/BannerServlet?type=image"/>
</a>
當用 type=link
鍵值對調用 servlet 時,servlet 抓取橫幅的元數據並將用戶重新路由至適當的 URL。
代碼和 CLASSPATH 設置
為了使用與本文一起提供的代碼,您必須首先解壓縮這個 zip 文件,然後用命令行 javac
編譯器或您喜歡的 IDE 編譯這些.java
文件。要編譯該代碼,請設置 CLASSPATH
以包含這兩個 JAR 文件(站長注:第二個就行了)。
mysql-connector-java-5.0.0-beta-bin.jar
servlet.jar
(如果它沒有和您使用的 JDK 打包在一起)
將已編譯的 .class
文件復制到先前創建的 [tomcat_installdir]\webapps\banner\WEB-INF\classes
目錄中。必須將作為示例提供的圖像文件和 < 文件放入 [tomcat_installdir]\webapps\banner
目錄。
數據庫設置
我們應用程序的數據庫部分只是用來持久存儲系統中每個橫幅的元數據。換句話說,我們實際上並不在數據庫中存儲圖像文件,而只是存儲指向每個圖像文件的引用。在我們的數據庫中,我們將使用七個列來描述每個橫幅廣告。
表 1 中的描述說明了每條記錄將包含的內容。我們實際上將在應用程序中只使用這七個數據庫列中的五個。我們的版本中沒有使用 CustomerName
和 NumberOfClicksPurchased
,但我們把它們作為占位符放置在這裡以用於擴展。您可以很容易地擴展這個應用程序,並把它用於現實的商業應用程序,其中客戶為每個橫幅的點擊次數付款。
表 1. 數據庫字段 字段名稱 描述 示例 ImageFile 對橫幅圖像物理位置的引用 /images/sitea.gif URL 站點用戶點擊橫幅之後,應重新路由他們的目標 URL 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);
ADS 表的“describe”操作類似於圖 1 所示。
圖 1. ADS 表
您需要用一些樣本值來填充數據庫以便確定所構建的數據庫是否正確。該項目的 zip 文件中包括一些樣本橫幅(GIF 格式),可以使用它們以了解應用程序運行時的情況。當然,對於 Web 橫幅 URL,需要聲明您決定放置橫幅文件的位置。可以按照下面的 SQL 語法將橫幅“注冊”到數據庫中:
mysql> insert into ADS values('/sitea.gif','',
'John Doe',100,100,0,10);
使用這一語法將表 2 中顯示的記錄插入到數據庫中。
表 2. 數據庫記錄
IMAGEFILE
sitea.gif
siteb.gif
sitec.gif
sited.gif
URL
/
/
/
/
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:\\localhost\BANNER
)。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 文件,從而允許擴充或更改查詢定義而無需編寫更多代碼。
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28120.html