【问题标题】:Why is Phase Listener-based JSF redirect not working for AJAX requests when session has timed-out?为什么会话超时时基于 Phase Listener 的 JSF 重定向不适用于 AJAX 请求?
【发布时间】:2012-06-24 01:50:18
【问题描述】:

我有一个 JSF Phase Listerner,它检查用户是否登录,如果没有,将他们重定向到登录页面。这适用于非 ajax 请求。但是,如果用户在一个页面上,在我的例子中,这个页面有一个 primefaces 数据表,并单击一个调用 ajax 请求的按钮——但他们的会话已超时——代码被执行以发出重定向(使用ExternalContext#redirect),但是用户没有导航到登录页面。

知道为什么这不起作用吗?

这是我的相位监听器:

private static final String IS_LOGGED_IN_INDICATOR = "loggedIn";
private static final String LOGIN_PAGE = "/login.jsp";

public PhaseId getPhaseId() {
    return PhaseId.RESTORE_VIEW;
}

public void beforePhase(PhaseEvent event) {
    ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
    HttpSession session = (HttpSession)ec.getSession(false);

    if (session==null || session.getAttribute(IS_LOGGED_IN_INDICATOR) == null) {
       try {
            ec.redirect(LOGIN_PAGE);
       }
       catch(IOException e) {
           // log exception...
       }            
    }
}

public void afterPhase(PhaseEvent event) {
    // no-op
}   

}

【问题讨论】:

    标签: jsf-2


    【解决方案1】:

    这是因为您必须在 XML 中为 Ajax 请求发送一个特殊响应才能进行重定向(检查this answer),我已经在这样的过滤器中实现了这一点..

    // Check if it's an Ajax Request 
    if ("partial/ajax".equals(((HttpServletRequest) request).getHeader("Faces-Request"))) {
          //redirect 
          response.setContentType("text/xml");
          response.getWriter()
               .append("<?xml version=  \"1.0\" encoding=\"UTF-8\"?>")
               .printf("<partial-response><redirect url=\"%s\"></redirect></partial-response>",url);
    

    你应该把它移植到你的 Phase Listener。

    【讨论】:

    • 您引用的答案说,如果我在 JSF 上下文中,我不必做特殊响应:“如果 ajax 请求是由 JSF 本身发起的(例如 等等on) 并且 Java 代码在 JSF 上下文中运行,那么您应该使用 ExternalContext#redirect() 代替。这会自动检测当前请求是否是 ajax 请求,并将返回一个特殊的 XML 响应,告诉 JSF ajax 引擎进行更改窗口的位置”。总而言之,答案表明使用 ExternalContext#redirect 应该创建正确的 AJAX 响应来执行重定向。
    • 没错,我忽略了您没有使用过滤器的事实。只是出于好奇,您为什么使用 PhaseL 监听器而不是普通的 servlet 监听器?顺便说一句,您的跟踪中是否有任何错误?我在 primefaces 中看到了一些关于这个问题的错误...like this one..
    • 我使用了一个过滤器,但将它移到了一个阶段监听器,以利用 JSF 对 AJAX 和非 AJAX 请求进行重定向的能力。如果我还添加了您引用的代码来处理 AJAX 请求,那么 servlet 过滤器就会起作用。
    【解决方案2】:

    失败是因为 ajax 上下文试图从视图根目录获取渲染工具包,而根本没有视图根目录。那时还没有恢复。这导致NullPointerExceptionPartialViewContext#createPartialResponseWriter() 中。反过来,这个异常不会被抛出,而是被放入一个应该由自定义ExceptionHandler 处理的 ajax 异常队列中。你显然没有任何人。如果您创建/使用像 FullAjaxExceptionHandler 这样的异常,则此异常是可见的(有关更多详细信息,另请参阅 this blog)。

    要解决特定问题,请改为在afterPhase() 中执行此工作。然后完全恢复视图根,并且 ajax 上下文可以从中获取渲染工具包,以便编写专门的 XML 响应,指示 JavaScript 中的 JSF ajax 引擎更改窗口位置。如果没有 ajax,则不需要渲染工具包,因为重定向基本上只是设置响应标头的问题。

    特定的NullPointerException 是否又是 Mojarra 中的错误是另一个问题,最好在他们自己的问题跟踪器上以问题报告的形式发布。

    【讨论】:

      猜你喜欢
      • 2014-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-27
      • 1970-01-01
      • 2013-05-27
      • 2012-04-25
      相关资源
      最近更新 更多