在Spring WebFlow中优雅地处理过期的HttpSession

时间:2012-03-28 14:37:08

标签: spring-webflow

(来自SpringSource forum。)

HttpSession已过期且用户在流程中重新提交页面时,他/她将被发送回流程的开头。我想要添加到此行为的所有内容都是一条消息,解释了它发生的原因。 “你没有活动,所以你已经重新启动......”

最简单/最佳实践方法是什么?

3 个答案:

答案 0 :(得分:4)

默认行为,在FlowHandlerAdapter.defaultHandleException()中,“尝试开始执行已结束或已过期的流”。

看起来像WebFlow一样处理这种方法就是提供FlowHandler handleException()方法来检查instanceof NoSuchFlowExecutionException,然后执行类似构建重定向网址或地点的操作Session会话范围的内容,以后可以在使用后删除。

由于WebFlow使用重定向的方式,我认为任何其他作用域都不会允许稍后在新流的视图呈现时使用这样的标记或消息。

但是,仅仅在Interceptor甚至Filter中检测新会话似乎同样有效。这是我在之前对此进行的调查中最终完成的操作,如引用的论坛帖子中所述。我只是希望有更漂亮的东西。

此外,到新流程开始时,已经创建了一个新的会话ID,因此无法从flow.xml中初始检测到这种情况。

示例过滤器逻辑:

if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) {
    log.info("Expired Session ID: " + request.getRequestedSessionId());
    response.sendRedirect("sessionExpired");
}
else {
    chain.doFilter(request, response);
}

示例拦截器:

public class SessionExpiredInterceptor extends HandlerInterceptorAdapter
{
    private String redirectLocation = "sessionExpired";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
        Object handler) throws Exception
    {
        if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid())
        {
            response.sendRedirect(redirectLocation);
            return false;
        }

        return true;
    }

    public String getRedirectLocation() {
        return redirectLocation;
    }

    public void setRedirectLocation(String redirectLocation) {
        this.redirectLocation = redirectLocation;
    }
}

答案 1 :(得分:1)

第1步: FlowController有一个默认的handlerAdapter。要自定义会话异常,您需要编写自己的自定义处理程序适配器并将其注册到流控制器bean,如下所示:

<bean id="flowController" class="org.springframework.webflow.mvc.servlet.FlowController">
.
.<property name="flowHandlerAdapter" ref="customFlowHandlerAdapter"/>

.
</bean>

<bean id="customFlowHandlerAdapter" class="gov.mo.courts.pbw.adapters.CustomFlowHandlerAdapter"
     p:flowExecutor-ref="flowExecutor"/>

第2步: CustomFlowHandlerAdapter 在此类中重写defaultHandleException方法。这是webflow在异常情况下调用并重新初始化会话的方法。请注意,到目前为止已经创建了新会话。此时只有异常类型会告诉您上一个会话超时。

public class PbwFlowHandlerAdapter extends FlowHandlerAdapter{
protected void defaultHandleException(String flowId, FlowException e,
            HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        if(e instanceof NoSuchFlowExecutionException){
            if(e.getCause() instanceof NoSuchConversationException){
                //"use newly created session object within request object to save your   customized message."
            }
        }
        super.defaultHandleException(flowId, e, request, response);
    }

您应用的第一个视图页应该能够显示此消息。

<%
                        if (session.getAttribute(YOUR_CUSTOM_MSG_KEY) != null) {
                    %>
                    <p class="errormessage">
                    <%=session.getAttribute(YOUR_CUSTOM_MSG_KEY)%>
                    </p>
                    <%
                    //once the message has been shown, remove it from the session
                    //as a new session has already been started at this time
                        session.removeAttribute(YOUR_CUSTOM_MSG_KEY);
                            }
                    %>

希望这有帮助。

答案 2 :(得分:1)

来自the Jira request I had opened,WebFlow开发人员说,

  

Custom FlowHandler是过期会话的扩展点。您   可以重定向到流并附加查询参数,例如   restarted = true,然后在流程中声明<input name="restarted" type="boolean" value="flashScope.restarted" />

我还没有确认,但想分享信息。