セッションの有効期限が切れたことを<p:growl>
に表示したい。 JSF/PrimeFaces ajaxリクエストでのセッションタイムアウトとViewExpiredException処理 のように、セッションの有効期限を処理する多くのメソッドを見つけましたが、facesメッセージを<p:growl>
にプッシュできませんでした。
要するに、サーバー側でHTTPセッションが自動的に期限切れになったときに、クライアント側で(JavaScript)コードを自動的に実行するにはどうすればよいですか?
PrimeFaces アイドルモニター を使用できます。セッションを無効にするために、タイムアウト後にユーザーはログアウトアクションにリダイレクトされます。ユーザーに警告するカウントダウンダイアログが表示される2分前。マウスをもう一度動かした後、セッションが延長されます。
PrimeFacesアイドルモニターおよび ダイアログ は、関連するすべてのページに追加できるテンプレートに配置されます。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://Java.Sun.com/jsf/html"
xmlns:ui="http://Java.Sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<ui:composition>
<h:form prependId="false">
<p:idleMonitor
timeout="#{session.maxInactiveInterval * 1000 - 125000}"
onidle="startIdleMonitor()"
onactive="timeoutDialog.hide()" />
<p:dialog id="timeoutSession"
header="#{msg['session.expire']}"
widgetVar="timeoutDialog"
showEffect="fade" hideEffect="fade"
modal="true"
width="400"
height="110"
closable="false"
draggable="false"
resizable="false"
appendToBody="true"
onHide="stopCount()"
onShow="doTimer()">
<br />
<p>
<span class="ui-icon ui-icon-alert" style="float: left; margin: 8px 8px 0;"/>
<p:panel>
#{msg['logoff.soon.1']}
<span id="dialog-countdown" style="font-weight: bold"></span>
#{msg['logoff.soon.2']}
</p:panel>
</p>
<br />
<p style="font-weight: bold;">#{msg['move.cursor']}</p>
</p:dialog>
<p:remoteCommand name="keepAlive" actionListener="#{auth.keepSessionAlive}" />
</h:form>
<script type="text/javascript">
var TIME = 120; // in seconds
var countTimer = TIME;
var processTimer;
var timer_is_on = 0;
var redirectPage = "#{request.contextPath}/auth/j_verinice_timeout";
var countDownDiv = "dialog-countdown";
var txtCountDown = null;
if (!txtCountDown)
txtCountDown = document.getElementById(countDownDiv);
function startIdleMonitor() {
countTimer = TIME;
txtCountDown.innerHTML = countTimer;
timeoutDialog.show();
}
function timedCount() {
txtCountDown.innerHTML = countTimer;
if (countTimer == 0) {
stopCount();
window.location.href = redirectPage;
return;
}
countTimer = countTimer - 1;
processTimer = setTimeout("timedCount()", 1000);
}
function doTimer() {
if (!timer_is_on) {
timer_is_on = 1;
timedCount();
}
}
function stopCount() {
clearTimeout(processTimer);
timer_is_on = 0;
keepAlive();
}
</script>
</ui:composition>
</html>
複数のページでタイムアウト処理をアクティブにするには、レイアウトテンプレートにタイムアウトテンプレートを含めます。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://Java.Sun.com/jsf/html"
xmlns:ui="http://Java.Sun.com/jsf/facelets"
xml:lang="de-DE">
<h:head>
...
</h:head>
<body>
<ui:include src="/template/sessionTimeOut.xhtml" />
<ui:include src="/nav.xhtml"/>>
<ui:insert name="content">Default content</ui:insert>
<ui:include src="/footer.xhtml"/>>
</body>
</html>
Web.xmlで設定できるWebアプリケーションの特定のタイムアウト:
<!--?xml version="1.0" encoding="UTF-8"?-->
<web-app>
...
<session-config>
<!-- Session idle timeout in min. -->
<session-timeout>30</session-timeout>
</session-config>
</web-app>
このソリューションの詳細については、このブログ投稿を参照してください: JSFおよびPrimeFaces:セッションタイムアウト処理
JSF 2.3を使用している場合は、スコープが設定されたセッションを使用できます <f:websocket>
これには。サーバー側でセッションが期限切れになると、<f:websocket>
は close code 1000( "normalclosure") で自動的に閉じられます。
言い換えれば、次のことを実行してください。
<f:websocket ... scope="session" onclose="sessionScopedSocketCloseListener" />
function sessionScopedSocketCloseListener(code) {
if (code == 1000) {
alert("Session has expired!");
}
}
必要に応じて、これを<p:growl>
のJavaScriptAPIと組み合わせることができます。
<p:growl widgetVar="growl" ... />
PF("growl").renderMessage({severity: "warn", summary: "Session has expired!" });
まだJSF2.3を使用していない場合は、いつでも <o:socket>
を使用できます。これは、<f:websocket>
とまったく同じonclose
機能を提供します。参照 サーバーはJSFによって作成されたHTMLページに非同期変更をプッシュする方法は?
@uı6ʎɹnɯlǝıuɐpによって投稿されたコードは非常に便利ですが、いくつかの所見を追加します。
@ Jonathan LprocessTimer = setTimeout("timedCount()", 1000)
をsetInterval("timedCount()", 1000)
に置き換えます。私は理にかなっていると思いますが、いくつかの変更が必要です:
_function doTimer() {
if (!timer_is_on) {
timer_is_on = 1;
processTimer = setInterval("timedCount()", 1000);
}
}
function stopCount() {
clearInterval(processTimer);
timer_is_on = 0;
keepAlive();
}
_
メソッドtimedCount()は次のように変更できます。
_function timedCount() {
txtCountDown.innerHTML = countTimer;
if (countTimer > 0) {
countTimer = countTimer - 1;
} else {
clearInterval(processTimer);
doLogout();
}
}
_
そして、keepAlive
remoteCommandの下に次のようなものを追加する必要があります。
_<p:remoteCommand name="doLogout" action="#{loginMB.logout()}"
process="@this" partialSubmit="true" immediate="true" />
_
マネージドBeanの内部:
_public void logout() {
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
validUser = false;
loggedUser = false;
redirectToPage("/login.xhtml");
}
private void redirectToPage(String page) {
ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
context.redirect(context.getRequestContextPath() + page);
}
_
_
name="doLogout"
_の属性_p:remoteCommand
_は、どこからでも呼び出すことができるjavascript関数に変換されることを忘れないでください。マネージドBeanでビューを繰り返すのに最適です。このアプローチにより、システムスタックが防止されますViewExpiredException。
keepAlive
の概念を理解していない人もいますが、それは非常に簡単です。マネージドBean内に単純な関数を追加するだけです。例keepSessionAlive
アクション:
_public void keepSessionAlive () {
System.out.println(">>> Session is alive... ");
}
_
_
p:remoteCommand
_という名前のkeepAlive
はkeepAlive()
というJavaScript関数であり、その呼び出しはアクションkeepSessionAlive
マネージドBean内。このアクションは、アイドル状態ではないことを示します。
_session.maxInactiveInterval
_のidleMonitor参照_<session-timeout>
_のweb.xml
_<p:idleMonitor timeout="#{session.maxInactiveInterval * 1000 - 125000}"
onidle="startIdleMonitor()" onactive="timeoutDialog.hide()" />
_
セッション終了後の実行
doLogout()
を防ぎ、ViewExpiredExceptionを取得するために、セッション終了の5秒前にセッションモニターを実行することをお勧めします。
Javascriptコードの最初の行は_var TIME = 120; // in seconds
_で、これはセッションを終了する時間を表します。元のコード_# {session.maxInactiveInterval * 1000 - 125000}
_は、1.000で乗算されたセッションタイムアウトを使用し(ミリ秒であるため)、125秒を表す125.000を減算します。これは、カウンターより5秒短いため、変更する必要はありません。