成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Servlet在session中共享鏈接

開發 后端
本文介紹Servlet在session中共享鏈接,包括使用方法,安全問題和解決之道等。

問題所在

如果要編寫一個購物車,通常需要寫很多個不同功能的Servlet。例如用戶登錄、添加商品、查詢購物車、結帳等。

在這些 Servlet 中都需要讀寫數據庫。如果我們在每個 Servlet 中都進行連接 -> 讀寫 -> 斷開連接的操作,就會消耗大量的服務器資源,不僅程序響應速度減緩,而且會加重服務器和數據庫的負擔。

把希望寄托于HttpSession

如我們所學,Servlet API 提供了一些方法和類來專門處理短期的會話跟蹤。網站的每個用戶都和 Javax.Servlet.http.HttpSession 對象有關,Servlet使用這個對象來記錄和檢索每個用戶的信息。

幸運的是,我們可以在會話對象中存儲任意的 Java 對象。存儲的方法大家都已經很熟悉,就是使用 setAttribute()方法。代表數據庫連接的Connection也不例外。

這就為我們讓不同的Servlet在session中共享鏈接帶來的希望。

安全問題

那么,僅僅像下面這樣做就可以了么?

1、在Servlet1中,顯示Servlet在session中設置一個屬性:
session.setAttribute("connection", connection);

2、在Servlet2中,取出這個屬性:
Connection connection = (Connection) session.getAttribute ("connection");

理論上,沒有問題。在 Servlet1 中產生的 Connection 對象,到了 Servlet2 中可以繼續使用。

但是如果 Servlet2 不小心改變了 connection 的引用,例如 connection = null; 那么,當它再次把這個connection放入session的屬性當中,其它的 Servlet 就會得到一個指向 null 的 connection!

解決之道

把 connection 直接在 session 中傳來傳去,看來不怎么安全。

解決思路是,我們找一個專門的人來保管這個 connection,在得到請求的時候,由這個人把 connection 的引用返回給調用者。這樣,即使調用者不小心把它得到的那份 connection 搞壞了,保管著手里也總還有一個備份。

相應的,在 session 的屬性中,我們不再保存 connection 本身,而是把這個保管者存進去。因為他能隨時給我們一個可用的 connection。

