鉴于您正在使用 JSF bean 管理工具(因此不是 CDI,这需要完全不同的答案),您可以通过以下方式实现此目的@CustomScoped http://docs.oracle.com/javaee/7/api/javax/faces/bean/CustomScoped.html. The @CustomScoped
值必须引用一个Map
在更广泛的、通常是现有的范围内实施。
就像是:
@ManagedBean
@CustomScoped("#{timeoutScope}")
public class TimeoutBean {}
As the @CustomScoped
注解不支持传递附加参数,设置超时只能通过附加自定义注解来完成,如下所示:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Timeout {
/** Minutes. */
int value();
}
@ManagedBean
@CustomScoped("#{timeoutScope}")
@Timeout(5) // Expires after 5 minutes.
public class TimeoutBean {}
现在,这是一个启动示例,说明如何#{timeoutScope}
看起来像,包括@PostConstruct
支持(自动)和@PreDestroy
支持(手动):
@ManagedBean
@SessionScoped
public class TimeoutScope extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;
@Override
public Object put(String name, Object bean) {
Timeout timeout = bean.getClass().getAnnotation(Timeout.class);
if (timeout == null) {
throw new IllegalArgumentException("@Timeout annotation is required on bean " + name);
}
Long endtime = System.nanoTime() + (timeout.value() * (long) 6e10);
Object[] beanAndEndtime = new Object[] { bean, endtime };
return super.put(name, beanAndEndtime);
}
@Override
public Object get(Object key) {
Object[] beanAndEndtime = (Object[]) super.get(key);
if (beanAndEndtime == null) {
return null;
}
Object bean = beanAndEndtime[0];
Long endtime = (Long) beanAndEndtime[1];
if (System.nanoTime() > endtime) {
String name = (String) key;
ScopeContext scope = new ScopeContext("timeoutScope", Collections.singletonMap(name, bean));
FacesContext context = FacesContext.getCurrentInstance();
context.getApplication().publishEvent(context, PreDestroyCustomScopeEvent.class, scope);
return null;
}
return bean;
}
}
你看,它是会话范围的并且实现了Map
。至于范围,这样它就与特定的用户会话相关联,而不是与整个应用程序相关联。如果您确实想要在应用程序中的所有用户会话之间共享该 bean,那么请将其设置为应用程序范围。至于Map
,无论 JSF 需要查找托管 bean,它都会首先尝试get()
。如果返回的话null
(即 bean 尚不存在),然后它将自动创建托管 bean 实例并执行put()
.
在 - 的里面put()
,这是提取并计算超时并将其存储在映射中的问题。在 - 的里面get()
,你只需检查超时并返回null
指示 JSF 该 bean 不再存在。然后 JSF 将简单地自动创建它并返回put()
, etc.
请注意我正在使用System#nanoTime() http://docs.oracle.com/javase/8/docs/api/java/lang/System.html#nanoTime--代替System#currentTimeMillis() http://docs.oracle.com/javase/8/docs/api/java/lang/System.html#currentTimeMillis--因为后者与 OS(操作系统)时间相关,而不是与硬件时间相关(因此它对 a.o. DST 和最终用户控制的时间变化敏感)。