Показать сообщение об успехе, а затем перенаправить на другую страницу по истечении времени ожидания с помощью PageFlow

Как я могу показать сообщение об успехе, а затем перенаправить пользователя на другую страницу по истечении времени ожидания, например. 5 секунд?

Мне нужно это для страницы входа в систему после успешного входа в систему. Я попробовал следующее, и я вижу предупреждающее сообщение об ошибке входа в систему, но не вижу сообщение об успешном входе в систему. Он сразу показывает целевую страницу.

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";
        }
    }

Я использую PageFlow от Seam для навигации.

у меня есть

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

на странице входа.


person Holysh    schedule 04.04.2013    source источник


Ответы (3)


Прежде всего, с кодом, который вы разместили, вы не увидите FacesMessage до перенаправления, вы увидите его после перенаправления. Но также, чтобы это произошло, вам нужно добавить фильтр, потому что сообщения теряются при перенаправлении. Это код нужного вам фильтра (не забудьте объявить его в 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;
}
}

Если это не работает для вас, и вам нужно показать сообщение раньше, вам нужно будет сделать что-то вроде следующего: сделать возврат метода недействительным, вызвать его через ajax и после добавления сообщения об успехе вызвать какой-либо метод javascript который подождет пару секунд, а затем сделает перенаправление (возможно, программным нажатием скрытой кнопки, которая перенаправляет на следующую страницу). На мой взгляд, это не стоит усилий, вы просто задержите процесс входа в систему. В любом случае пользователь будет знать, что tlogin прошел успешно, потому что он будет перенаправлен на домашнюю страницу (или на любую другую страницу, на которую вы его отправляете)

EDIT: сообщения отображаются на странице после завершения метода, поэтому ожидание в методе управляемого компонента не будет работать. после добавления FacesMessage используйте

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

И в вашем xhtml вам понадобится функция javascript, подобная этой:

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

где hiddenButtonId — это идентификатор кнопки p:, которая перенаправляет на домашнюю страницу и скрыта (display: none)

Но опять же, это неприятный подход, на мой взгляд, этого делать не нужно, вы просто затянете процесс входа в систему.

person damian    schedule 04.04.2013
comment
Привет @Damian, я работаю с ajax, я пробовал Thread.currentThread().sleep(5000); он позволяет странице ждать 5 секунд, но сообщение отображается после перенаправления, я просто хочу показать сообщение перед перенаправлением с помощью этого метода, спасибо !! - person Holysh; 04.04.2013
comment
Обратите внимание, что это целевое решение JSF 1.x. В JSF 2.x есть гораздо более приятный способ использования flash scope. - person BalusC; 04.04.2013
comment
@Holysh Я отредактировал ответ, чтобы объяснить, как сделать так, чтобы сообщение отображалось ДО перенаправления. - person damian; 04.04.2013

Это одна из утилит Flash. Вместо

FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,"Sample info message", "PrimeFaces rocks!"));:

просто используйте этот код

FacesContext facesContext = FacesContext.getCurrentInstance();
Flash flash = facesContext.getExternalContext().getFlash();
flash.setKeepMessages(true);
flash.setRedirect(true);
facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,"Sample info message", "PrimeFaces rocks!"));
person user1643352    schedule 04.04.2013
comment
Вызов setRedirect() не нужен. Обратите внимание, что сообщение появится на целевой странице, и поэтому OP должен иметь там <p:messages>. - person BalusC; 04.04.2013
comment
Привет @BalusC, я ждал твоего ответа :) да, это работает с моим кодом, а также с кодом, предоставленным пользователем..., но проблема в том, как я могу показать сообщение до перенаправления, а затем через 5 секунд, например, перенаправить на другую страницу - person Holysh; 04.04.2013
comment
Привет, Балус, какова точная полезность setRedirect? - person user1643352; 04.04.2013
comment
@Holysh, отображение сообщения в течение 5 секунд неэргономично, потому что, возможно, пользователь не увидит сообщение или потратит 5 секунд впустую. - person user1643352; 04.04.2013

вы не можете объявить MultiPageMessagesSupport в файле web.xml, вы должны объявить MultiPageMessagesSupport в файлеfaces-config.xml. пример:

enter code here

<lifecycle>
    <phase-listener>your.package.MultiPageMessagesSupport</phase-listener>
</lifecycle>
person Felipe    schedule 12.11.2013