添加来自 Spring Bean 的 JSF 消息

Add JSF Message From Spring Bean

我在从 Spring 组件向 FacesContext 添加消息时遇到问题。这是 senario:

  1. 用户从 .xhtml 页面登录
  2. Spring 安全授权用户
  3. 如果用户 success/failed、return 从 Spring 管理的 class 发送到 UI 的消息(AuthenticationFailureHandlerAuthenticationSuccessHandler ), 即 primefaces.

我无法通过以下方式添加消息:

@Component
public class LoginFailureHandler implements AuthenticationFailureHandler {

    private static Logger logger = LoggerFactory.getLogger(LoginFailureHandler.class);

    @Override
    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        logger.info("Login failed: " + httpServletRequest.getParameter("j_username"), e);
        FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Login Error", e.getLocalizedMessage());
        FacesContext.getCurrentInstance().addMessage(null, message);
        httpServletResponse.sendRedirect("/timsgui/login.jsf?error=1");
    }
}

因为这个 class 不在 JSF 生命周期中,所以 FacesContext.getCurrentInstance() returns null。这是我的 jsf 页面:

<body>

    <p:growl id="growl" sticky="true" showDetail="true" life="3000" />

    <h:form name="login" action="../j_spring_security_check" method="POST">
        <h:panelGrid>
            <h:outputLabel for="j_username" value="Username:"/>
            <p:inputText id="j_username"/>

            <h:outputLabel for="j_password" value="Password:"/>
            <p:password id="j_password"/>

            <!-- need CSRF protection which is enabled default after Spring 4-->
            <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
            <p:commandButton value="Login" update="growl" type="submit"/>
        </h:panelGrid>
    </h:form>

我试图将 FacesContext 注入 spring bean 但它仍然 returns null:

@ManagedProperty("#{facesContext}")

有没有我可以将当​​前 FacesContext 注入 Spring bean 或任何其他想法,我可以将来自 Spring Bean 的全局消息添加到 FacesContext没有 FacesContext.getCurrentInstance().addMessage()?

好的,我解决了这个问题。感谢@M.Delinum 和@Xtreme Biker 的建议。我将消息注入 HttpSession 并从 http 范围获取它。这是最终代码:

@Component
public class LoginFailureHandler implements AuthenticationFailureHandler {

    private static Logger logger = LoggerFactory.getLogger(LoginFailureHandler.class);

    @Override
    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        logger.info("Login failed: " + httpServletRequest.getParameter("j_username"), e);
        HttpSession session = httpServletRequest.getSession(false);
        if (session != null) {
            session.setAttribute("loginFailMessage", "Login is failed");
        }
        httpServletResponse.sendRedirect("/timsgui/login.jsf?error=true");
    }
}
<h:outputText value="#{sessionScope['loginFailMessage']}" rendered="#{not empty sessionScope['loginFailMessage']}" styleClass="highlight"/>