我必须满足以下要求:
[...]如果登录的用户闲置超过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。
我希望听到一些优点,主要关注良好的设计实践。
答案 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对象到期(或即将到期)会话时,它可以循环遍历相应事件的所有事件处理程序并调用它们。这样可以让你的图层分开。