日韩天天综合网_野战两个奶头被亲到高潮_亚洲日韩欧美精品综合_av女人天堂污污污_视频一区**字幕无弹窗_国产亚洲欧美小视频_国内性爱精品在线免费视频_国产一级电影在线播放_日韩欧美内地福利_亚洲一二三不卡片区

讓不同的Servlet在一個(gè)Session共享連接_JSP教程

編輯Tag賺U幣
教程Tag:暫無(wú)Tag,歡迎添加,賺取U幣!

推薦:講解Linux系統(tǒng)下JDK、Tomcat的安裝
本文詳細(xì)講解Linux系統(tǒng)下JDK、Tomcat的安裝 Jdk安裝: [root@b home]# ls jdk-1_5_0_12-linux-i586-rpm.bin lost found oracle 1、將jdk進(jìn)行解壓 [root@b home]# ./jdk-1_5_0

==== 問(wèn)題所在 ====

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

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

==== 把希望寄托于 HttpSession ====

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

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

這就為我們讓不同的servlet在一個(gè)session內(nèi)共享鏈接帶來(lái)的希望。

==== 安全問(wèn)題 ====

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

1、在Servlet1中,向session中設(shè)置一個(gè)屬性:

session.setAttribute("connection", connection);

2、在Servlet2中,取出這個(gè)屬性:

Connection connection = (Connection) session.getAttribute ("connection");

理論上,沒(méi)有問(wèn)題。在 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 中傳來(lái)傳去,看來(lái)不怎么安全。

解決思路是,我們找一個(gè)專門的人來(lái)保管這個(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è)類的具體寫法是:

public class ConnectionHolder {
public ConnectionHolder(Connection con) {
// 保存連接
this.con = con;
try {
// 禁用自動(dòng)提交,以隔離不同session之間的操作。
con.setAutoCommit(false);
}
catch(SQLException e) {
// 錯(cuò)誤處理代碼
}
}
public Connection getConnection() {
// 通過(guò)這個(gè)getter方法獲取連接
return con;
}
private Connection con = null; // 設(shè)置為私有變量,這很重要,以確保變量安全。
}
==== 使用方法 ====

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

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

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

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

1 protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
2
3 // 同步代碼取得數(shù)據(jù)庫(kù)連接
4 synchronized (session) {
5 // 看看這個(gè)持有者是否已經(jīng)在 session 中了
6 ConnectionHolder holder = (ConnectionHolder) session.getAttribute
("servletapp.connection");
7
8 // 如果不在,就創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)連接,并把它交給持有者。
9 if (holder == null) {
10 try {
11 holder = new ConnectionHolder(DriverManager.getConnection(
"Connection URL"));
12 session.setAttribute("servletapp.connection", holder);
13 }
14 catch (SQLException sqle) {
15 // 錯(cuò)誤處理代碼
16 }
17 }
18
19 // 從容器取得實(shí)際連接
20 conn = holder.getConnection();
21 }
.... // 別忘了commit
}
這段代碼看起來(lái)有那么幾行。但實(shí)際上,在每個(gè)session中,只有第一次執(zhí)行的servlet需要進(jìn)行數(shù)據(jù)庫(kù)連接操作,此后的servlet只會(huì)執(zhí)行第4、6、20這三行。

==== 誰(shuí)來(lái)負(fù)責(zé)斷開連接? ====

當(dāng) servlet 們不必再為創(chuàng)建數(shù)據(jù)庫(kù)連接費(fèi)心的時(shí)候,也就沒(méi)有人愿意管關(guān)閉連接這檔子事了。事實(shí)上,更重要的是,他們沒(méi)法管。因?yàn)檫@個(gè)連接是放在 session 中的,而沒(méi)有誰(shuí)能準(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ù)庫(kù)連接就會(huì)自動(dòng)關(guān)閉。

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

具體方法是:

public void valueUnbound(HttpSessionBindingEvent event) {
// 當(dāng)從Session刪除或當(dāng)Session結(jié)束時(shí),關(guān)閉數(shù)據(jù)連接。
try {
if (con != null) {
con.rollback(); // 放棄所有未提交的數(shù)據(jù)
con.close();
}
}
catch (SQLException e) {
// 錯(cuò)誤處理代碼
}
}
==== 完整示例 ====

下面是一個(gè)完整的 ConnectionHolder:

import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionBindingEvent;
import java.sql.Connection;
import java.sql.SQLException;
public class ConnectionHolder implements HttpSessionBindingListener {
public ConnectionHolder(Connection con) {
// 保存連接
this.con = con;
try {
con.setAutoCommit(false);
}
catch(SQLException e) {
// 錯(cuò)誤處理代碼
}
}
public Connection getConnection() {
return con;
}
public void valueBound(HttpSessionBindingEvent event) {
// 當(dāng)增加Session時(shí),什么也不做
}
public void valueUnbound(HttpSessionBindingEvent event) {
// 當(dāng)從Session刪除或當(dāng)Session結(jié)束時(shí),關(guān)閉數(shù)據(jù)連接。
try {
if (con != null) {
con.rollback(); // 放棄所有未發(fā)送數(shù)據(jù)
con.close();
}
}
catch (SQLException e) {
// 錯(cuò)誤處理代碼
}
}
private Connection con = null;
}

分享:Linux系統(tǒng)下兩種自動(dòng)啟動(dòng)Tomcat的方法
 有很多辦法可以讓Tomcat在系統(tǒng)啟動(dòng)的時(shí)候自動(dòng)運(yùn)行,我這里介紹兩種方法,一種簡(jiǎn)單,另外一種復(fù)雜而專業(yè)。在介紹這兩個(gè)方法前你應(yīng)該先裝JDK,Tomcat。Tomcat的安裝很簡(jiǎn)單,下載二進(jìn)制壓縮包

來(lái)源:模板無(wú)憂//所屬分類:JSP教程/更新時(shí)間:2008-08-22
相關(guān)JSP教程