在桌面应用程序中管理登录会话:在哪个层?

时间:2012-09-14 11:17:19

标签: java session layer session-timeout

我必须满足以下要求:

  

[...]如果登录的用户闲置超过30分钟,他必须退出。

其中空闲表示“不按鼠标或键盘”。

现在,我非常肯定在我第一次阅读时如何实现这一点:对我而言,这听起来像是与业务逻辑有关的要求,所以我应该在业务层实现它(具有3-层结构) 这里有一些代码:

// simplified and generalized version of my login method
public boolean login(String email, String password) {
    user = dao.read(email, password); //returns either null or the user
    boolean logged = user != null;
    if (logged) {
       // initialize Session somehow, let's say for example:
        Session.start();
    }
    return logged;
}

// simplified and generalized version of my logout method
public void logout() {
    operatore = null;
    // terminate Session somehow, let's say for example:
    Session.destroy();
}

这是理想的,但有一个问题:Session应该知道如何检测用户不活动(然后触发logout()方法)......但不幸的是,这完全取决于GUI的制作方式!
[只是要清楚:我知道我要做到这一点,但我想独立完成如何实现UI(例如Java Swing,命令行,基于Web等)]

我的意思是,业务层不能(也不应该imo)捕获用户事件/交互,所以我必须在GUI包中实现Session 从那里使用它:在我的设计中,一个层应该只与其严格的下层接口进行交互,并且不应该知道任何更高级别的任何内容(数据访问层是独立的(好吧,它取决于数据库)和其他持久性机制),业务层只依赖于数据访问层接口,表示层只依赖于业务层接口。)

问题在于,我觉得错误地认识到我认为是表示层中业务逻辑要求的一部分。

顺便说一下,会话到期可能需要对表示逻辑做太多,因为必须“监听”用户输入。

这让我想起了我前一段时间回答的另一个相关问题,但我也会问这个问题,以避免任何疑问:link to the question

我希望听到一些优点,主要关注良好的设计实践。

3 个答案:

答案 0 :(得分:1)

正如要求所说

  

如果登录的用户闲置超过30分钟,他必须是   退出。

所以这里的输入是键盘或鼠标活动。当然这属于表示层。

在Web应用程序方案中,鼠标/键盘活动(实用程序)模块会触发会话超时。

我们可以使用Observer / Listener模式。如果是在java

http://www.vogella.com/articles/DesignPatternObserver/article.html会有所帮助

使用httpsession列表器,我们可以将此活动传递到业务层。这意味着您可以调用业务层功能来进行清理。

在桌面方案中,我们可以使用可以使用类似模式的Swing应用程序。

所以关键是Presentation层根据Utility Class提供的输入通知其他层。

答案 1 :(得分:0)

它甚至可以变得更令人兴奋。不同屏幕上的不同超时(可能是显示视频的屏幕,因此在视频打开时将超时放在一边)。针对不同用户的不同超时(对于某些用户,应该永远不会超时)。可以在不登录的情况下访问的屏幕,但应用程序应该“超时”并返回“主”屏幕。

我最终将业务层应用程序注册到演示控件中的“activity”。不是一个美丽的网站。很高兴看到一个好的解决方案。

答案 2 :(得分:0)

两个

您的业务层只需要知道有一些用户活动 - 它不一定需要知道该活动是什么或该活动是如何被触发的(甚至是它来自哪里)。

public class Session {
    ...
    public static void keepAlive() {
        // update last activity fields with new timestamp
    }
    ....
}

每当您的表示层接收某种输入(鼠标移动,鼠标点击,按键等)时,由该层中的对象通知业务层发生了某些事情。

为了保持分离,您可能希望向Session对象添加一些事件。

public interface SessionExpiringEventHandler {
    void sessionExpiring();
}

public interface SessionExpiredEventHandler {
    void sessionExpired();
}

public class Session {
    ...
    private List<SessionExpiringEventHandler> expiringHandlers;
    private List<SessionExpiredEventHandler> expiredHandlers;
    ...
    public static void addExpiringEventHandler(SessionExpiringEventHandler h) {
        expiringHandlers.add(h);
    }
    public static void addExpiredEventHandler(SessionExpiredEventHandler h) {
        expiredHandlers.add(h);
    }
    ....
}

这样,当Session对象到期(或即将到期)会话时,它可以循环遍历相应事件的所有事件处理程序并调用它们。这样可以让你的图层分开。