显示成功消息,然后在超时后使用PageFlow重定向到另一个页面

问题描述:

如何显示成功消息,然后在超时(例如)后将用户重定向到另一个页面5秒?

How can I show a success message and then redirect the user to another page after a timeout of e.g. 5 seconds?

成功登录后,我需要此用于登录页面.我尝试了以下操作,但在登录失败时可以看到警告消息,但在登录成功时却看不到成功消息.它会立即显示目标页面.

I need this for the login page after a successful login. I tried the following and I can see the warning message on login failure, but not the success message on login success. It shows immediately the target page.

public String check(){
      if (username.equals("test") && password.equals("test")) {
          FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,"Sample info message", "PrimeFaces rocks!")); 
            return "Success";
        }else{
          FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN,"Sample warn message", "Watch out for PrimeFaces!"));  
            return "Failure";
        }
    }

我正在使用Seam的PageFlow进行导航.

I'm using Seam's PageFlow for navigation.

我有一个

<p:messages id="messages" showDetail="true" autoUpdate="true" closable="true" />

在登录页面上.

首先,使用您发布的代码,您不会在重定向之前看到FacesMessage,而在重定向之后会看到它.但是,为了实现这一点,您需要添加一个过滤器,因为重定向时消息会丢失.这是您需要的过滤器的代码(别忘了在web.xml中声明它):

First of all, with the code you posted you won't see the FacesMessage before the redirect, you'll see it after the redirect. But also, in order to make that happen you'll need to add a filter, because messages are lost when you redirect. This is the code for the filter you need (don't forget to declare it in web.xml):

public class MultiPageMessagesSupport implements PhaseListener {

private static final long serialVersionUID = 1250469273857785274L;
private static final String sessionToken = "MULTI_PAGE_MESSAGES_SUPPORT";

@Override
public PhaseId getPhaseId() {
    return PhaseId.ANY_PHASE;
}

/*
 * Check to see if we are "naturally" in the RENDER_RESPONSE phase. If we
 * have arrived here and the response is already complete, then the page is
 * not going to show up: don't display messages yet.
 */
@Override
public void beforePhase(final PhaseEvent event) {
    FacesContext facesContext = event.getFacesContext();
    int msg = this.saveMessages(facesContext);

    if (PhaseId.RENDER_RESPONSE.equals(event.getPhaseId())) {
        if (!facesContext.getResponseComplete()) {
            this.restoreMessages(facesContext);
        }
    }
}

/*
 * Save messages into the session after every phase.
 */
@Override
public void afterPhase(final PhaseEvent event) {
    if (event.getPhaseId() == PhaseId.APPLY_REQUEST_VALUES ||
            event.getPhaseId() == PhaseId.PROCESS_VALIDATIONS ||
            event.getPhaseId() == PhaseId.INVOKE_APPLICATION) {
        FacesContext facesContext = event.getFacesContext();
        int msg = this.saveMessages(facesContext);
    }
}

@SuppressWarnings("unchecked")
private int saveMessages(final FacesContext facesContext) {
    List<FacesMessage> messages = new ArrayList<FacesMessage>();
    for (Iterator<FacesMessage> iter = facesContext.getMessages(null); iter.hasNext();) {
        messages.add(iter.next());
        iter.remove();
    }

    if (messages.isEmpty()) {
        return 0;
    }

    Map<String, Object> sessionMap = facesContext.getExternalContext().getSessionMap();
    List<FacesMessage> existingMessages = (List<FacesMessage>) sessionMap.get(sessionToken);
    if (existingMessages != null) {
        existingMessages.addAll(messages);
    } else {
        sessionMap.put(sessionToken, messages);
    }
    return messages.size();
}

@SuppressWarnings("unchecked")
private int restoreMessages(final FacesContext facesContext) {
    Map<String, Object> sessionMap = facesContext.getExternalContext().getSessionMap();
    List<FacesMessage> messages = (List<FacesMessage>) sessionMap.remove(sessionToken);

    if (messages == null) {
        return 0;
    }

    int restoredCount = messages.size();
    for (Object element : messages) {
        facesContext.addMessage(null, (FacesMessage) element);
    }
    return restoredCount;
}
}

如果这对您不起作用,并且您需要在此之前显示该消息,那么您将必须执行以下操作:使该方法返回void,通过ajax调用它,并在添加成功消息后调用一些javascript方法,将等待几秒钟,然后进行重定向(也许可以通过编程方式单击一个重定向到下一页的隐藏按钮). 我认为这不值得麻烦,您只会延迟登录过程.无论如何,用户将知道登录成功,因为他将被重定向到主页(或您发送给他的任何页面)

If this doesn't work for you, and you need to show the message before, then you'll have to something like the following: make the method return void, invoke it through ajax, and after adding the success message invoke some javascript method that will wait a couple of seconds and then make the redirect (maybe by programmatically clicking a hidden button that redirects to next page). In my opinion this is not worth the trouble, you will just delay the login process. Anyway user will know tha tlogin succeeded because he will be redirect to home page (or whatever page you send him to)

方法完成后,消息将显示在页面中,因此在托管bean方法中等待将不起作用.添加FacesMessage之后,使用

the messages are displayed in the page when the method finishes, so waiting in the managed bean method won't work. after adding the FacesMessage, use

RequestContext.getCurrentInstance().execute("waitAndRedirect()");

在您的xhtml中,您需要具有与此类似的javascript函数:

And in your xhtml, you'll need to have a javascript function similar to this:

function waitAndRedirect() {
    setTimeout(function() {
        hiddenButtonId.click();
    }, 2000);
}

其中hiddenButtonId是p:button的ID,该p:button重定向到主页并被隐藏(display:none)

where hiddenButtonId is the ID of a p:button which redirects to home page and is hidden (display:none)

但是,这又是一种令人讨厌的方法,我认为没有必要这样做,您只会延迟登录过程.

But again, this a nasty approach, in my opinion there's no need to do this, you will just delay the login process.