日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
Servlet在session中共享鏈接

問題所在

創(chuàng)新互聯(lián)專注于企業(yè)成都全網(wǎng)營(yíng)銷推廣、網(wǎng)站重做改版、新干網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、HTML5建站、商城網(wǎng)站開發(fā)、集團(tuán)公司官網(wǎng)建設(shè)、成都外貿(mào)網(wǎng)站制作、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為新干等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。

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

在這些 Servlet 中都需要讀寫數(shù)據(jù)庫。如果我們?cè)诿總€(gè) Servlet 中都進(jìn)行連接 -> 讀寫 -> 斷開連接的操作,就會(huì)消耗大量的服務(wù)器資源,不僅程序響應(yīng)速度減緩,而且會(huì)加重服務(wù)器和數(shù)據(jù)庫的負(fù)擔(dān)。

把希望寄托于HttpSession

如我們所學(xué),Servlet API 提供了一些方法和類來專門處理短期的會(huì)話跟蹤。網(wǎng)站的每個(gè)用戶都和 Javax.Servlet.http.HttpSession 對(duì)象有關(guān),Servlet使用這個(gè)對(duì)象來記錄和檢索每個(gè)用戶的信息。

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

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

安全問題

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

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

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

理論上,沒有問題。在 Servlet1 中產(chǎn)生的 Connection 對(duì)象,到了 Servlet2 中可以繼續(xù)使用。

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

解決之道

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

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

相應(yīng)的,在 session 的屬性中,我們不再保存 connection 本身,而是把這個(gè)保管者存進(jìn)去。因?yàn)樗茈S時(shí)給我們一個(gè)可用的 connection。

這個(gè)類的具體寫法是:

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

使用方法

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

如果有的話,直接調(diào)用它的get方法,取得數(shù)據(jù)庫連接。

如果沒有的話,說明這個(gè)session還沒有連接過數(shù)據(jù)庫,那么當(dāng)前類就立刻創(chuàng)建一個(gè)數(shù)據(jù)庫連接,并把這個(gè)連接交給保管者,然后再把保管者放入 session 中,以便后續(xù)的 Servlet 使用。

下面是一個(gè)實(shí)例:

 
 
 
  1. protected void doGet(HttpServletRequest req, HttpServletResponse res)  
  2. throws ServletException, IOException {  
  3. // 同步代碼取得數(shù)據(jù)庫連接  
  4. synchronized (session) {  
  5. // 看看這個(gè)持有者是否已經(jīng)在 session 中了  
  6. ConnectionHolder holder = (ConnectionHolder) session.getAttribute  
  7. ("servletapp.connection");  
  8. // 如果不在,就創(chuàng)建一個(gè)數(shù)據(jù)庫連接,并把它交給持有者。  
  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. // 錯(cuò)誤處理代碼  
  17. }  
  18. }  
  19. // 從容器取得實(shí)際連接  
  20. conn = holder.getConnection();  
  21. }  
  22. .... // 別忘了commit  

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

誰來負(fù)責(zé)斷開連接?

當(dāng) Servlet 們不必再為創(chuàng)建數(shù)據(jù)庫連接費(fèi)心的時(shí)候,也就沒有人愿意管關(guān)閉連接這檔子事了。事實(shí)上,更重要的是,他們沒法管。因?yàn)檫@個(gè)連接是放在 session 中的,而沒有誰能準(zhǔn)確的預(yù)測(cè),一個(gè) session 會(huì)何時(shí)終止。

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

這兩個(gè)方法可以在一個(gè) session 被創(chuàng)建/失效的時(shí)候分別自動(dòng)執(zhí)行。我們就把關(guān)閉連接的代碼放在第二個(gè)方法中,這樣,當(dāng)一個(gè) session 失效的時(shí)候,數(shù)據(jù)庫連接就會(huì)自動(dòng)關(guān)閉。

要想讓一個(gè)類成為L(zhǎng)istener,只需讓它實(shí)現(xiàn) HttpSessionBindingListener 接口。我們的 connection 是由 ConnectionHolder 這個(gè)類來保管的,因此最方便的辦法就是把它注冊(cè)成一個(gè)監(jiān)聽器。

具體方法是:

 
 
 
  1. public void valueUnbound(HttpSessionBindingEvent event) {  
  2. // 當(dāng)從Session刪除或當(dāng)Session結(jié)束時(shí),關(guān)閉數(shù)據(jù)連接。  
  3. try {  
  4. if (con != null) {  
  5. con.rollback(); // 放棄所有未提交的數(shù)據(jù)  
  6. con.close();  
  7. }  
  8. }  
  9. catch (SQLException e) {  
  10. // 錯(cuò)誤處理代碼  
  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. // 錯(cuò)誤處理代碼  
  29. }  
  30. }  
  31. public Connection getConnection() {  
  32. return con;  
  33. }  
  34. public void valueBound(HttpSessionBindingEvent event) {  
  35. // 當(dāng)增加Session時(shí),什么也不做  
  36. }  
  37. public void valueUnbound(HttpSessionBindingEvent event) {  
  38. // 當(dāng)從Session刪除或當(dāng)Session結(jié)束時(shí),關(guān)閉數(shù)據(jù)連接。  
  39. try {  
  40. if (con != null) {  
  41. con.rollback(); // 放棄所有未發(fā)送數(shù)據(jù)  
  42. con.close();  
  43. }  
  44. }  
  45. catch (SQLException e) {  
  46. // 錯(cuò)誤處理代碼  
  47. }  
  48. }  
  49. private Connection con = null;  

本文題目:Servlet在session中共享鏈接
文章路徑:http://www.5511xx.com/article/djoecpo.html