我正在使用存储字符串的 ThreadLocal 对象。我正在将字符串值设置为过滤器中的 ThreadLocal 对象,该过滤器会拦截受特定条件约束的所有请求。此外,我将 ThreadLocal 的字符串值设置为 HttpSession 作为属性。
session中的属性被多个jsps使用,最终传递给业务层。
我面临的问题是,来自不同客户端的多个请求在某个时间点获得相同的字符串值,尽管会话不同。
所以我的理解是,多个会话访问同一个线程。我没有看到任何其他解释。
将属性设置为请求会导致在 jsps 之间移动时出现问题。由于spring security有重定向,这意味着请求属性丢失。
那么有什么办法可以改变实现,使多个会话不使用同一个线程?
编辑:添加示例代码
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');
}
}