Поскольку этот вопрос приблизился к 5k просмотров, я думаю, что было бы полезно привести пример рабочего решения.
Подход, изложенный в вопросе, неверен - он не будет обрабатывать перезапуски сервера и будетне масштаб.Вот лучший подход.
Во-первых, ваш HttpServlet должен обрабатывать пользовательские входы и выходы из системы, что-то вроде этого:
public class ExampleServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String action = req.getParameter("do");
HttpSession session = req.getSession(true);
//simple plug. Use your own controller here.
switch (action) {
case "logout":
session.removeAttribute("user");
break;
case "login":
User u = new User(session.getId(), req.getParameter("login"));
//store user on the session
session.setAttribute("user",u);
break;
}
}
}
Пользовательский компонент должен быть Serializable и должен перерегистрировать себя после десериализации:
class User implements Serializable {
private String sessionId;
private String login;
User(String sessionId, String login) {
this.sessionId = sessionId;
this.login = login;
}
public String getLogin() { return login; }
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
//re-register this user in sessions
UserAttributeListener.sessions.put(sessionId,this);
}
}
Вам также понадобится HttpAttributeListener для правильной обработки жизненного цикла сеанса:
public class UserAttributeListener implements HttpSessionAttributeListener {
static Map<String, User> sessions = new ConcurrentHashMap<>();
@Override
public void attributeAdded(HttpSessionBindingEvent event) {
if ("user".equals(event.getName()))
sessions.put(event.getSession().getId(), (User) event.getValue());
}
@Override
public void attributeRemoved(HttpSessionBindingEvent event) {
if ("user".equals(event.getName()))
ExampleServlet.sessions.remove(event.getSession().getId());
}
@Override
public void attributeReplaced(HttpSessionBindingEvent event) {
if ("user".equals(event.getName()))
ExampleServlet.sessions.put(event.getSession().getId(),
(User)event.getValue());
}
}
Конечно, вам необходимо зарегистрировать слушателя в web.xml:
<listener>
<listener-class>com.example.servlet.UserAttributeListener</listener-class>
</listener>
После этого вы всегда можете получить доступ к статической карте в UserAttributeListener, чтобы получить представление о том, сколько сеансов запущено, сколько сеансов использует каждый пользователь и т. Д. В идеале у вас должна быть немного более сложная структура данных, гарантирующая еесобственный отдельный синглтон-класс с надлежащими методами доступа.Использование контейнеров с параллельной стратегией копирования при записи также может быть хорошей идеей, в зависимости от варианта использования.