Jsf 特定托管bean实例在时间间隔后过期

Jsf 特定托管bean实例在时间间隔后过期,jsf,scope,managed-bean,Jsf,Scope,Managed Bean,我有两个JSF托管beanA和B,我需要在2分钟后过期/销毁/销毁A,在5分钟后过期/销毁B。我检查了这个相关问题,但它将在整个会话中过期。我不想使整个会话过期 如何使用自定义范围实现这一点?鉴于您使用的是JSFbean管理工具(因此不是CDI,这需要一个完全不同的答案),您可以使用。@CustomScoped值必须引用更广泛(通常是现有)范围中的映射实现 比如: @ManagedBean @CustomScoped("#{timeoutScope}") public class Timeout

我有两个JSF托管bean
A
B
,我需要在2分钟后过期/销毁/销毁
A
,在5分钟后过期/销毁
B
。我检查了这个相关问题,但它将在整个会话中过期。我不想使整个会话过期


如何使用自定义范围实现这一点?

鉴于您使用的是JSFbean管理工具(因此不是CDI,这需要一个完全不同的答案),您可以使用。
@CustomScoped
值必须引用更广泛(通常是现有)范围中的
映射
实现

比如:

@ManagedBean
@CustomScoped("#{timeoutScope}")
public class TimeoutBean {}
由于
@CustomScoped
注释不支持传递附加参数,因此只能通过以下附加自定义注释设置超时:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Timeout {

    /** Minutes. */
    int value();

}
现在,这里有一个关于
{timeoutScope}
的启动示例,包括
@PostConstruct
支持(自动)和
@PreDestroy
支持(手动):

@ManagedBean
@会议范围
公共类TimeoutScope扩展HashMap{
私有静态最终长serialVersionUID=1L;
@凌驾
公共对象put(字符串名称、对象bean){
Timeout Timeout=bean.getClass().getAnnotation(Timeout.class);
如果(超时==null){
抛出新的IllegalArgumentException(“@Timeout注释是bean”+name所必需的);
}
Long-endtime=System.nanoTime()+(timeout.value()*(Long)6e10);
Object[]beanAndEndtime=新对象[]{bean,endtime};
返回super.put(名称、Bean和EndTime);
}
@凌驾
公共对象获取(对象密钥){
对象[]beanAndEndtime=(对象[])super.get(键);
如果(beanAndEndtime==null){
返回null;
}
对象bean=beanAndEndtime[0];
Long-endtime=(Long)Bean和endtime[1];
if(System.nanoTime()>endtime){
字符串名称=(字符串)键;
ScopeContext范围=新的ScopeContext(“timeoutScope”,Collections.singletonMap(名称,bean));
FacesContext context=FacesContext.getCurrentInstance();
context.getApplication().publishEvent(context,PreDestroyCustomScopeEvent.class,scope);
返回null;
}
返回豆;
}
}
你看,它是会话范围,并实现
Map
。至于范围,通过这种方式,它被绑定到特定的用户会话,而不是整个应用程序。如果您确实希望在应用程序中的所有用户会话中共享bean,那么将其设置为应用程序范围。至于
映射
,henever JSF需要找到一个托管bean,它首先尝试
get()
。如果它返回
null
(即bean还不存在),那么它将自动创建托管bean实例并执行
put()

put()
中,需要提取和计算超时并将其存储在映射中。在
get()
中,您只需检查超时并返回
null
,以指示JSF bean不再存在。然后JSF将自动创建它,并返回到
put()
,等等


请注意,我使用的是而不是,因为后者与操作系统时间有关,而与硬件时间无关(因此,它对a.o.DST和最终用户控制的时间更改非常敏感)。

如果容器正在管理您的beans@Dummy它们是JSF/ManageBean而不是EJB!!我正在管理JSFbean的范围!!您并没有明确地说,您可以在技术上使用会话bean作为jsf支持bean。如果是的话,你没有想过定时器服务吗?你真的需要销毁它们吗?或者你认为销毁它们是唯一的解决办法,是不是有一种不同的用途?这是我多年来第一次听到这个requirement@Kukeltje我真的想销毁这些豆子。所以没有办法
@PreDestroy
支持(自动)?实际上,我希望bean的时间一结束,
@PreDestroy
就会调用它!!也许你错过了更新后的答案,或者没有真正尝试过,或者没有逐行阅读代码?好吧,我读了你更新后的答案和代码行署名!!据我所知,
@PreDestroy
支持是手动的,而不是自动的!!它是否可以自动执行,比如每当Bean超时时,它都会自动调用
get
@PreDestroy
??如果我在你的回答中遗漏了什么,请告诉我。谢谢提示:不要在正式英语中使用“!!”或“?”,也不要过度使用粗体格式。这样一来,你像个混蛋一样过来,我很想删除答案,而忽略你未来的问题。至于注释中的问题,代码不会以编程方式触发
@PostConstruct
,因为JSF已经自动完成了这一操作。代码只会手动触发
@PreDestroy
,因为JSF不会自动触发。带有
publishEvent()
的行执行此操作。在提出新问题之前尝试一下。谢谢你的回复和提示。我以后会处理的。
@ManagedBean
@CustomScoped("#{timeoutScope}")
@Timeout(5) // Expires after 5 minutes.
public class TimeoutBean {}
@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;
    }

}