servlet上下文和单例对象

时间:2012-02-15 16:52:26

标签: java servlets singleton

我见过一个Singleton类对象的例子,它有一个包含从数据库中检索的用户ID和密码的映射。这有助于在用户登录期间不会每次都点击DB。

现在我在想,不能通过ServletContext属性来完成。

基本上在这两种情况下我们都会有应用程序范围的对象。

那么,在这种情况下我们可以使用ServletContext属性吗。

2 个答案:

答案 0 :(得分:4)

如果您需要从应用程序的任何位置访问Map,那么它实际上是放置它的最佳位置。

您可以注册Servlet Context Listener,在contextInitialized注册,您可以获得单身人士并将其存储为ServletContext

的属性

然后通过获取相应的属性

,在Web应用程序的任何位置使用它来访问它

getServletContext().getAttribute("UsersMap");

答案 1 :(得分:1)

如果数据库中的数据基本上是静态的,那么是的,你可以这样做。如果数据库中的数据是动态的,那么不,建议不要这样做。否则,您需要编写相当多的代码来保持DB和servletcontext变量同步。当新用户在webapp上注册时,您当然希望该用户能够登录。

无论如何,如果您在DB中有100万用户怎么办?你真的想把这一切都复制到服务器的内存中吗?出于什么目的?这完全违背了DB的目的。您想验证登录吗?我真的无法想象为什么验证登录将是如此昂贵,您需要在服务器的内存中拥有整个数据库的副本。这是一个有点像DB可以在不到一毫秒内完成的工作。必须在其他地方解决问题的原因。

也许您不必要地将整个数据库复制到Java的内存中并在每行的Java中完全进行验证而不是使用SQL WHERE子句?像这样的东西?

resultSet = statement.executeQuery("SELECT * FROM users");

while (resultSet.next()) {
    if (username.equals(resultSet.getString("username")) && password.equals(resultSet.getString("password"))) {
        valid = true;
        break;
    }
}

对于刚接触数据库而不了解SQL权限的初学者来说,这是一个经常出现的思维错误。如果您在用户名列上设置UNIQUE索引并为密码列编制索引,则以下方式更有效:

statement = connection.prepareStatement("SELECT id FROM users WHERE username=? AND password=md5(?)");
statement.setString(1, username);
statement.setString(2, password);
resultSet = statement.executeQuery();
valid = resultSet.next();