是否可以为注入@Named beans的所有会话对象全局设置会话超时?
我有几个@ConversationScoped bean,例如:
import javax.annotation.PostConstruct;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.inject.Inject;
import javax.inject.Named;
@Named
@ConversationScoped
public class SomeBean1 {
@Inject
private Conversation conversation;
@PostConstruct
private void init() {
if (conversation.isTransient()) {
conversation.begin();
}
}
}
@Named
@ConversationScoped
public class SomeBean2 {
@Inject
private Conversation conversation;
@PostConstruct
private void init() {
if (conversation.isTransient()) {
conversation.begin();
}
}
}
这些会话的默认超时为600000毫秒。我想知道是否有任何方法可以在全局设置会话的超时,或者我需要在每个bean中设置它
if (!conversation.isTrainsient()) {
conversation.setTimeout(MY_CUSTOM_TIMEOUT);
}
(问题是有很多CDI bean并且每个人手动设置超时都不是最佳解决方案)
答案 0 :(得分:2)
使用Seam / Weld,您应该可以执行以下操作:
@Inject
private HttpConversationContext conversationContext;
public void observePreload(@Observes PreloadCompleteEvent event) {
//Set global conversation timout to 60000 ms
conversationContext.setDefaultTimeout(60000);
}
否则我相信您必须为每次对话设置它。
编辑:注意我使用了自定义事件,同样可以通过以下方式完成:
public void observePreload(@Observes @Started WebApplication webapp) {
答案 1 :(得分:2)
所以,这是我使用的解决方案(Oracle WebLogic 12c,WELD 1.1.Final):
import org.jboss.weld.context.http.HttpConversationContext;
import javax.inject.Inject;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
@WebListener
public class SessionListener implements HttpSessionListener {
@Inject
private HttpConversationContext conversationContext;
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
if (conversationContext != null) {
final long DEFAULT_TIMEOUT = 2 * 60 * 60 * 1000;
if (conversationContext.getDefaultTimeout() < DEFAULT_TIMEOUT){
conversationContext.setDefaultTimeout(DEFAULT_TIMEOUT);
}
}
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {}
}
将上下文注入到侦听器中,并在用户启动会话时设置超时。
答案 2 :(得分:1)
这可以通过CDI 1.1以便携方式轻松完成。
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.enterprise.context.Initialized;
import javax.enterprise.event.Observes;
import javax.inject.Inject;
import javax.servlet.ServletRequest;
public class ConversationTimeoutDefaultSetter {
@Inject
private Conversation conversation;
public void conversationInitialized(
@Observes @Initialized(ConversationScoped.class)
ServletRequest payload) {
conversation.setTimeout(1800000L); // 30 minutes
}
}
另一个便携式选项是装饰对话。 (警告:未经测试。)
import static javax.interceptor.Interceptor.Priority.APPLICATION;
import javax.annotation.Priority;
import javax.decorator.Decorator;
import javax.decorator.Delegate;
import javax.enterprise.context.Conversation;
import javax.inject.Inject;
@Decorator
@Priority(APPLICATION)
public class ConversationTimeoutDefaultSetter implements Conversation, Serializable {
private static final long serialVersionUID = 1L;
@Inject
@Delegate
private Conversation delegate;
private void setDefaultTimeout() {
delegate.setTimeout(1800000L); // 30 minutes
}
@Override
public void begin() {
setDefaultTimeout();
delegate.begin();
}
@Override
public void begin(String id) {
setDefaultTimeout();
delegate.begin(id);
}
@Override
public void end() {
delegate.end();
}
@Override
public String getId() {
return delegate.getId();
}
@Override
public long getTimeout() {
return delegate.getTimeout();
}
@Override
public void setTimeout(long milliseconds) {
delegate.setTimeout(milliseconds);
}
@Override
public boolean isTransient() {
return delegate.isTransient();
}
}
答案 3 :(得分:0)
您还可以将对话bean的超时与当前http请求的会话超时同步:
if (conversation.isTransient()) {
conversation.setTimeout(((HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext()
.getRequest()).getSession().getMaxInactiveInterval()*1000);
conversation.begin();
}