Подключение области с помощью HttpSessionListener - PullRequest
2 голосов
/ 16 ноября 2011

Я пишу веб-приложение, которое позволяет людям сотрудничать.Я бы хотел, чтобы некоторые из моих сервисов работали для совместной работы (в которой участвуют несколько человек), а не для какой-либо отдельной http-сессии.Я создал пользовательский Scope, в котором хранятся бобы.Чтобы управлять жизненным циклом компонента, я отслеживаю идентификаторы сеансов, связанные следующим образом:

protected ConcurrentMap<String,Object> attributes = 
    new ConcurrentHashMap<String, Object>();

...
@Override
public Object get(String name, ObjectFactory<?> factory) {
    synchronized(this.attributes) {
        Object scopedObject = this.attributes.get(name);
        if (scopedObject == null) {
            scopedObject = factory.getObject();
            this.attributes.put(name, scopedObject);
            RequestAttributes reqAttrs = RequestContextHolder.currentRequestAttributes();
            activeSession(name).add(reqAttrs.getSessionId());

        }
        return scopedObject;
    }
}

Когда сеанс закрывается, я хотел бы удалить идентификатор сеанса из списка активных сеансов, связанных с данным компонентом.название.Когда набор становится пустым, я могу очистить.

Самый простой способ, которым я могу думать о закрытии сеанса управления, - это HttpSessionListener, но у меня есть разрыв между моим Scope и слушателем.Я вижу следующие возможности:

  1. Я могу создать HttpSessionListener статически, принять единственный экземпляр, заставить его управлять списком подписок, и мои экземпляры Scope подписываются на его события,Но это кажется избыточным, и мне не нравится шаблон синглтона для этого.

  2. Если бы у меня был доступ к HttpSession в Scope, я мог бы добавить Scope в список, сохраненный в сеансе, и попросите слушателя уведомить членов этого списка, что сеанс уходит.Но я не понимаю, как получить объект сеанса (а не только его идентификатор) в экземпляре Scope.

  3. Я могу заставить свой Scope реализоватьHttpSessionListener интерфейс и тем самым обновлять его состояние напрямую, но я не знаю, как программно зарегистрировать слушателя.Есть ли публичный способ сделать это?

  4. Есть ли лучший способ?

Спасибо за вашу помощь,

гена

1 Ответ

2 голосов
/ 19 ноября 2011

Не получив ни одного комментария или ответа, я выбрал вариант # 1:

public class SessionMonitor implements HttpSessionListener {
    protected final Log logger = LogFactory.getLog(getClass());

    protected CopyOnWriteArrayList<SessionEventListener> subscribers = new CopyOnWriteArrayList<SessionEventListener>();
    protected ConcurrentHashMap<String,HttpSession> sessions = new ConcurrentHashMap<String,HttpSession>();
    protected static SessionMonitor singleton;
    public static SessionMonitor soleInstance() throws ConfigurationException {
        if (singleton == null)
            throw new ConfigurationException("No SessionMonitor instance has been created");
        return singleton;
    }

    public SessionMonitor() {
        if (singleton == null)
            singleton = this;
    }

    @Override
    public void sessionCreated(HttpSessionEvent e) {
        HttpSession session = e.getSession();
        this.sessions.putIfAbsent(session.getId(), session);
        logger.trace("Registered session " + session.getId());
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent e) {
        String sessionId = e.getSession().getId();
        this.sessions.remove(sessionId);
        for (SessionEventListener listener: subscribers)
            listener.sessionEnded(sessionId);
        logger.trace("Removed session " + sessionId);
    }

    public HttpSession getSession(String id) {
        return this.sessions.get(id);
    }

    public void addListener(SessionEventListener listener) {
        this.subscribers.add(listener);
        logger.trace("Added listener " + listener);
    }

    public void removeListener(SessionEventListener listener) {
        this.subscribers.remove(listener);
        logger.trace("Removed listener " + listener);
    }
}

Когда создается область, она регистрируется с помощью SessionMonitor:

public ConditionalScope() throws ConfigurationException {
    logger.debug("Registering " + this.toString() + " for session monitoring");
    SessionMonitor.soleInstance().addListener(this);
}

Мне не ясно, однако, когда удалять Scope из SessionMonitor. Будет ли здесь работать какой-то WeakArray?

...