Я решил эту проблему с помощью фильтра
открытый класс SessionReplicationFilter реализует фильтр {
@Inject
SessionReplicationManager manager;
public SessionReplicationFilter() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
//Process chain first
if (chain != null) {
chain.doFilter(request, response);
}
//check http request
if (request instanceof HttpServletRequest) {
HttpServletRequest httpRequest = (HttpServletRequest) request;
// Retrieve the session and the principal (authenticated user)
// The principal name is actually the username
HttpSession session = httpRequest.getSession();
Principal principal = httpRequest.getUserPrincipal();
if (principal != null && principal.getName() != null && session != null) {
manager.checkExistingSession(principal.getName(), session))
}
}
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
}
Менеджер смотрит вслед
Открытый класс @ApplicationScoped SessionReplicationManager {
private Map<String, HttpSession> map = new ConcurrentHashMap<String, HttpSession>();
public boolean checkExistingSession(String user, HttpSession session) {
if (map.keySet().contains(user)) {
if (!session.getId().equals(map.get(user).getId())) {
System.out.println("User already logged in ");
HttpSession oldSession = map.get(user);
// copies all attributes from the old session to the new session (replicate the session)
Enumeration<String> enumeration = oldSession.getAttributeNames();
while (enumeration.hasMoreElements()) {
String name = enumeration.nextElement();
System.out.println("Chaning attribut " + name);
session.setAttribute(name, oldSession.getAttribute(name));
}
// invalidates the old user session (this keeps one session per user)
oldSession.invalidate();
map.put(user, session);
return true;
}
} else {
System.out.println("Putting "+user+" into session cache");
map.put(user, session);
return false;
}
return false;
}
}
Он очень хорошо работает с аннотированными компонентами CoDI ViewScoped.
Если первый пользователь становится недействительным, каждый запрос (AJAX) вызывает исключение с истекшим сроком действия сеанса, которое можно легко обработать даже с помощью кнопки восстановления сеанса.
Единственная незначительная проблема с bean-компонентами с областью просмотра заключается в том, что они получают новый идентификатор представления. Поменяв их на исходные, все работает нормально.
Вещи, которые мне нужно добавить:
- Автоматический выход (опрос ajax, веб-сокеты,...)
- Какой-то реестр, где хранятся все viewscoped-id
В этом комментарии не хватает:
С уважением
person
urbiwanus
schedule
17.07.2012