我有2個JSF託管的bean A
和B
,我需要在5分鐘後過期/銷燬/銷燬A
和B
。我檢查了這個相關的問題Timing out from a bean,但它正在過期整個會話。我不想過期整個會議。在時間間隔後過期特定的託管bean實例
如何使用自定義範圍實現此目的?
我有2個JSF託管的bean A
和B
,我需要在5分鐘後過期/銷燬/銷燬A
和B
。我檢查了這個相關的問題Timing out from a bean,但它正在過期整個會話。我不想過期整個會議。在時間間隔後過期特定的託管bean實例
如何使用自定義範圍實現此目的?
鑑於您使用JSF bean管理工具(因此不需要CDI,這需要完全不同的答案),您可以使用@CustomScoped
來實現此目的。 @CustomScoped
值必須在更廣泛的通常存在的範圍內引用Map
實現。
喜歡的東西:
@ManagedBean
@CustomScoped("#{timeoutScope}")
public class TimeoutBean {}
由於@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()
等
請注意,我用System#nanoTime()
,而不是作爲System#currentTimeMillis()
後者是依賴於OS(操作系統)的時間,而不是硬件的時間(和因此它對時間和最終用戶控制的變化敏感)。
你不能這樣做,如果容器管理你的豆 – Dummy
@Dummy他們是JSF /管理bean **不** ** ejbs!我正在管理JSF beans的範圍! – Junaid
你沒有明確地說過,你可以在技術上使用會話bean作爲你的jsf支持bean。如果是這樣,你是否想過計時器服務? – Dummy