Web 應用程序中的主頁和 servlet
現在准備好將第二個 Web 頁面、一個 servlet 及其關聯的 ConnectionPool 類與現有的單個頁面 Web 應用程序集成。下面是配置 Web 服務器的步驟。
我們將把新的 JSP 頁面添加到應用程序。需要再次啟動應用程序組裝工具(Application Assembly Tool(AAT)),然後裝入 Test_war.ear 文件,該文件是先前為 TestTeam.Html 頁面而創建的。
展開 Test_war、Web Modules、DB2TestSample 和 Files,然後選擇 Resource Files。單擊鼠標右鍵,然後選擇 Add Files 選項。只需要象先前添加 TestTeam.Html 一樣將 TestMain.JSp 添加在 Webdirectory 中。這個 JSP 文件還使用 bgsnd.mid 和 blob.gif 資源文件。同樣,象先前所做的那樣,需要從 resource 目錄中選擇這些文件。
保存文件。
請注意 圖 5中的倒數第二行:JSP:include。 因為我們還沒有准備好 JSP,所以您需要編輯那個文件並刪除那一行。稍後我們將把它添加回去。這一步“非常”重要,不要跳過,否則 TestMain.JSP 頁面將無法在浏覽器中工作。
回到 Administration Console。展開 Enterprise Application,然後選擇 TestSample。單擊鼠標右鍵,然後單擊 Stop。在它停止後,再次重復這些步驟,只不過這次選擇 Remove。
在 Console 菜單項中依次選擇 Wizards 和 Install Enterprise Application。象以前所做的一樣,裝入 Test_war.ear 文件。
轉至 Nodes,選擇您的節點,然後單擊鼠標右鍵。選擇 Regen Webserver plugin。
現在選擇 Application Servers,然後選擇 Default Server。在 Stop 上單擊鼠標右鍵,然後單擊 Start 再次開始。
打開所選的 Web 浏覽器。輸入 URL:http://your-Machine-name/testTeam/Web/TestTeam.html。迅速出現 TestTeam.Html 頁面。這次的區別是:8 秒後顯示的不是錯誤頁面而是 TestMain.JSP 頁面。Anakin Skywalker 現在一定很興奮。
注:在實際的 Web 環境下,您不會將源代碼放在 servlets 目錄中,而只會放入 .class 文件或者包含這些類文件的 .jar 文件。為了簡單起見,我已將源代碼都放在了一起。理想情況下,將在單獨的目錄中編譯源文件,並且將僅復制運行 Web 所需的可執行代碼。
同樣,在上面添加 .class 文件的步驟中,您必須確保在 Root Directory 域中輸入正確路徑。如果不這樣做,您將以“servlets”結尾作為路徑的一部分,而這並不是我們希望的。
先前我們從 TestMain.jsp 中除去了 JSP:include 這一行以裝入並運行 JSP 屏幕。現在,我們將把它添加回去。這將是 servlet 代碼的第一段。我們將添加新的 Web 組件, 添加類文件,然後創建 servlet 映射。
在 servlets 目錄中有文件 DBBean.java 和 ConnectionPool.java。我們所做的 前期步驟之一是安裝 Java 開發者工具箱(JDK)。為了編譯 servlet Java 代碼,現在需要修改 CLASSPATH 環境變量。我們需要向其添加 <install-path>/aPPServer/lib/j2ee.jar;。這最好是通過選擇桌面上的 My Computer->PropertIEs 然後選擇 Advanced 選項卡,接下來選擇 Environment Variables 按鈕來完成。在 System Variables 部分選擇 CLASSPATH,然後選擇 Edit 按鈕。在 variable value 域,添加 <install-path>/aPPServer/lib/J2EE.jar;。按三次 OK 按鈕。
需要對已編寫、復制和修改的 Java 代碼進行編譯。打開一個 MS-DOS 命令提示窗口,然後切換至有樣本代碼的目錄。輸入命令 javac DBBean.Java。這將在當前目錄生成 DBBean.class 和 ConnectionPool.class 文件。
通過選擇 Start->Programs->WebSphere->Application Assembly Tool 從桌面 Start 菜單啟動 AAT。裝入 Test_war.ear 文件。
展開 Web Modules、DB2TestSample 和 Files。在類上單擊鼠標右鍵,然後選擇 Add Files。現在,我們將添加這兩個類文件。在 Root Directory 中輸入到這兩個類文件的路徑:<samples-path>/servlets。按 Enter 鍵。
選擇 ConnectionPool.class 然後按 Add 按鈕。對 DBBean.class 文件采用相同操作,然後按 OK 按鈕。
回到 AAT,現在您將看到添加的兩個類文件。接下來,我們要添加 DBBean servlet 作為 Web 組件。選擇 DB2TestSample 項下的 Web Components。在其上單擊鼠標右鍵,然後選擇 New。
在 Component Name 中輸入 DBBean。可選地輸入顯示名稱和描述。
在 Component Type 下選擇 Servlet 單選按鈕。在 classname 域中輸入 DBBean,或者按 Browse 按鈕,然後選擇 DBBean。按 OK 按鈕。
現在我們要添加一個 servlet 映射。在 AAT 左窗格中選擇 Servlet Mapping。單擊鼠標右鍵,然後選擇 New。在顯示的對話框中,URL Pattern 域中輸入 /DBBean。在 Servlet 域中輸入 ../DBBean。按 OK 按鈕。URL 名稱是浏覽器所期望的。在我們的例子中,這是我們在 TestMain.jsp 文件內指定的。WebSphere 通過剛創建的 servlet 映射將 URL 映射成實際的 servlet 名稱。請注意,我們在 servlet 名稱前添加“../”,因為 servlet“別名”到 JSP 的相對路徑是“../”;即,JSP 在 testTeam/Web 目錄中,而 servlet 別名是 testTeam。
在 File 菜單項下選擇 Save 按鈕。
現在,我們需要將新更改的應用程序安裝到 WebSphere 和 Web 服務器中。啟動 WebSphere Administration Console。
要安裝保存在 AAT 工具中的新版本,我們先除去現有版本,然後添加新版本。展開 Enterprise Application,然後選擇 Test_war 項。單擊鼠標右鍵,然後選擇 Remove。
選擇 Console 菜單項,然後依次選擇 Wizards 和 Install Enterprise Application。選擇 Install application (*.ear) 單選按鈕。輸入到 Test_war.ear 文件的路徑,或者使用 browse 按鈕來查找它。
單擊 Next 按鈕直到 Finish 按鈕處於激活狀態。然後按 Finish 按鈕。
您將看到 WebSphere Application 控制台的左窗格用新的應用程序更新過了。
現在展開 Nodes 項,然後展開您的機器名稱項。在機器名稱上單擊鼠標右鍵,然後選擇 Regen WebSphere plugin。
轉至 Start->Settings->Control Panel。選擇 Administrative Tools。
雙擊 Services。向下滾動到 IBM HTTP Server,單擊鼠標右鍵,然後選擇 Stop,或者從菜單欄選擇 STOP 圖標。
它停止後,再次啟動它,強制它啟用我們所做的更改。
返回 Administration Console,從左窗格的 Enterprise Applications 節點下選擇 Test_war。單擊鼠標左鍵,然後選擇 START。
至此,完成了安裝步驟。現在,讓我們進行測試來看看它是否工作。從 MS-DOS 命令提示窗口輸入命令 DB2JSTRT 3456。這將啟動端口 3456 上的 DB2 JDBC 偵聽器,該端口就是我們所說的這個應用程序將用來與服務器通信的端口。這需要在正在運行 Web 服務器的機器上完成,該機器可以是正在運行浏覽器和/或 DB2 服務器的機器,也可以不是這樣的機器。
啟動 Web 浏覽器,然後輸入我們主頁的 URL:http://your-Machine-name/testTeam/Web/TestTeam.Html。就象在初始測試中那樣,我們會看到主頁大約出現 8 秒鐘,然後將自動出現 TestMain.JSP 頁面。這裡的實際問題是“servlet 正確運行了嗎?”。故障的第一個跡象是顯示在 Web 浏覽器中的錯誤消息。如果那裡沒有顯示任何信息,則查看 <WebSphere-install-path>/logs 目錄中的 Default_server_stdout.log 和 Default_Server_stderr.log 文件。滾動到底部。您會看見 DBBean: init 項,然後是成功或錯誤消息。如果 DB 連接成功,應該會在 Default_Server_stdout.log 文件中看到 DBBean : made connection pool。
注:日志中的常見錯誤是連接到 DB2 時用戶標識或密碼不正確。這是因為您沒有編輯 DBBean.Java 並將用戶標識、密碼以及數據庫 URL 更改成您的安裝值。
它的外觀如何?
圖 7中的 Internet Explorer 抓屏顯示了正在運行的應用程序,並顯示主頁或至少它的大部分。注意鏈接的顏色,它基於對 BODY 標記的定義,與 一些真正的 Html:TestMain.JSP 主頁所描述的一樣。還請注意,由於表對齊域,所以表單中的所有按鈕都和按鈕功能的文本描述一樣排列整齊。如果您的機器有發聲功能,則會聽到音樂在播放。最重要的是,滾動到浏覽器屏幕的底部,並確保沒有顯示任何錯誤。DBBean servlet 應該已經運行並連接到數據庫。
如果您熟悉數據庫,則可以發出 DBSTOP 命令,然後啟動 Web 浏覽器和應用程序。在本例中,因為數據庫沒有在運行,所以數據庫連接會失敗。您會看見一些故障指示。使用 DB2START 命令重新啟動數據庫。還可以查看 <install-path>/aPPServer/logs 目錄下的 XXXXstderr.log 文件。使用 Notepad 或類似編輯器浏覽該文件。轉至底部。您應該“不”會看到任何 SQL 錯誤。如果看到了,則 DBBean servlet 失敗。
圖 7:應用程序的主 Web 頁面
下一步是什麼?
如果回過頭看一下 圖 3,您會看到我已經討論了前兩個頁面:TestTeam.html 和 TestMain.JSp 以及由 TestMain.JSP 調用的 DBBean servlet。為了節省空間,我將不詳細論述 TestMSP.Html、TeamStruct.JSp、TeamStructCl servlet 和 RawData.JSP 文件。我將簡要描述 RawData servlet 的一點信息,如 圖 6所示。
幾乎應用程序中那些片段的每個功能都在下面的類似情況中進行了描述。文件 TestMSP.html 只是顯示了當前測試計劃的 HTML 表示,這樣測試組外的人員可以知道我們在做什麼。文件 TeamStruct.html 顯示了團隊的組織,例如誰進行什麼工作。它還顯示用於各種軟硬件環境的各種測試機器,包括每台機器上測試的產品和發行版。文件 TeamStruct.Html 包含 TeamStruct.jsp。這個 JSP 調用 TeamStructCl servlet。JSP 顯示表的第一部分,它顯示了每個產品的測試用例總數、Java、C/C++、64 位、自動的、手工的、UI 的數目以及其它總數。填充這個表的實際數字是從 TSTCASES 數據庫表通過 TeamStructCl servlet 抽取的,並且使用 Html 表標記進行格式化。
象先前所做的那樣,再次啟動 AAT 以添加上面的 JSP 和 Html 文件。這次,我們還將從 resources 目錄添加所有其它 *.jpg 文件,因此我將不通過名稱列出它們。現在,一起添加它們比每次進行更改更容易。因為我們要添加 TeamStructCl servlet 和 DBaccess servlet(由 TeamStructCl servlet 使用),所以我們還需要遵循 上面的步驟以在 AAT 中注冊 servlet。不要忘記為 TeamStructCl 添加 servlet 映射。我們不需要為 ConnectionPool 或 DBAccess Java 文件添加映射,因為它們不是真正的 servlet,只是由 servlet 調用以執行實用程序任務的 Java 代碼。它們不象這個示例中的 servlet 那樣生成任何 Html。
保存文件,然後遵循上面的步驟從 WebSphere Administration Console 中刪除應用程序,接著再次添加應用程序。這將應用更改。不要忘記像 上面完成的那樣重新生成並停止/重新啟動 HTTP 服務器。
RawData JSP 和相應的 servlet 用來滿足那些想看到每段最新可用信息的人們的需要。從數據庫中抽取數據,然後按列顯示數據,而不進行任何格式化或合並。完成該任務的代碼是從 CoreServlets 一書以及參考資料中提到的網站中復制並稍作修改。我在 DB2 UDB Application Development Certification Guide 中也發現了相似的代碼。 圖 8 的第一列顯示了一種接收行數據和列數據並將數據格式化成 Html 表的 Java 方法。注意第 8-10 行,for(int col=0; col<columnCount; col++) buffer.append("<TH>" + columnNames[col]);它在表的頂部顯示了列名。第 11-17 行顯示了被放入表中各列的實際數據。在第 11-17 行中,您還將看到一個以行為索引的外部循環以及一個以列為索引的內部循環。
第二列,方法 getQueryResults() 從 DB2 獲取實際數據。列名被放入字符串數組 ColumnNames 中,如第 8-12 行所示。第 8-12 行設置了正確的環境,以便第 20-31 行可以獲取列名。第 5-7 行中的語句顯示了從 DB2 抽取的數據,而第 20-31 行接收這些數據並將其存儲在一個字符串數組的向量(即二維數組)中。
包含這個示例代碼的原因是為了顯示使用這麼少的代碼可以完成多少工作。用這兩個簡單的方法抽取行數據並進行格式化。
圖 8 — RawData servlet
1 public String toHtmlTable(String headingColor) {
2 StringBuffer buffer = new StringBuffer
3 ("<TABLE BORDER=1>\n");
4 if (headingColor != null) {
5 buffer.append(" <TR BGCOLOR=\"" +
6 headingColor + "\">\n ");
7 } else buffer.append(" <TR>\n");
8 for(int col=0; col<columnCount; col++)
9 buffer.append("<TH>" + columnNames
10 [col]);
11 for(int row=0; row<getRowCount(); row++) {
12 buffer.append("\n <TR>\n ");
13 String[] rowData = getRow(row);
14 for(int col=0; col<columnCount; col++)
15 buffer.append("<TD>" + rowData
16 [col]);
17 }
18 buffer.append("\n</TABLE>");
19 return(buffer.toString());
20 } 1 public void getQueryResults() {
2 Connection c = Access.getConn();
3 try {
4 DatabaseMetaData dbMetaData = c.getMetaData();
5 Statement stm = c.createStatement();
6 ResultSet rs = stmt.executeQuery("SELECT *
7 FROM TSTRSLTS");
8 ResultSetMetaData resultsMetaData =
9 rs.getMetaData();
10 columnCount = resultsMetaData.getColumnCount();
11
12 columnNames = new String[columnCount];
13
14
15 for (int i=1; i<columnCount+1; i++)
16 columnNames[i-1] =
17 resultsMetaData.getColumnName(i).trim
18 ();
19
20 rowData = new String[columnCount];
21 queryResults = new Vector();
22
23 while(rs.next()) {
24 String[] row = new String[columnCount];
25 for(int i=1; i<columnCount+1; i++) {
26 String entry = rs.getString(i);
27 if (entry != null) entry = entry.trim();
28 row[i-1] = entry;
29 }
30 addRow(row);
31 }
32 return;
33 } catch(SQLException sqle) { System.out.println
34 ("Error : " + sqle);
35 return; }
36 }
37 }
現在,我們正如對上面的 TeamStruct 例子所做的那樣添加 RawData.JSP 和 RawDataCl servlet。
象編譯其它 Java 文件那樣編譯 RawDataCl.Java。
象上面完成的那樣啟動 AAT,然後重復上面的步驟。
將 .JSP 添加到 resources 目錄的文件列表中。
將 .class 添加到 classes 目錄的文件列表中。
將 .class 作為 Web Component 添加。
將 .JSP 作為 Web Component 添加。
為 .class 文件添加 servlet 映射。
按 AAT 中的 save 按鈕。
轉至 WebSphere Admin Console,刪除現有的 Test 應用程序,然後使用向導裝入新的應用程序。
不要忘記重新生成插件,接著停止 IBM HTTP 服務器,然後重新啟動它。
我不打算一步一步地分別完成這些步驟,因為它們與先前的步驟一樣,只是 Java 源文件名已改變(以保持簡單!)。請注意,我們沒有編譯 DBaccess.java。文件 TeamStructCl.java 和 RawDataCl.java 引用文件 DBaccess.java。這樣,編譯這兩個 .java 文件的任何一個時,也會編譯引用的文件 DBAccess.java。如果願意使用同一 Javac 命令,則可以編譯它。
TeamStruct servlet 從 DB2 UDB 中的 TSTCASES 表裝入數據。在運行應用程序,然後單擊 Team Structure 按鈕之前,我們應該 把數據填充到表中。這是在本文開始期間就完成的,因此只要驗證是否完成了那些步驟。
這把我們帶到 Test Results 按鈕,它是這個應用程序起實際作用的部分。頁面上的許多鏈接都是到簡單的 Html 頁面、JSP 和 servlet。這個按鈕把我們帶到產生顯示測試數據的各種格式的 JSP。 圖 3很好地顯示了這一點,因為 TestResults.jsp 在其下面包含許多 JSP 和 servlet。下面的 圖 9顯示了 TestResults.JSP。
圖 9:TestResults.JSP
1 <Html><HEAD><TITLE>Test Results</TITLE></HEAD>
2 <body text="#FF0000" bgcolor="#FFFFFF" link="#FF00FF" vlink="#F00000" alink="#FF8080"
3 background="../resources/whtmarb.jpg">
4 <center><table><td><IMG SRC="/School/UploadFiles_7810/201105/20110503092305203.gif" height=34 width=34></td>
14 <td><font color="#3333FF"><font size=+1><a href="#Custom">Custom 15Query</a></font></font>
15 </td></tr>
16
17 </table><hr SIZE=4 WIDTH="100%">
18
19 <table><tr><td BGCOLOR="#99FF99"><b> <JSP:include page="../TestTeamCl"
20 flush="true" /></table></form><hr>
21
22 <h2> <a NAME="Custom"><font color="#FF0000">Custom Query</font></h2>
23 <font color="#3366FF">Enter a product and platform to see history for this combination.</font>
24 <FORM METHOD="post" ACTION="Custom.JSP">
25 <p>Product : <INPUT TYPE="text" NAME="product" VALUE="Distributed Debugger" SIZE="30"
26 MAXLENGTH="40">
27 Platform : <INPUT TYPE="text" NAME="platform" VALUE="NT" SIZE="15" MAXLENGTH="15"></p>
28 <INPUT TYPE="submit" NAME="SUBMIT" ID="SUBMIT" VALUE="SUBMIT"></form>
29 <hr></center></BODY></Html>
這個 JSP 被分成由空白行分隔的幾節。正如使用上面描述的 TestMain.JSp 一樣,有一個包含標題、一些圖片以及用於各種域和熱鏈接的顏色設置的標題信息。緊接著標題的一節是一張由三行組成的表。每行都非常相似,執行同一功能。那個功能是到頁面後面某一節的快速鏈接。因此,這裡有通過 JSP 顯示的三節的三個鏈接。第二個鏈接,第 10-12 行,是 <tr><td><img SRC="/School/UploadFiles_7810/201105/20110503092306531.gif" height=34 width=34></td><td><font color="#3333FF"><font size=+1><a href="#Platform">Summary by Platform</a></font></font></td></tr>。這是由封閉的 <tr>...</tr>定義的單個行。在這行內有兩個由封閉的 <td>...</td>定義的列。第一列顯示類似於 的圖標,它只是標識行的一種花哨的方法。
第二列包含文本,該文本作為到後續頁面中某一節的鏈接(超文本鏈接)。通過單擊鏈接,頁面會滾動到那一節。在這個例子中,它將滾動到第 11 行中標記為 #Platform 的那一節。# 意味著鏈接位於同一頁面;沒有在另一個 URL 上找到鏈接。因為在這個表中有三行,所以在這個 Web 頁面中有三節。看一下 圖 9,您可能想知道這三個頁面的位置在哪裡以及為什麼 #Platform 是同一頁面中的鏈接而任何地方都沒有 Platform 的標號。答案在第 19-20 行:<JSP:include page="../TestTeamCl" flush="true" />。它包括位於這一位置的 TestTeamCl servlet 輸出。
看一下第 19-20 行周圍的標記,我們看見一些標記沒有匹配的結束標記。例如,有開始一行一列的 <tr><td>,但卻沒有匹配的結束一行一列的 </td></tr>。類似地,有表示粗體文本開始的 <b>。但是,沒有表示粗體文本結束的 </b>。這一問題的答案是匹配的結束標記在 servlet 中產生。請注意,第 19-20 行中 JSP 周圍的開始和結束標記注明哪些文本創建並終止表。除了我剛提到的初始的幾項以外,servlet 填充表的大部分信息。這個 JSP 中的標記與那些由 servlet 生成的標記的組合就是 Web 浏覽器和最終用戶所看到的。當您運行應用程序時產生這個頁面,然後使用浏覽器的 VIEw Source 功能。您將會看見包含來自 JSP 和 servlet 的所有標記的整個頁面。
在第 22 行中,標記 <a NAME="Custom"> 是標號的一個示例。我提到了三個標號,這是三個中的最後一個。在第一個表中,可以看到 #Custom,它是到頁面中這一節的鏈接。
最後,我想討論一下第 24-28 行:<FORM METHOD="post" ACTION="Custom.JSp"> <p>Product : <INPUT TYPE="text" NAME="product" VALUE="Distributed Debugger" SIZE="30" MAXLENGTH="40"> Platform : <INPUT TYPE="text" NAME="platform" VALUE="NT" SIZE="15" MAXLENGTH="15"></p><INPUT TYPE="submit" NAME="SUBMIT" ID="SUBMIT" VALUE="SUBMIT"></form>。這是一個 FORM 標記,用於允許選擇一個按鈕,將信息傳遞到那個特定按鈕所鏈接的目標頁面。在這個例子中有兩個文本域和一個按鈕。按下按鈕時,將文本域的內容傳遞到目標頁面,在本例中是由 ACTION= fIEld 指定的 Custom.JSP。許多 Html 書籍以及在參考資料一節中提到的網站上都詳盡地描述了表單。簡而言知,INPUT TYPE= 域定義了域是什麼類型,在這個示例中是 TEXT 或 SUBMIT。text 類型意味著可以通過浏覽器在那裡輸入文本。submit 類型意味著現在將調用由 action 標識的頁面。VALUE 域是傳遞到下一頁面的信息。可以象我在這裡所做的那樣指定初始的缺省值。因此,對於 product,缺省值為 Distributed Debugger。類似地,對於 platform,缺省值為 NT。
圖 10:TestTeamCl servlet 代碼片斷
1 /*
2 Written by Ed Van Gennip. IBM Canada Limited. 2000
3 Purpose : Extract from DB2 product and platform test results and
4 display the results is two tables. Format these tables (Html
5 tags) and pass back to TesTReslts.JSP.
6 */
7
8 import Java.io.*;
9 import Javax.servlet.*;
10 import Javax.servlet.http.*;
12 import Java.sql.SQLException;
13
14 public class TestTeamCl extends HttpServlet{
15 private DBaccess Access;
16
17 public TestTeamCl() { }
18
19
20 public void init() { access = new DBAccess(getServletContext()); }
21
22 public void doGet(HttpServletRequest httpServletRequest,
23 HttpServletResponse httpServletResponse)
24 throws ServletException, IOException {
25 httpServletResponse.setContentType("text/Html");
26 printWriter pW = httpServletResponse.getWriter();
27 try { Access.startAction(); }
28 catch (SQLException e1) {
29 System.out.println(new StringBuffer("SQL Exception : ").
30 append(e1).toString());
31 }
32 String astring[] = Access.getLastDateAndDriver();
33 pW.println("<font size=+1>Last Update</font></b></td>");
34 pW.println("<td>");
35 if (astring == null) pW.println("No drivers found");
36 else pW.println(astring[0].substring(0, 19));
37 pW.println("</td><td BGCOLOR=\"#99FF99\"><b>");
38 pW.println("<font size=+1>Latest Debug/OLT
39 Driver</font></b></td>");
40 pW.println("<td>");
41 if (astring == null) pW.println("No drivers found");
42 else pW.println(astring[1]);
43 pW.println("</td></tr></table>");
44 pW.println("<h2><a NAME=\"Platform\"><font color=\"#FF0000\">
45 Summary by Platform</font></h2>");
46 pW.println("<font color=\"#3366FF\">Summary by platform across
47 all products for the driver shown above which ship on that
48 platform. The button in the PLATFORM fIEld takes you to
49 the details for that platform and its history.</font>");
50 pW.println("<FORM METHOD=\"post\"
51
52 ACTION=\"Web/Platform.JSP\">");
53 pW.println("<table BORDER=3 BGCOLOR=\"#CCCCCC\">");
54 pW.println("<tr BGCOLOR=\"#99FF99\">");
55 pW.println("<td><b>PLATFORM</b></td>");
56 pW.println("<td><b>Total TC</b></td>");
57 pW.println("<td><b>Passed #/%</b></td>");
58 pW.println("<td><b>Failed #/%</b></td>");
59 pW.println("<td><b>Not run # %</b></td></tr>");
60 if (astring != null) {
61 putPlatRow(Access, pW, "Windows", astring[1]);
62 putPlatRow(Access, pW, "AIX4.3.3", astring[1]);
63 putPlatRow(Access, pW, "AIX5.0L", astring[1]);
64 ...........
65 putPlatRow(Access, pW, "S/390", astring[1]);
66 }
67 pW.println("</table></form><hr>");
68 ...
69 try { Access.endAction(); }
70 catch (SQLException e2) {
71 System.out.println(new StringBuffer("SQL Exception :")
72 .append(e2).toString());
73
74 }
75 }
76
77 private void putPlatRow(DBaccess dBAccess,
78 printWriter pW, String string1, String string2) {
79 pW.println("<tr><td><INPUT TYPE=\"submit\"
80 NAME=\"PLATFORM\" VALUE=\""+string1 + "\"></td>");
81 int an[] = dBAccess.queryTotalsByPlatformDriver(string1,
82 string2);
83 if (an == null) { pW.println("</tr>"); return; }
84 pW.println("<td><center>"+an[0] + "</center></td>");
85 int i = an[1] + an[2];
86 if (i > 0) {
87 pW.println("<td><center>"+an[1] + "/" + an[1] * 100 / i +
88 "</center></td>");
89 pW.println("<td><center>"+an[2] + "/" + an[2] * 100 / i +
90 "</center></td>");
91 } else {
92 pW.println("<td><center>"+an[1] + "/0</center></td>");
93 pW.println("<td><center>"+an[2] + "/0</center></td>");
94 }
95 if (an[0] > 0)
96 pW.println("<td><center>"+an[3] + "/" + an[3] * 100 / an[0]
97 + "</center></td>");
98 else
99 pW.println("<td><center>"+an[3] + "/0</center></td>");
100 pW.println("</tr>");
101 }
102 }
起實際作用的 servlet
已經提到過 TestTeam servlet,現在應該介紹它了。因為 servlet 變得更長更復雜,所以我無法在這裡包含整個代碼,但是它包含在 .zip 文件中。在這裡包含了我想描述的主要部分。大多數未包含的片斷都是重復的。這就是我將說明的例子以及原因。
正如先前提到的,我將描述這個 servlet 的各個方面,然後留給您去徹底地閱讀和了解它。第一點要注意的是第 15 行:private DBaccess access;,它告訴我們涉及到了另一個類 DBAccess。這個類是真正的起實際作用的類,因為它執行所有數據庫查詢並處理任何更新。源代碼包含在 .zip 文件中但不在這裡,因為要描述的內容太多。下面是安裝這個代碼以在 WebSphere 中執行的步驟。
當第一次裝入 servlet,第一次實例化時,調用 servlet 的 init() 方法,如第 20 行所示,public void init() { access = new DBaccess(getServletContext());}。這創建了 DBaccess 對象,它在 servlet 的生命期內保持活動。可以在第 27 行:access.startAction(); 看見 DBaccess 類的第一次使用,我們可以在其中看見 startAction 方法的調用。這個方法簡單地通過調用 ConnectionPool 方法連接到數據庫。在後面的第 32-43 行中,語句 access.getLastDateAndDriver(); 再次調用 DBAccess 類。在這個例子中,它正在對數據庫進行查詢以檢索上次數據庫更新的日期和驅動程序名稱。接下來的幾行顯示了如何對查詢返回的結果進行查錯,然後進行格式化以便顯示。將生成的 Html 標記和文本傳遞到 pW — printWriter 對象。這個對象用於將文本和標記傳遞到浏覽器以便顯示。輸出類似於 圖 11。
第 50-59 行顯示了表單的構造以及顯示在表中的列名。表位於表單中。表的第一列是按鈕列表。每個平台(即 Windows、AIX、Solaris 等)有一個按鈕。其余的列包含該平台的總結數據。通過選擇一個按鈕,可以將您帶到一個新的頁面 Platform.jsp,它是作為 FORM 標記上的 ACTION 參數列出的。這個 JSP 顯示了那個平台的詳細測試結果。類似地,還有一節顯示了產品而不是平台的總結測試結果。由於這一節與平台代碼非常相似,所以這裡已經從 servlet 中除去以節省空間。有一點區別是:產品表單的 ACTION 參數指向 product.jsp。這兩個級聯的 JSP,每一個都有一個相應的 sevlet:Platform.java 和 Product.java。這些 servlet 通過調用 JSP 來完成所顯示表的填充工作。下面描述了 Product.java。因為 Platform.java 與 Product.Java 非常相似,所以沒有進行描述。
第 60-65 行包含語句 putPlatRow(access, pW, "Windows", astring[1]);,它是在這個 servlet 中對 putPlatRow 方法的一系列調用。還顯示了 putPlatRow 方法。這個方法用於對上面提到的表中列的總結數據進行查詢和格式化。有一個類似的方法 putProdRow(...),它完成的功能相同,但是它基於產品而不是平台。每個調用傳遞一個不同平台,查詢基於該平台的測試數據。 putPlatRow 方法通過 dBAccess.queryTotalsByPlatformDriver(string1, string2); 調用從數據庫獲取數據,如代碼樣本所示。DBAccess 類方法 queryTotalsByPlatform 執行查詢,然後將數據作為整數數組返回,其中每個整數對應於顯示表中的一列。類似地,對於產品表,有 queryTotalsByProductDriver 方法。
最後幾行接收由 queryTotalsByPlatformDriver 調用返回的值數組,然後對它們進行格式化以便顯示。請注意額外的邏輯,該邏輯處理對於特定方案沒有測試用例的情況,即,測試用例數為零。以我的數學知識,我記得除數最好不為零。putProdRow 方法存在相似的邏輯,該邏輯從 queryTotalsByProductDriver 方法獲取其結果數組。
既然了解了這個 servlet 是什麼,就需要將它和 TestResults.jsp 添加到 WebSphere Web 服務器。即使沒有准備好 Platform.jsp 和 Product.jsp,我們仍然可以集成 TestResults.jsp 和 TestTeamCl servlet。因為在安裝第一個 JSP 和 servlet 時完成了大部分工作,所以這些步驟非常簡單。我們只需要遵循上面安裝 TeamStruct JSP 和 TeamStructCl servlet 所完成的相同步驟。除了更改名稱外,步驟完全相同。我們還遵循完全相同的步驟,從 AAT 保存 .ear 文件,將它裝入 Admin Console,重新生成 HTTP 服務器,重新啟動 HTTP 服務器,然後通過執行下列步驟來測試它:
啟動浏覽器,或者如果它已在運行,則用它訪問 http://your-Machine-name/testTeam/Web/TestTeam.Html,其中您可以選擇 TestResults 按鈕來調用 TestResults.JSP 從而調用 TestTeamCl servlet。
圖 11:TestTeamCl servlet 的部分輸出和標題
Last Update 2001/04/20 15:32:22 Latest Debug/OLT Driver 20010411b
如果您選擇 Platform 和 Product 表中任何按鈕,將顯示錯誤。這是因為我們還沒有為 Platform 和 Product JSP 編寫這些按鈕要調用的代碼,也沒有編寫相應的 servlet。因此,這就是下一步。