Jsf 根据用户权限,在preRenderViewEvent中导航到其他页面;ExternalContext#dispatch()不起作用

Jsf 根据用户权限,在preRenderViewEvent中导航到其他页面;ExternalContext#dispatch()不起作用,jsf,omnifaces,Jsf,Omnifaces,仅当用户具有查看该页面的权限时,才应呈现该页面。我尝试通过在PreRenderView事件侦听器方法中执行检查来实现这一点: <f:event type="preRenderView" listener="#{theBean.init}" /> 当我尝试查看拒绝页面时,我看到了它,但在服务器日志中出现异常: at org.omnifaces.util.FacesLocal.getRequestMap(FacesLocal.java:945) [omnifaces-1.7.jar:1

仅当用户具有查看该页面的权限时,才应呈现该页面。我尝试通过在PreRenderView事件侦听器方法中执行检查来实现这一点:

<f:event type="preRenderView" listener="#{theBean.init}" />
当我尝试查看拒绝页面时,我看到了它,但在服务器日志中出现异常:

at org.omnifaces.util.FacesLocal.getRequestMap(FacesLocal.java:945) [omnifaces-1.7.jar:1.7]
at org.omnifaces.util.FacesLocal.getRequestAttribute(FacesLocal.java:953) [omnifaces-1.7.jar:1.7]
at org.omnifaces.util.Faces.getRequestAttribute(Faces.java:1416) [omnifaces-1.7.jar:1.7]
at org.omnifaces.eventlistener.CallbackPhaseListener.getCallbackPhaseListeners(CallbackPhaseListener.java:110) [omnifaces-1.7.jar:1.7]
at org.omnifaces.eventlistener.CallbackPhaseListener.afterPhase(CallbackPhaseListener.java:77) [omnifaces-1.7.jar:1.7]
at com.sun.faces.lifecycle.Phase.handleAfterPhase(Phase.java:189) [jsf-impl-2.1.7-jbossorg-2.jar:]
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:107) [jsf-impl-2.1.7-jbossorg-2.jar:]
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139) [jsf-impl-2.1.7-jbossorg-2.jar:]
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:594) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:]
at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:98) [primefaces-4.0.7.jar:4.0.7]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:]
at org.jboss.weld.servlet.ConversationPropagationFilter.doFilter(ConversationPropagationFilter.java:62) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:]
...
原因:在dispatch调用之后,FacesContext.getCurrentInstance()立即返回null。但这不会中断当前阶段。因此,在相位结束时,执行PhaseListener。它尝试获取FacesContext实例,但获取null

我可以在这里避免执行PhaseListener吗? 或者可能是检查FacesContext当前实例不为null是否应添加到omnifaces

谢谢。

永远不要使用。在一个像样的JSF web应用程序中,这种方法没有一个合理的用例。它只会破坏JSF的生命周期,因为它会在当前请求中创建另一个
FacesContext
。您应该使用JSF自己的或使用

当您已经使用JSF2.2时,请使用支持导航案例结果的
(如
):

或者当您仍然使用JSF 2.0/2.1,因此只能使用
,并且如果您使用的是OmniFaces,请使用其Or:

如果您没有使用OmniFaces,以下是它的实现方式:

public void init() {
    // ...
    FacesContext context = FacesContext.getCurrentInstance();
    context.getApplication().getNavigationHandler().handleNavigation(context, null, "someViewId");
}

请注意,当使用
@PostConstruct
而不是
f:viewAction
preRenderView
时,这一切仍可能失败。另请参见a.o.

制作此行
fc.responseCommlete()
try…catch
块中的最后一行。有一个拼写错误,无法编译。(OmniFaces与例外情况无关)我尝试了两种情况。没有什么变化。看起来两者都应该很好。使用
responseComplete()
我们只是中断了JSF生命周期,但没有提交响应,不是吗?正如您所说,我已经纠正了它。谢谢根据文件,这是更正确的方法。即使两者都可以正常工作。您正在使用
ExternalContext#dispatch(“/path/to/resource”)(可能是404-我昨天没有太集中精力)。如果需要限制访问(当授权(权限检查)失败时),应使用
ExternalContext#redirect(“/path/to/resource”);有条件地重定向到公共资源。在这两种情况下,
FacesContext#responseComplete()完全没有必要。您在实际应用中是否需要它?此外,如果您使用的是JSF2.2,那么最好将
替换为
。我想使用dispatch,因为我不想更改客户端浏览器中的URL。
public String init() {
    // ...
    return "someViewId";
}
public void init() {
    // ...
    Faces.navigate("someViewId");
}
public void init() {
    // ...
    FacesContext context = FacesContext.getCurrentInstance();
    context.getApplication().getNavigationHandler().handleNavigation(context, null, "someViewId");
}