在时间间隔后过期特定的受管bean实例 [英] Expire specific managed bean instance after time interval

查看:118
本文介绍了在时间间隔后过期特定的受管bean实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有2个JSF管理的bean AB,我需要在2分钟后到期/销毁/销毁A,在5分钟后需要B.我检查了这个相关问题从bean中超时,但整个会话期满了.我不想整个会话都过期.

I have 2 JSF managed beans A and B and I need to expire/destruct/destroy A after 2 minutes and B after 5 minutes. I checked this related question Timing out from a bean, but it is expiring whole session. I do not want to expire whole session.

如何通过自定义范围实现此目标?

How can I achieve this with a custom scope?

推荐答案

鉴于您使用的是JSF bean管理工具(因此不是CDI,这将需要完全不同的答案),您可以使用 @CustomScoped . @CustomScoped值必须在更广泛的(通常是现有的)范围内引用Map实现.

Given that you're using JSF bean management facility (and thus not CDI, which would require a completely different answer), you can achieve this with @CustomScoped. The @CustomScoped value must refer a Map implementation in a broader, usually existing, scope.

类似的东西:

@ManagedBean
@CustomScoped("#{timeoutScope}")
public class TimeoutBean {}

由于@CustomScoped批注不支持传递其他参数,因此只能通过如下所示的其他自定义批注来设置超时时间:

As the @CustomScoped annotation doesn't support passing additional arguments, setting the timeout can only be done via an additional custom annotation like below:

@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支持(手动):

Now, here's a kickoff example of how the #{timeoutScope} looks like, including @PostConstruct support (automatically) and @PreDestroy support (manually):

@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().

You see, it's session scoped and implements Map. As to the scope, this way it's tied to a specific user session, not to the whole application. If you actually want to share the bean across all user sessions in the application, then make it application scoped instead. As to the Map, henever JSF needs to find a managed bean, it first tries get(). If it returns null (i.e. bean doesn't exist yet), then it will auto-create the managed bean instance and perform a put().

put()内,只需提取和计算超时并将其存储在地图中即可.在get()内部,您只需检查超时并返回null即可指示JSF Bean已不存在.然后,JSF会简单地自动创建它,然后返回put()等.

Inside the put(), it's a matter of extracting and calculating the timeout and store it in the map. Inside the get(), you just check the timeout and return null to indicate JSF that bean doesn't exist anymore. JSF will then simply auto-create it and come back at put(), etc.

请注意,我正在使用 System#nanoTime() 而不是 System#currentTimeMillis() ,因为后者与OS(操作系统)时间相关,与硬件时间无关(因此,它对DST和最终用户控制的时间变化很敏感).

Do note that I'm using System#nanoTime() instead of System#currentTimeMillis() as the latter is tied to OS (operating system) time, not to hardware time (and it's thus sensitive to a.o. DST and enduser-controlled changes in time).

这篇关于在时间间隔后过期特定的受管bean实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