當用戶登錄系統時,在日志表中插入一條記錄,記錄用戶登錄的時間,在用戶退出系統時記錄用戶退出系統的時間。
我們利用HttpSessionBindingListener接口來完成記錄登錄和退出日志的功能,該接口中定義了兩個方法:
·valueBound(HttpSessionBindingEvent event)
·valueUnbound(HttpSessionBindingEvent event)
如果一個類實現了HttpSessionBindingListener接口,當對象通過session.setAttribute()被綁定到Session中時,則對象的接口方法valueBound()被自動調用,當對象從session中移出時(通過調用session.invalidate()、session.removeAttribute()或session自動過期時),valueUnbound()方法將被自動調用。
下面我們使User.Java類實現HttpSessionBindingListener接口,調整后的代碼如下所示:
代碼清單 18 實現了HttpSessionBindingListener的User.java
1. package bookstore; 2. import javax.Servlet.http.HttpSessionBindingListener; 3. import javax.servlet.http.HttpSessionBindingEvent; 4. import java.sql.*; 5. import java.text.SimpleDate表單at; 6. import java.util.Date; 7. 8. public class User implements HttpSessionBindingListener 9. { 10. … 11. private String loginDatetime;//用戶登錄時間 12. … 13. public void valueBound(HttpSessionBindingEvent event) 14. { 15. Connection conn = null; 16. String sqlStr = "insert into T_LOGIN_LOG(ID, USER_ID, DT_LOGIN) " + 17. " values(SEQ_LOGIN_LOG_ID.NEXTVAL,?,? )"; 18. try 19. { 20. conn = DBConnection.getConnection(); 21. PreparedStatement pStat = conn.prepareStatement(sqlStr); 22. loginDatetime = getCurrDatetimeStr(); //當前時間串 23. pStat.setString(1, userId); 24. pStat.setString(2, loginDatetime); 25. pStat.executeUpdate(); 26. 27. } catch (SQLException e) 28. { 29. throw new RuntimeException( 30. "用戶登陸日志寫入出錯"); 31. } finally 32. { 33. try 34. { 35. if (conn != null) 36. { 37. conn.close(); 38. } 39. } catch (SQLException ex) 40. { 41. ex.printStackTrace(); 42. } 43. } 44. } 45. 46. public void valueUnbound(HttpSessionBindingEvent event) 47. { 48. Connection conn = null; 49. String sqlStr = " update T_LOGIN_LOG set DT_LONOUT = ? " + 50. " where USER_ID=? and DT_LOGIN = ?"; 51. try 52. { 53. conn = DBConnection.getConnection(); 54. PreparedStatement pStat = conn.prepareStatement(sqlStr); 55. pStat.setString(1, getCurrDatetimeStr()); 56. pStat.setString(2, userId); 57. pStat.setString(3, loginDatetime); 58. pStat.executeUpdate(); 59. 60. } catch (SQLException e) 61. { 62. throw new RuntimeException( 63. "用戶退出日志寫入出錯"); 64. } finally 65. { 66. try 67. { 68. if (conn != null) 69. { 70. conn.close(); 71. } 72. } catch (SQLException ex) 73. { 74. ex.printStackTrace(); 75. } 76. } 77. } 78. 79. //獲取當前時間字串,以yyyyMMddHHmmss格式返回,如20050505010101 80. private static String getCurrDatetimeStr() 81. { 82. SimpleDate表單at sdf = new SimpleDate表單at("yyyyMMddHHmmss"); 83. return sdf.表單at(new Date()); 84. } 85. } |
valueBound()方法向T_LOGIN_LOG表插入一條登錄日志,在valueUnbound()方法中更新日志表的退出時間,此外第80~84行提供了一個獲取當前時間串的方法getCurrDatetimeStr(),通過該方法獲取登錄和退出時間點的時間字符串。
下面通過描述用戶登錄系統直到退出時所經歷的步驟說明程序如何記錄用戶的登錄和退出時間的:
1.用戶通過login.JSP輸入密碼登錄后,程序轉向switch.jsp控制頁面。
2.在switch.jsp中,我們通過session.setAttribute("ses_userBean", userBean)方法將User.java類的對象userBean綁定到session中。
3.此時userBean對象的HttpSessionBindingListener接口方法valueBound()被調用,向T_LOGIN_LOG表插入一條登錄日志。
4.switch.jsp轉向welcome.jsp頁面。
5.用戶點擊welcome.jsp頁面中的鏈接退出系統時,轉向quit.jsp頁面。
6.quit.jsp調用session.invalidate()方法,userBean對象從session中清除。
7.此時userBean對象的HttpSessionBindingListener接口方法valueUnbound()方法被調用,更新日志的退出時間,關閉瀏覽器窗口。
HttpSessionBindingListener接口是Web容器的事件接口,實現接口的類在某個事件發生時自動被調用,Web容器有多個這樣的事件接口,它們分別是:
·ServletContextListener 接口:Web容器啟動和銷毀的事件處理接口,接口中定義了兩個方法。
·ServletContextAttributeListener接口:Web上下文屬性發生更改時的事件處理接口。
·HttpSessionListener接口:Session創建和銷毀事件的事件處理接口。
·HttpSessionAttributeListener接口:Session會話中屬性對象更改的事件處理接口,該接口和我們在前面使用的HttpSessionBindingListener接口相似。
此外在J2EE1.4中還提供了另外兩個事件處理接口,它們是:
·ServletRequestListener接口:Request請求對象創建和銷毀事件處理接口。
·ServletRequestAttributeListener接口:更改Request中屬性對象時的事件處理接口。
程序部署
在Web程序開發完成后,我們開始著手程序部署的工作,我們希望將這個Web應用程序部署到Tomcat5.0的Web應用服務器中。
首先我們設置Web應用程序的默認首頁,然后再將整個Web程序打成一個WAR檔案文件包。
1.設置默認訪問的頁面,雙擊工程窗格中的webModule節點,JBuilder在內容窗格顯示如下的頁面:
![]() 圖 26 設置Web程序默認訪問的頁面 |
點擊Welcome files列表右邊的Add…按鈕,在彈出的對話框中錄入login.JSP并按確定按鈕,將login.jsp頁面作為默認頁面,這樣web.XML部署描述文件中將新增以下粗體的部署信息:
代碼清單 19 Web應用程序默認頁面
1. … 2. <web-app> 3. <display-name>webModule</display-name> 4. <welcome-file-list> 5. <welcome-file>login.jsp</welcome-file> 6. </welcome-file-list> 7. … 8. </web-app> |
當用戶在URL中沒有指定具體的訪問文件名時,Web容器自動查看URI下是否有login.jsp文件,如果直接調出這個文件。
2.在工程窗格中的資源樹中右擊webModule節點,Properties…->Build->在Build設置面中,將Build Web archive設置為When building project or module選項,如下圖所示:
![]() 圖 27 設置在Rebuild工程或Web模塊時創建WAR檔案文件 |
3.在工程窗格中右擊chapter13.jpx,在彈出的菜單中選擇Rebuild編譯整個工程。
4.編譯完成后,在工程根目錄下將產生一個webModule.war文件。
5.拷貝webModule.war文件至<JBuilder2005安裝目錄>/thirdparty/jakarta-tomcat-5.0.27/webapps目錄下。
這樣就完成Web應用程序的部署了,下面我們啟動Tomcat 5.0 Web應用程序服務器,并訪問剛才部署的webModule.war應用程序。
1.雙擊<JBuilder2005安裝目錄>/thirdparty/jakarta-tomcat-5.0.27/bin下的startup.bat啟動Tomcat 5.0 Web應用服務器(請保證這時JBuilder中沒有運行Web應用程序,以免沖突)。
2.打開IE,鍵入http://localhost:8080/webModule,將正確訪問到剛才部署的Web應用程序,如下圖所示:
![]() 圖 28 部署后login.jsp的訪問效果 |
Tomcat 服務器默認工作于8080端口,所以在機器名后需要添加端口號,可以通過更改Tomca位于conf目錄下的server.xml配置文件可以更改這個端口號。
由于我們的web應用程序的WAR文件名為webModule.war,web服務器啟動后,會自動將WAR文件解壓到webModule目錄下,所以必須通過http://localhost:8080/webModule訪問。此外,由于默認訪問頁面為login.jsp,所以沒有指定具體的頁面時,login.jsp頁面被調用訪問。