这个问题与这个问题非常相似:Using JSF 2.0 / Facelets, is there a way to attach a global listener to all AJAX calls? 但是解决方案对我不起作用。我错过了一些东西。
问题是:当会话过期时,我单击一些 ajax 链接/按钮并发送重定向(来自Filter
)浏览器不更新页面 接收最后一个非 AJAX 请求的页面。
我所拥有的是:
- WebSphere 上的 JSF 2.1(我也使用 Richfaces 4.2.0)
- 我使用 AJAX(登录后的第一个请求除外)
- 我
@ManagedBean(name = "user") @SessionScoped UserBean
与字段一起使用User user
(这又是用于用户访问管理的 EJB 实体类) - 我使用 OmniFaces 类来执行
FullAjaxExceptionHandler
(没有我的过滤器它工作正常,感谢 BalusC) 我使用
javax.servlet.Filter
映射到来@WebFilter("*.xhtml")
管理对资源的访问和登录检查。doFilter()
函数片段:.... if (user == null) { // if user is not logged in redirectToLogin(req, res); }
并且在同一个 Filter 类中有
redirectToLogin()
函数(再次感谢 BalusC (= ):private static final String FACES_REDIRECT_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<partial-response><redirect url=\"%s\"></redirect></partial-response>"; protected void redirectToLogin(ServletRequest req, ServletResponse res) throws IOException { HttpServletRequest request = (HttpServletRequest) req; if ("partial/ajax".equals(request.getHeader("Faces-Request"))) { res.setContentType("text/xml"); res.setCharacterEncoding("UTF-8"); res.getWriter().printf(FACES_REDIRECT_XML, request.getContextPath() + "/login.xhtml"); } else { String url = request.getContextPath() + "/login.xhtml"; HttpServletResponse resHttp = (HttpServletResponse) res; resHttp.sendRedirect(url); } }
当会话过期时,我单击了一些 ajax 链接/按钮(发生 ViewExpiredException)。我可以在调试中看到字符串res.getWriter().printf(FACES_REDIRECT_XML, request.getContextPath() + "/login.xhtml");
执行。我还可以看到 HTTP REDIRECT 请求和响应登录.xhtml(那不是登录页面,这是上次发出非 AJAX 请求的旧页面!) Firebug 中的页面,但浏览器不更新视图.
我能否以某种方式检测到过滤器(FacesContext 外部)中发生 ViewExpiredException 并将控制权传递给 FullAjaxExceptionHandler?(顺便说一句,如果可能的话,我不再需要 ajaxExceptionHandler 来处理 ViewExpiredException,对吧?)浏览器页面没有更新的原因是什么?
正如我在帖子顶部提到的那样,我阅读并遵循了相关帖子的指导方针,但我错过了一些东西或误解了。会是什么呢?
谢谢。
更新:我收到的 HTML 代码是上次非 AJAX 请求返回的旧 HTML 页面!所以问题是 FacesServlet 不会将我的 login.xhtml 发送到客户端的浏览器。
Update2:我发现我从 FasesServlet 收到的页面是最后一个非 AJAX 请求的页面(在我的情况下,这是我成功登录后看到的第一个视图)。(顺便说一句,浏览器仍然没有更新页面,并且存在由这一行引起的 XML 解析错误<!DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
:)
更新3:web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<session-config>
<session-timeout>
1
</session-timeout>
</session-config>
<context-param>
<param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
<param-value>true</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>login.xhtml</welcome-file>
</welcome-file-list>
<context-param>
<param-name>javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE</param-name>
<param-value>true</param-value>
</context-param>
<error-page>
<error-code>500</error-code>
<location>/errors/500.xhtml</location>
</error-page>
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/loginViewExpired.xhtml</location>
</error-page>
</web-app>