2

人々が共同作業できるようにする Web アプリケーションを作成しています。サービスの一部を、個々の http セッションではなく、コラボレーション (数人が関与する) に限定したいと考えています。Scope豆を保存するカスタムを作成しました。Bean のライフサイクルを管理するために、次のように関連付けられたセッション ID を追跡します。

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;
    }
}

セッションが終了したら、特定の Bean 名に関連付けられたアクティブなセッションのリストからセッション ID を削除したいと考えています。セットが空になったら片付けます。

管理セッションの終了を考える最も簡単な方法は を使用することですがHttpSessionListener、私Scopeとリスナーの間に切断があります。次の可能性が見えます。

  1. を静的に作成しHttpSessionListener、単一のインスタンスを想定して、サブスクリプション リストを管理し、Scopeインスタンスにそのイベントをサブスクライブさせることができます。しかし、それは冗長に思えます。私はこれに対するシングルトン パターンが好きではありません。

  2. HttpSessionのにアクセスできる場合は、セッションに保存されているリストScopeに を追加し、Scopeそのリストのメンバーにセッションが終了することをリスナーに通知させることができます。Scopeしかし、インスタンス内のセッション オブジェクト (ID だけでなく) を取得する方法がわかりません。

  3. Scopeインターフェイスを実装してその状態を直接更新することはできHttpSessionListenerますが、リスナーをプログラムで登録する方法がわかりません。それを行う公的な方法はありますか?

  4. より良い方法はありますか?

ご協力いただきありがとうございます、

遺伝子

4

1 に答える 1

2

コメントや回答を受け取っていないので、次のようにオプション#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);
}

ただし、 から をいつ削除するかについては明確ではありませScopeSessionMonitor。ここで何らかの WeakArray作業が行われるでしょうか?

于 2011-11-18T21:58:45.517 に答える