快捷搜索:  as  2018  FtCWSyGV  С˵  test  xxx  Ψһ  w3viyKQx

澳门新葡亰集团平台网址大全_龟发之家论坛



==== 问题所在 ====

假如要编写一个购物车,平日必要写很多个不合功能的servlet。例如用户登录、添加商品、查询购物车、结帐等。

在这些 servlet 中都必要读写数据库。假如我们在每个 servlet 中都进行连接 -> 读写 -> 断开连接的操作,就会耗损大年夜量的办事器资本,不仅法度榜样相应速率减缓,而且会加严惩事器和数据库的包袱。

==== 把盼望依靠于 HttpSession ====

如我们所学,Servlet API 供给了一些措施和类来专门处置惩罚短期的会话跟踪。网站的每个用户都和 javax.servlet.http.HttpSession 工具有关,servlet应用这个工具来记录和检索每个用户的信息。

幸运的是,我们可以在会话工具中存储随意率性的 java 工具。存储的措施大年夜家都已经很认识,便是应用 setAttribute()措施。代表数据库连接的Connection也不例外。

这就为我们让不合的servlet在一个session内共享链接带来的盼望。

==== 安然问题 ====

那么,仅仅像下面这样做就可以了么?

1、在Servlet1中,向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。

这个类的详细写法是:

public class ConnectionHolder {

public ConnectionHolder(Connection con) {

// 保存连接

this.con = con;

try {

// 禁用自动提交,以隔离不合session之间的操作。

con.setAutoCommit(false);

}

catch(SQLException 澳门新葡亰集团平台网址大全e) {

// 差错处置惩罚代码

}

}

public Connection getConnection() {

// 经由过程这个getter措施获取连接

return con;

}

private Connection con = null; // 设置为私有变量,这很紧张,以确保变量安然。

}

==== 应用措施 ====

每个 servlet 在盼望取得数据库连接的时刻,先看看 session 中是否有这个“保管者”(即上面的ConnectionHolder)。

假如有的话,直接调用它的get措施,取得数据库连接。

假如没有的话,阐明这个session还没有连接过数据库,那么当前类就立即创建一个数据库连接,并把这个连接交给保管者,然后再把保管者放入 session 中,以便后续的 servlet 应用。

下面是一个实例:

1protected void doGet(HttpServletRequest req, HttpServletResponse res)

throws ServletException, IOException {

2

3// 同步代码取得数据库连接

4synchronized (session) {

5// 看看这个持有者是否已经在 session 中了

6ConnectionHolder holder = (ConnectionHolder) session.getAttribute

("servletapp.connection");

7

8// 假如不在,就创建一个数据库连接,并把它交给持有者。

9if (holder == null) {

10try {

11holder = new ConnectionHolder(DriverManager.getConnection(

"Connection URL"));

12session.setAttribute("servletapp.connection", holder);

13}

14catch (SQLException sqle) {

15// 差错处置惩罚代码

16}

17}

18

19// 安闲器取得实际连接

20conn = holder.getConnection();

21}

.... // 别忘了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 这个类来保管的,是以最方便的法子便是把它注册成一个 监听 器。

详细措施是:

public void valueUnbound(HttpSessionBindingEvent event) {

// 当从Session删除或当Session停止时,关闭数据连接。

try {

if (con != null) {

con.rollback(); // 放弃所有未提交的数据

con.close();

}

}

catch (SQLException e) {

// 差错处置惩罚代码

}

}

==== 完备示例 ====

下面是一个完备的 ConnectionHolder:

import javax.servlet.http.HttpSessionBindingListener;澳门新葡亰集团平台网址大全

import javax.servl澳门新葡亰集团平台网址大全et.http.HttpSessionBindingEvent;

import java.sql.Connection;

import java.sql.SQLException;

public class ConnectionHolder implements HttpSessionBindingListener {

public ConnectionHolder(Con澳门新葡亰集团平台网址大全nection con) {

// 保存连接

this.con = con;

try {

con.setAutoCommit(false);

}

catch(SQLException e) {

// 差错处置惩罚代码

}

}

public Connection getConnection() {

return con;

}

public void valueBound(HttpSessionBindingEvent event) {

// 当增添Session时,什么也不做

}

public void valueUnbound(HttpSessionBindingEvent event) {

// 当从Session删除或当Session停止时,关闭数据连接。

try {

if (con != null) {

con.rollback(); // 放弃所有未发送数据

con.close();

}

}

catch (SQLException e) {

// 差错处置惩罚代码

}

}

private Connection con = null;

您可能还会对下面的文章感兴趣: