通过筛选设置FacesMessage

时间:2012-12-21 05:12:35

标签: java jsf message servlet-filters

在我的JSF应用程序中,有一个Filter用于检查authenticati0n进程。身份验证失败时,过滤器会重定向到login.xhtml

如何从FacesMessageFilter传递到我的登录页面?

虽然,我在下面使用,但不行。

FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, message, null));

AuthenticationFilter.java

public class AuthenticationFilter implements Filter  {
    private FilterConfig config;
    private ServletContext servletContext;

    public void init(FilterConfig filterConfig) {
        config = filterConfig;
        servletContext = config.getServletContext();
    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
        HttpSession session = httpRequest.getSession();
        User user = (User) session.getAttribute(Constants.LOGIN_USER);
        if (user == null) {
            ...
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, message, null));

            String loginView = httpRequest.getContextPath() + Constants.LOGIN_PAGE;
            httpResponse.sendRedirect(loginView);
        } else if (!user.getRole().equals(Role.SYSTEM_ADMINISTRATOR)) {
            ....
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, message, null));

            String loginView = httpRequest.getContextPath() + Constants.LOGIN_PAGE;
            httpResponse.sendRedirect(loginView);
        } else {
            filterChain.doFilter(servletRequest, servletResponse);
        }
        servletContext.log("Exiting the filter");
    }

    public void destroy() {
        //Nothing to do.
    }
}

2 个答案:

答案 0 :(得分:7)

FacesContextFacesServlet创建。当你进入过滤器时,它尚未被调用。过滤器在servlet之前运行。因此,您永远无法联系过滤器中的FacesContext。另外,面部消息是请求作用域,因此重定向会使它们无论如何都会消失。

login.xhtml<f:event type="preRenderView">期间自行设置。最简单的方法是让过滤器暂时将其放在会话范围内。

session.setAttribute("message", message);
httpResponse.sendRedirect(loginView);

然后在login.xhtml的预呈现视图侦听器方法中从会话范围中删除:

String message = (String) externalContext.getSessionMap().remove("message");

if (message != null) {
    context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, message, null));
}

答案 1 :(得分:0)

我遇到了类似的问题,试图在EJB计时器中获取FacesContext。 BalusC已经在多个线程上指出,不可能这样做。或者,您可以使用'ServletContextListener',但ScheduledExecutorService并不像EJB计时器那样很好地定义调度。

在任何情况下,他提出的一个建议是实际向由托管bean支持的JSF页面发出Web请求,以利用我想用计时器设置的应用程序作用域bean上的方法。

我提到这一点,因为看起来你可以做类似的事情,你将一个参数传递给JSF页面,其中包含你想要的消息和用户的IP地址等等。该页面可以由请求范围的bean支持,该bean具有注入其中的应用程序范围的bean,该bean以IP作为键存储在映射中。然后,当用户被重定向到登录页面时,该页面可以在请求作用域bean上调用get错误消息方法,并将相同的应用程序作用域bean注入其中,从而获取该IP的错误消息或沿着这些行的某些内容。

无论如何,我确信BalusC的答案足够且比这更恰当,但是他的“只是向ejb计时器提出请求”的建议对于我在应用程序作用域上调度方法调用很有用,我想我可能会在这里提出它的可能用途。

@BalusC你对我指的帖子有什么看法吗?我找不到。