当前位置: 首页 > 知识库问答 >
问题:

将ThreadLocal与Filter、HttpSession和Session属性一起使用时的不一致性

韩夕
2023-03-14

我使用的是一个存储字符串的ThreadLocal对象。我将String值设置为过滤器中的ThreadLocal对象,该对象将截取符合特定条件的所有请求。另外,我将ThreadLocal的字符串值设置为HttpSession作为属性。

那么,有什么方法可以改变实现,使多个会话不使用同一个线程呢?

编辑:添加示例代码

public class ContextFilter implements Filter {

    //No significant variables other than constants

    public void doFilter(ServletRequest request, ServletResponse response,
                FilterChain chain) throws IOException, ServletException {

            // Set the Session Timeout Object
            SessionTimeoutObject obj = (SessionTimeoutObject) httpRequest
                    .getSession().getAttribute(KEY);
            if (obj == null) {
                httpRequest.getSession().setAttribute(KEY,
                        new SessionTimeoutObject());
            }

            if( some conditions ) {
                chain.doFilter(request, response);
            } else {
                //Defaulting identifier
                String identifier = "init";

                if (ContextHolder.getId() != null
                        && !ContextHolder.getId().equals("")) {
                    identifier = ContextHolder.getId());
                }

                //Do some thing 

                //Compare the identifier with the value in session and use if it exists
                String existingId = (String) httpRequest.getSession()
                        .getAttribute(ID_KEY);
                if (existingId != null
                        && !existingId.trim().equals("")) {
                    identifier = existingId;
                }

                //Setting id to context only happens here
                ContextHolder.setId(identifier);
                //Validate the identifier

                //Get Business Obj method using identifier
                BusinessObj bo = getBusObj(identifier);

                //everything above is successful so set in session
                httpRequest.getSession().setAttribute("identifier", identifier);
                httpRequest.getSession().setAttribute("BusinessObj",
                    bo);

                //no exceptions yet then good to go
                chain.doFilter(request, response);
            }

    }


}

public class SessionTimeoutObject implements Serializable, HttpSessionBindingListener {

    private String backup;

    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        //Mainly for debuggin what happens to the session
        backup = (String) event.getSession().getAttribute("identifier");
    }

    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        //Mainly for debuggin what happens to the session
        if (ContextHolder.getId() != null) {
            backup = ContextHolder.getId();
        } 
    }

}

class ContextHolder {

    private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();

    public ContextHolder() {
    }

    public static void setId(String identifier) {
        if (null == identifier) {
            //throw some exception
        }
        contextHolder.set(identifier);
    }

    public static String getId() {
        return (String) contextHolder.get();
    }

    public static void clearId() {
        contextHolder.remove();
    }

    public static void setDefaultId() {
        ContextHolder.clearId();
        contextHolder.set('init');
    }
}

共有1个答案

党博超
2023-03-14

您应该将代码包装在try/finally块中,在finally块中执行contextholder.clearid()以清除上下文持有者。这一点很重要,因为请求处理线程是重用的,这意味着ContextHolders线程本地保留与以前相同的id。-M.Deinum

做到以上几点就解决了问题。

 类似资料:
  • 我有一个重命名了布尔变量的FileBean。它有以下代码。 我已经使用请求对象将其对象传递给jsp(考虑fileDetail是一个请求属性名)。我的jsp包含以下代码。 使用这个,我在jsp上获得了以下运行时异常。 请向我建议解决办法。 提前谢谢。

  • 问题内容: 我想分享我使用素数,f:viewParam和p:commandButton的经验,并提出一些问题。请看此页面: 支持bean具有不执行任何操作的“ myMethod()”方法。当您进入页面时,它需要“ id_file”参数并将其放在备用bean的idFile属性中。然后单击按钮,然后调用myMethod。然后再次单击,将得到一个模糊的验证错误,并且永远不会调用myMethod: 首先,

  • 实际上,我们使用Google IdP作为应用程序的SSO/SAML身份验证类型。我们已将其配置为将用户连接到应用程序,并且运行良好。但最近,我们还想要求用户对应用程序生命周期中可能发生的不同操作进行重新验证。 更详细地说,当我们向Google Idp发送SAML请求时,我们在节点“AuthnRequest”中添加了属性ForceAuthn=“true”,我们还添加了AuthnContextClas

  • 属性文件如何与Apache Camel一起使用,以引用可配置的属性。例如,如果有从文件夹读取文件的路由,那么如何在属性文件中配置该文件夹位置。我正在使用JavaDSL。

  • 我试图在Material UI的TextField上使用React的“ref”属性访问输入数据。通过“inputRef”或“inputProps”似乎没有一种简单的方法可以做到这一点。 下面的示例显示了第26行的inputProps的使用。将TextField的名称指定给“ref”属性似乎不会生成有效的对象。 对于“inputRef”,根据Material ui文档,它强制使用函数,尝试将字段数据

  • 出于某种原因,属性不起作用,即使url是正确的,但具有属性。 模板: 脚本: 我做错了什么?欢迎任何帮助。