1、HttpSessionBindingListen
2、在线人数统计程序:
在UserList这个类中,应用单件模式,向程序提供一个全局访问点。
import java.util.Vector;
import java.util.Enumeration;
public class UserList
{
}
User 类实现了HttpSessionBindingListen
import javax.servlet.http.HttpSessionBindingListen
import javax.servlet.http.HttpSessionBindingEvent;
public class User implements HttpSessionBindingListen
{
}
登录时添加会话:
User user = new User(y.getid());
session.setAttribute("user",user);
退出时删除会话:
User us = (User)session1.getAttribute("user");
退出时删除会话并关闭浏览器Servelt
import javax.servlet.*;
import java.io.*;
import javax.servlet.http.*;
public class LogoutServlet extends HttpServlet
{
}
======================================================================================================================
连接数据库是很费时间的一项工作,所以,如果你的每个JSP页面里都有DriverManager.getConnection()这句的话,那你的网站肯定要慢死了(除非你有超快的服务器)。
但是,如果你只建立一个连接,然后所有用户都使用这个连接,那肯定也慢死了,因为所有对数据库的查询和更新操作将一个一个地通过这个唯一的连接,发送到数据库。
比较好而且常用的解决办法有两个。第一个是使用连接池,任何对数据库的查询和存取并不是直接发往数据库,而是发到连接池,连接池可以管理这些对数据库的操作。它可以同时处理大量的对数据库的操作,而不是像只建立一个连接那样,一条一条处理。因为现在的数据库系统都是设计成多线程的,可以同时处理多个连接的。
下面重点来说说第二种方法,就是把数据库连接作为session的一部分。原理很简单。当有一个用户登陆你的网站时,为其新建一个数据库连接,例如
Connection conn = DriverManager.getConnection("");
然后,把它放到session里面
session.setAttribute("servletapp.connection",conn);
于是conn这个对象就不会被销毁,因此此用户对数据库的连接就一直保留着,然后此用户若是在你网站上浏览论坛或者购物,一直都是用这个连接,而不用重新连接数据库,速度也就加快了。 直到他登出这个网站,或者session到期了,那么conn这个对象就会自动被销毁,那么,他对数据库的连接也就断开了。
用这个方法,每个用户可以有其自己的连接,即使若干用户同时发出对数据库的查询或存取,也都是通过其单独的连接,速度当然大大加快了。
在具体实现上,还需要写一个HttpSessionBindingListener,因为,当此用户登出你的网站时,你一定会写
session.invalidate();
于是,所有session里面的对象都销毁,包括conn,可是对数据库的连接还没断开。因此你要写一个class,实现interface HttpSessionBindingListener;实现里面的public void valueBound(HttpSessionBindingEvent event)和public void valueUnbound(HttpSessionBindingEvent event)
当一个对象被绑定到session里面去时,valueBound()会自动被调用,当一个对象被session删掉或者session被销毁时,valueUnbound()会自动被调用。所以,你可以把断开数据库的语句放在valueUnbound()里面。例如
public void valueUnbound(HttpSessionBindingEvent event) {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {}
}
这样,当你的用户登出网站时,以上函数被调用,然后conn与数据库服务器断开。
下面是〈Java Servlet Programming〉里面的一个完整例子
import java.io.*;
import java.sql.*;
import javax.servlet.*;
import javax.servlet.http.*;
class ConnectionHolder implements HttpSessionBindingListener {
private Connection con = null;
public ConnectionHolder(Connection con) {
// Save the Connection
this.con = con;
try {
con.setAutoCommit(false); // transactions can extend between web pages!
}
catch(SQLException e) {
// Perform error handling
}
}
public Connection getConnection() {
return con; // return the cargo
}
public void valueBound(HttpSessionBindingEvent event) {
// Do nothing when added to a Session
}
public void valueUnbound(HttpSessionBindingEvent event) {
// Roll back changes when removed from a Session
// (or when the Session expires)
try {
if (con != null) {
con.rollback(); // abandon any uncomitted data
con.close();
}
}
catch (SQLException e) {
// Report it
}
}
}
/* Actual Servlet */
public class ConnectionPerClient extends HttpServlet {
public void init() throws ServletException {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
}
catch (ClassNotFoundException e) {
throw new UnavailableException("Couldn't load OracleDriver");
}
}
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/plain");
PrintWriter out = res.getWriter();
HttpSession session = req.getSession(true);
Connection con;
// Synchronize: Without this two holders might be created for one client
synchronized (session) {
// Try getting the connection holder for this client
ConnectionHolder holder =
(ConnectionHolder) session.getAttribute("servletapp.connection");
// Create (and store) a new connection and holder if necessary
if (holder == null) {
try {
holder = new ConnectionHolder(DriverManager.getConnection(
"jdbc:oracle:oci7:ordersdb", "user", "passwd"));
session.setAttribute("servletapp.connection", holder);
}
catch (SQLException e) {
log("Couldn't get db connection", e);
}
}
// Get the actual connection from the holder
con = holder.getConnection();
}
// Now use the connection
try {
Statement stmt = con.createStatement();
stmt.executeUpdate(
"UPDATE INVENTORY SET STOCK = (STOCK - 10) WHERE PRODUCTID = 7");
stmt.executeUpdate(
"UPDATE SHIPPING SET SHIPPED = (SHIPPED + 10) WHERE PRODUCTID = 7");
// Charge the credit card and commit the transaction in another servlet
res.sendRedirect(res.encodeRedirectURL(
req.getContextPath() + "/servlet/CreditCardHandler"));
}
catch (Exception e) {
// Any error is grounds for rollback
try {
con.rollback();
session.removeAttribute("servletapp.connection");
}
catch (Exception ignored) { }
out.println("Order failed. Please contact technical support.");
}
}
}