URL 重定向不适用于 preRenderView 事件
URL redirection not working on preRenderView event
我终于在页面之间传递了消息,但这并没有将我重定向到用户登录页面 (../../index.xhtml),而是显示了禁止访问的页面:
public String permission() throws IOException {
FacesContext context = FacesContext.getCurrentInstance();
Map<String, Object> sessionMap = context.getExternalContext().getSessionMap();
String isLog = (String) sessionMap.get("isLogged");
if(isLog != "TRUE") {
System.out.println("*** The user has no permission to visit this page. *** ");
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Info : ", "Loggez-vous"));
context.getExternalContext().getFlash().setKeepMessages(true);
//context.getExternalContext().redirect("../../index.xhtml");
return "../../index.xhtml?faces-redirect=true";
} else {
System.out.println("*** The session is still active. User is logged in. *** ");
}
return "../../index.xhtml?faces-redirect=true";
}
当然,限制页面有这个:
<f:event type="preRenderView" listener="#{userloginMB.permission()}"/>
使用获取外部上下文的重定向会使消息丢失。
当使用 faces-redirect=true 时,您需要从 root context 指定 absolute path。
因此您的结果字符串应如下所示:
return "/dir1/dir2/index.xhtml?faces-redirect=true";
如果 index.xhtml 驻留在(上下文根)中,即 Web Content/index.xhtml 则使用此结果字符串:
return "/index.xhtml?faces-redirect=true";
如果 index.xhtml 驻留在 Web Content/pages/dir2/index.xhtml 中,则使用此结果字符串:
return "/pages/dir2/index.xhtml?faces-redirect=true";
忽略一般设计问题(寻找 here 作为起点),您似乎混淆了新的 JSF 2.2 <f:viewAction>
和旧的 JSF 2.0/2.1 <f:event type="preRenderView">
把戏。
仅 <f:viewAction>
支持在 GET 请求中将导航结果作为 String
返回,<f:event type="preRenderView">
不支持。对于后者,您需要 ExternalContext#redirect()
,而您碰巧已经注释掉了它。
所以,你应该做任何一个
<f:event type="preRenderView" listener="#{bean.onload}"/>
public void onload() throws IOException {
// ...
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
ec.redirect(ec.getRequestContextPath() + "/index.xhtml");
}
或
<f:metadata>
<f:viewAction action="#{bean.onload}"/>
</f:metadata>
public String onload() {
// ...
return "/index.xhtml"; // Note: no need for faces-redirect=true!
}
不要混淆它们。
请注意,我以这样的方式编写代码,您始终可以使用相对于网络根目录的 /path
,而无需 fiddle 和 ../
废话。
另请参阅:
- What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
我终于在页面之间传递了消息,但这并没有将我重定向到用户登录页面 (../../index.xhtml),而是显示了禁止访问的页面:
public String permission() throws IOException {
FacesContext context = FacesContext.getCurrentInstance();
Map<String, Object> sessionMap = context.getExternalContext().getSessionMap();
String isLog = (String) sessionMap.get("isLogged");
if(isLog != "TRUE") {
System.out.println("*** The user has no permission to visit this page. *** ");
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Info : ", "Loggez-vous"));
context.getExternalContext().getFlash().setKeepMessages(true);
//context.getExternalContext().redirect("../../index.xhtml");
return "../../index.xhtml?faces-redirect=true";
} else {
System.out.println("*** The session is still active. User is logged in. *** ");
}
return "../../index.xhtml?faces-redirect=true";
}
当然,限制页面有这个:
<f:event type="preRenderView" listener="#{userloginMB.permission()}"/>
使用获取外部上下文的重定向会使消息丢失。
当使用 faces-redirect=true 时,您需要从 root context 指定 absolute path。
因此您的结果字符串应如下所示:
return "/dir1/dir2/index.xhtml?faces-redirect=true";
如果 index.xhtml 驻留在(上下文根)中,即 Web Content/index.xhtml 则使用此结果字符串:
return "/index.xhtml?faces-redirect=true";
如果 index.xhtml 驻留在 Web Content/pages/dir2/index.xhtml 中,则使用此结果字符串:
return "/pages/dir2/index.xhtml?faces-redirect=true";
忽略一般设计问题(寻找 here 作为起点),您似乎混淆了新的 JSF 2.2 <f:viewAction>
和旧的 JSF 2.0/2.1 <f:event type="preRenderView">
把戏。
仅 <f:viewAction>
支持在 GET 请求中将导航结果作为 String
返回,<f:event type="preRenderView">
不支持。对于后者,您需要 ExternalContext#redirect()
,而您碰巧已经注释掉了它。
所以,你应该做任何一个
<f:event type="preRenderView" listener="#{bean.onload}"/>
public void onload() throws IOException {
// ...
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
ec.redirect(ec.getRequestContextPath() + "/index.xhtml");
}
或
<f:metadata>
<f:viewAction action="#{bean.onload}"/>
</f:metadata>
public String onload() {
// ...
return "/index.xhtml"; // Note: no need for faces-redirect=true!
}
不要混淆它们。
请注意,我以这样的方式编写代码,您始终可以使用相对于网络根目录的 /path
,而无需 fiddle 和 ../
废话。
另请参阅:
- What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?