用户刷新页面 错误消失了 如何保存页面刷新错误?
这就是MessageStoreInterceptor的工作方式。它实际上是一个功能,而不是错误。
页面刷新是用户触发的操作,这意味着可以假定他已经阅读了上一个操作(登录尝试)的结果,除非他闭着眼睛按F5键。
您应该希望消息在第一次读取后过期。
考虑具有很多非ajax操作的页面,例如,组合框取决于其他操作,等等。…如果错误消息持续存在,则它将在每次不涉及进入另一个页面的提交操作之后弹出。
你不要那样 您应该希望收到一条消息,指出在 该 操作之后一个操作出了错(或正确)。如果用户随后继续执行其他操作(如刷新),并且这些操作没有出错(或处于特定的成功状态),则不会显示任何消息。
在那之后,也有不少世界问题 时,从会话持久性消息删除,否则你会与下一个动作得到该消息RETRIEVE或AUTOMATIC一个operationMode。然后,您可以(但不应该)自定义MessageStore拦截器,或自行在会话之间写入/读取/删除消息,从而从根本上重新发明轮子。甚至放置两个MessageStore拦截器,一个RETRIEVE和一个STORE用于displayLoginPageAction,得到刚才提到的陷阱。
RETRIEVE
AUTOMATIC
STORE
displayLoginPage
您还使用PRG模式(发布/重定向/获取),以避免刷新页面时重新发送数据。同样,您应该避免重复读取相同的消息两次。
要查看它是如何工作的,可以看一下MessageStore Interceptor源代码,它很简单:
ValidationAware
operationMode
actionMessages
actionErrors
fieldErrors
/** * Handle the retrieving of field errors / action messages / field errors, which is * done before action invocation, and the <code>operationMode</code> is 'RETRIEVE'. * * @param invocation * @throws Exception */ protected void before(ActionInvocation invocation) throws Exception { String reqOperationMode = getRequestOperationMode(invocation); if (RETRIEVE_MODE.equalsIgnoreCase(reqOperationMode) || RETRIEVE_MODE.equalsIgnoreCase(operationMode) || AUTOMATIC_MODE.equalsIgnoreCase(operationMode)) { Object action = invocation.getAction(); if (action instanceof ValidationAware) { // retrieve error / message from session Map session = (Map) invocation.getInvocationContext().get(ActionContext.SESSION); if (session == null) { if (LOG.isDebugEnabled()) { LOG.debug("Session is not open, no errors / messages could be retrieve for action ["+action+"]"); } return; } ValidationAware validationAwareAction = (ValidationAware) action; if (LOG.isDebugEnabled()) { LOG.debug("retrieve error / message from session to populate into action ["+action+"]"); } Collection actionErrors = (Collection) session.get(actionErrorsSessionKey); Collection actionMessages = (Collection) session.get(actionMessagesSessionKey); Map fieldErrors = (Map) session.get(fieldErrorsSessionKey); if (actionErrors != null && actionErrors.size() > 0) { Collection mergedActionErrors = mergeCollection(validationAwareAction.getActionErrors(), actionErrors); validationAwareAction.setActionErrors(mergedActionErrors); } if (actionMessages != null && actionMessages.size() > 0) { Collection mergedActionMessages = mergeCollection(validationAwareAction.getActionMessages(), actionMessages); validationAwareAction.setActionMessages(mergedActionMessages); } if (fieldErrors != null && fieldErrors.size() > 0) { Map mergedFieldErrors = mergeMap(validationAwareAction.getFieldErrors(), fieldErrors); validationAwareAction.setFieldErrors(mergedFieldErrors); } session.remove(actionErrorsSessionKey); session.remove(actionMessagesSessionKey); session.remove(fieldErrorsSessionKey); } } }
redirectAction
/** * Handle the storing of field errors / action messages / field errors, which is * done after action invocation, and the <code>operationMode</code> is in 'STORE'. * * @param invocation * @param result * @throws Exception */ protected void after(ActionInvocation invocation, String result) throws Exception { String reqOperationMode = getRequestOperationMode(invocation); boolean isRedirect = invocation.getResult() instanceof ServletRedirectResult; if (STORE_MODE.equalsIgnoreCase(reqOperationMode) || STORE_MODE.equalsIgnoreCase(operationMode) || (AUTOMATIC_MODE.equalsIgnoreCase(operationMode) && isRedirect)) { Object action = invocation.getAction(); if (action instanceof ValidationAware) { // store error / messages into session Map session = (Map) invocation.getInvocationContext().get(ActionContext.SESSION); if (session == null) { if (LOG.isDebugEnabled()) { LOG.debug("Could not store action ["+action+"] error/messages into session, because session hasn't been opened yet."); } return; } if (LOG.isDebugEnabled()) { LOG.debug("store action ["+action+"] error/messages into session "); } ValidationAware validationAwareAction = (ValidationAware) action; session.put(actionErrorsSessionKey, validationAwareAction.getActionErrors()); session.put(actionMessagesSessionKey, validationAwareAction.getActionMessages()); session.put(fieldErrorsSessionKey, validationAwareAction.getFieldErrors()); } else if(LOG.isDebugEnabled()) { LOG.debug("Action ["+action+"] is not ValidationAware, no message / error that are storeable"); } } }
注1 :登录操作也是不言自明的:如果登录后再次进入登录页面,则仅表示登录失败…顺便说一句,以上说明适用于每个页面/功能 注2 :网站产生的消息会在X秒钟后自动过期,而不关心用户是否已阅读这些消息…… 这 与可用性恕我直言。
用户刷新页面
错误消失了
如何保存页面刷新错误?
在那之后,也有不少世界问题 时, 从会话持久性消息删除,否则你会与下一个动作得到该消息RETRIEVE或AUTOMATIC一个operationMode。然后,您可以(但不应该)自定义MessageStore拦截器,或自行在会话之间写入/读取/删除消息,从而从根本上重新发明轮子。甚至放置两个MessageStore拦截器,一个RETRIEVE和一个STORE用于displayLoginPageAction,得到刚才提到的陷阱。
在调用之前,如果Action是 ValidationAwareand operationMode是RETRIEVEor AUTOMATIC:
/* * Handle the retrieving of field errors / action messages / field errors, which is * done before action invocation, and the operationMode is ‘RETRIEVE’. * * @param invocation * @throws Exception / protected void before(ActionInvocation invocation) throws Exception { String reqOperationMode = getRequestOperationMode(invocation);
if (RETRIEVE_MODE.equalsIgnoreCase(reqOperationMode) || RETRIEVE_MODE.equalsIgnoreCase(operationMode) || AUTOMATIC_MODE.equalsIgnoreCase(operationMode)) { Object action = invocation.getAction(); if (action instanceof ValidationAware) { // retrieve error / message from session Map session = (Map) invocation.getInvocationContext().get(ActionContext.SESSION); if (session == null) { if (LOG.isDebugEnabled()) { LOG.debug("Session is not open, no errors / messages could be retrieve for action ["+action+"]"); } return; } ValidationAware validationAwareAction = (ValidationAware) action; if (LOG.isDebugEnabled()) { LOG.debug("retrieve error / message from session to populate into action ["+action+"]"); } Collection actionErrors = (Collection) session.get(actionErrorsSessionKey); Collection actionMessages = (Collection) session.get(actionMessagesSessionKey); Map fieldErrors = (Map) session.get(fieldErrorsSessionKey); if (actionErrors != null && actionErrors.size() > 0) { Collection mergedActionErrors = mergeCollection(validationAwareAction.getActionErrors(), actionErrors); validationAwareAction.setActionErrors(mergedActionErrors); } if (actionMessages != null && actionMessages.size() > 0) { Collection mergedActionMessages = mergeCollection(validationAwareAction.getActionMessages(), actionMessages); validationAwareAction.setActionMessages(mergedActionMessages); } if (fieldErrors != null && fieldErrors.size() > 0) { Map mergedFieldErrors = mergeMap(validationAwareAction.getFieldErrors(), fieldErrors); validationAwareAction.setFieldErrors(mergedFieldErrors); } session.remove(actionErrorsSessionKey); session.remove(actionMessagesSessionKey); session.remove(fieldErrorsSessionKey); } }
}
调用后,如果Action是 ValidationAwareand operationMode是STOREor(或operationModeis是AUTOMATICResult的类型redirectAction):
/* * Handle the storing of field errors / action messages / field errors, which is * done after action invocation, and the operationMode is in ‘STORE’. * * @param invocation * @param result * @throws Exception / protected void after(ActionInvocation invocation, String result) throws Exception {
String reqOperationMode = getRequestOperationMode(invocation); boolean isRedirect = invocation.getResult() instanceof ServletRedirectResult; if (STORE_MODE.equalsIgnoreCase(reqOperationMode) || STORE_MODE.equalsIgnoreCase(operationMode) || (AUTOMATIC_MODE.equalsIgnoreCase(operationMode) && isRedirect)) { Object action = invocation.getAction(); if (action instanceof ValidationAware) { // store error / messages into session Map session = (Map) invocation.getInvocationContext().get(ActionContext.SESSION); if (session == null) { if (LOG.isDebugEnabled()) { LOG.debug("Could not store action ["+action+"] error/messages into session, because session hasn't been opened yet."); } return; } if (LOG.isDebugEnabled()) { LOG.debug("store action ["+action+"] error/messages into session "); } ValidationAware validationAwareAction = (ValidationAware) action; session.put(actionErrorsSessionKey, validationAwareAction.getActionErrors()); session.put(actionMessagesSessionKey, validationAwareAction.getActionMessages()); session.put(fieldErrorsSessionKey, validationAwareAction.getFieldErrors()); } else if(LOG.isDebugEnabled()) { LOG.debug("Action ["+action+"] is not ValidationAware, no message / error that are storeable"); } }