這個類的具體寫法是:

  1. public class ConnectionHolder {  
  2. public ConnectionHolder(Connection con) {  
  3. // 保存連接  
  4.  
  5. this.con = con;  
  6. try {  
  7. // 禁用自動提交,以隔離不同session之間的操作。  
  8.  
  9. con.setAutoCommit(false);  
  10. }  
  11. catch(SQLException e) {  
  12. // 錯誤處理代碼  
  13.  
  14. }  
  15. }  
  16. public Connection getConnection() {  
  17. // 通過這個getter方法獲取連接  
  18.  
  19. return con;  
  20. }  
  21. private Connection con = null; // 設置為私有變量,這很重要,以確保變量安全。  
  22.  

使用方法

每個 Servlet 在希望取得數據庫連接的時候,先看看Servlet在session中是否有這個“保管者”(即上面的ConnectionHolder)。

如果有的話,直接調用它的get方法,取得數據庫連接。

如果沒有的話,說明這個session還沒有連接過數據庫,那么當前類就立刻創建一個數據庫連接,并把這個連接交給保管者,然后再把保管者放入 session 中,以便后續的 Servlet 使用。

下面是一個實例:

  1. protected void doGet(HttpServletRequest req, HttpServletResponse res)  
  2. throws ServletException, IOException {  
  3. // 同步代碼取得數據庫連接  
  4. synchronized (session) {  
  5. // 看看這個持有者是否已經在 session 中了  
  6. ConnectionHolder holder = (ConnectionHolder) session.getAttribute  
  7. ("servletapp.connection");  
  8. // 如果不在,就創建一個數據庫連接,并把它交給持有者。  
  9. if (holder == null) {  
  10. try {  
  11. holder = new ConnectionHolder(DriverManager.getConnection(  
  12. "Connection URL"));  
  13. session.setAttribute("servletapp.connection", holder);  
  14. }  
  15. catch (SQLException sqle) {  
  16. // 錯誤處理代碼  
  17. }  
  18. }  
  19. // 從容器取得實際連接  
  20. conn = holder.getConnection();  
  21. }  
  22. .... // 別忘了commit  

這段代碼看起來有那么幾行。但實際上,在每個session中,只有第一次執行的Servlet需要進行數據庫連接操作,此后的Servlet只會執行第4、6、20這三行。

誰來負責斷開連接?

當 Servlet 們不必再為創建數據庫連接費心的時候,也就沒有人愿意管關閉連接這檔子事了。事實上,更重要的是,他們沒法管。因為這個連接是放在 session 中的,而沒有誰能準確的預測,一個 session 會何時終止。

好在有一種叫做“監聽器”(Listener)的東西可以專門管這件事。Listener有很多方法,其中的兩個方法是:
◆public void valueBound(HttpSessionBingEvent event);
◆public void valueUnbound(HttpSessionBingEvent event);

這兩個方法可以在一個 session 被創建/失效的時候分別自動執行。我們就把關閉連接的代碼放在第二個方法中,這樣,當一個 session 失效的時候,數據庫連接就會自動關閉。

要想讓一個類成為Listener,只需讓它實現 HttpSessionBindingListener 接口。我們的 connection 是由 ConnectionHolder 這個類來保管的,因此最方便的辦法就是把它注冊成一個監聽器。

具體方法是:

  1. public void valueUnbound(HttpSessionBindingEvent event) {  
  2. // 當從Session刪除或當Session結束時,關閉數據連接。  
  3. try {  
  4. if (con != null) {  
  5. con.rollback(); // 放棄所有未提交的數據  
  6. con.close();  
  7. }  
  8. }  
  9. catch (SQLException e) {  
  10. // 錯誤處理代碼  
  11. }  
  12. }  
  13.  
  14. ConnectionHolder:  
  15.  
  16. import javax.servlet.http.HttpSessionBindingListener;  
  17. import javax.servlet.http.HttpSessionBindingEvent;  
  18. import java.sql.Connection;  
  19. import java.sql.SQLException;  
  20. public class ConnectionHolder implements HttpSessionBindingListener {  
  21. public ConnectionHolder(Connection con) {  
  22. // 保存連接  
  23. this.con = con;  
  24. try {  
  25. con.setAutoCommit(false);  
  26. }  
  27. catch(SQLException e) {  
  28. // 錯誤處理代碼  
  29. }  
  30. }  
  31. public Connection getConnection() {  
  32. return con;  
  33. }  
  34. public void valueBound(HttpSessionBindingEvent event) {  
  35. // 當增加Session時,什么也不做  
  36. }  
  37. public void valueUnbound(HttpSessionBindingEvent event) {  
  38. // 當從Session刪除或當Session結束時,關閉數據連接。  
  39. try {  
  40. if (con != null) {  
  41. con.rollback(); // 放棄所有未發送數據  
  42. con.close();  
  43. }  
  44. }  
  45. catch (SQLException e) {  
  46. // 錯誤處理代碼  
  47. }  
  48. }  
  49. private Connection con = null;  

【編輯推薦】

  1. Future Response Servlet特性
  2. 簡單介紹Servlet實例運行
  3. 淺析ServletQueryForConnPool測試
  4. Tomcat Java Servlet引擎安全設定
  5. Jetty-Servlet容器額外功能
責任編輯:佚名 來源: IT168
相關推薦

2010-07-30 08:25:20

SessionASP.NET

2009-07-08 15:13:00

獲取所session數JSPServlet

2010-07-23 10:01:54

SQL Server

2009-07-08 15:01:00

Servlet Ses

2011-05-07 16:31:17

Windows系統網絡打印機

2009-07-07 16:57:11

2009-08-15 21:22:19

2009-07-02 14:39:27

Session的值JSP Asp.net

2014-12-15 15:07:36

Esri

2011-08-02 13:03:10

服務器DFS

2020-03-20 14:48:46

SpringBootJava分布式

2021-05-31 10:47:17

SpringSecuritySession

2012-11-06 16:51:29

nginx負載均衡

2011-05-07 09:32:31

Tomcat

2015-08-19 15:45:33

2009-07-06 15:19:13

webwork ser

2009-07-09 10:03:40

Servlet應用Weblogic環境

2009-07-07 09:41:02

異步ServletAJAX

2009-02-25 08:30:24

Windows 7Homegroup

2012-05-15 09:31:11

Windows 8IE 10
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲视频在线播放 | 久久久精品一区 | 国产情品| 亚洲在线 | 在线色| 欧美一级视频免费看 | 亚洲综合色 | 国产精品久久久久久吹潮 | 国产在线中文字幕 | 成人午夜视频在线观看 | 嫩草一区二区三区 | 成人免费网站 | 国产婷婷色一区二区三区 | 欧美aaaaaa | 999久久久国产精品 欧美成人h版在线观看 | 亚洲精品乱码久久久久久黑人 | 国产成人精品久久二区二区91 | 亚洲日韩中文字幕一区 | 亚洲乱码一区二区三区在线观看 | 亚洲精品综合 | 人碰人操| 久久久久久久一区二区三区 | 国产午夜精品久久久久免费视高清 | 在线观看亚洲精品 | 亚洲狠狠丁香婷婷综合久久久 | 啪啪毛片 | 欧美精品一二三 | 成人网av | 精品视频免费 | 欧美视频一区 | 欧美久久一区二区三区 | 91精品久久久久久久久久 | 美女视频黄的免费 | 国产黄色小视频 | 国产精品亚洲欧美日韩一区在线 | 在线免费观看毛片 | 欧美午夜一区二区三区免费大片 | 国产午夜在线 | 国产毛片视频 | 精品国产欧美一区二区三区不卡 | 欧美日韩国产三级 |