5

我必须满足以下要求:

[...]如果登录的用户闲置超过 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 等)来完成它]

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

问题是,我认为在表示层中实现业务逻辑需求的一部分对我来说是错误的。

顺便说一句,会话到期可能与表示逻辑有太多关系,因为必须“听”用户输入。

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

我想听听一些有价值的意见,主要集中在良好的设计实践上。

4

3 回答 3

1

正如要求所说

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

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

在 Web 应用场景中,鼠标/键盘活动 (Utility) 模块触发会话超时。

我们可以使用观察者/监听者模式。如果是java

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

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

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

所以重点是表示层根据实用程序类提供的输入通知其他层。

于 2012-09-14T11:28:18.273 回答
0

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

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

于 2015-06-15T16:07:37.200 回答
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 对象过期(或即将过期)会话时,它可以循环遍历相应事件的所有事件处理程序并调用它们。这将让你保持你的层分开。

于 2015-11-20T22:56:54.393 回答