首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ThreadLocal in DispatcherServlet

ThreadLocal in DispatcherServlet
EN

Stack Overflow用户
提问于 2016-02-03 11:54:52
回答 1查看 1K关注 0票数 1

我有一个带有javascript的Spring (v4.1.3) web应用程序。我已经实现了一个自定义DispatcherServlet,并在web.xml中配置了相同的

在UI向服务器发出的每个请求的HTTP头中都有一个独特的屏幕代码。

在自定义dispatcher servlet的doService方法中,我捕获Header并将值放入ThreadLocal dto变量中。我访问服务层中的这个ThreadLocal变量,以执行一些审计逻辑,这对于所有请求来说都是常见的。

来自CustomDispatcherServlet的代码:

代码语言:javascript
复制
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
    String uiCode = request.getHeader("uiCode");

    if ((uiCode != null && !uiCode.trim().isEmpty())) {
        UiCodeDto uiCodeDto = new UiCodeDto(uiCode);
        final ThreadLocal<UiCodeDto> threadLocalUser = new ThreadLocal<UiCodeDto>();
        threadLocalUser.set(uiCodeDto);
    }

    ...
    super.doService(request, response);
}

来自服务层的代码:

代码语言:javascript
复制
UiCodeDto temp = ThreadLocalUtil.getUiCodeDto(Thread.currentThread());

从ThreadLocalUtil检索ThreadLocal值的代码:

代码语言:javascript
复制
public final class ThreadLocalUtil {
    public static UiCodeDto getUiCodeDto(Thread currThread) {
        UiCodeDto UiCodeDto = null;

        try {
            Field threadLocals = Thread.class.getDeclaredField("threadLocals");
            threadLocals.setAccessible(true);
            Object currentThread = threadLocals.get(currThread);
            Field threadLocalsMap = currentThread.getClass().getDeclaredField("table");
            threadLocalsMap.setAccessible(true);
            threadLocalsMap.setAccessible(true);
            Object[] objectKeys = (Object[]) threadLocalsMap.get(currentThread);
            for (Object objectKey : objectKeys) {
                if (objectKey != null) {
                    Field objectMap = objectKey.getClass().getDeclaredField("value");
                    objectMap.setAccessible(true);
                    Object object = objectMap.get(objectKey);

                    if (object instanceof UiCodeDto) {
                        UiCodeDto = (UiCodeDto) object;
                        break;
                    }
                }
            }
        } catch (Exception e) {
            ...
        }

        return UiCodeDto;
    }
}

问题如下: 1.我得到了屏幕代码的随机值,这意味着http请求N的值将出现在http请求N+1中。2. ThreadLocal变量中存在空DTO,同名-因此,有时当我访问服务层的ThreadLocal时,我会得到一个null。

在理解ThreadLocal在DispatcherServlet中的行为方面,我需要帮助--为什么它会在doService方法中获得另一个请求的值?

提前谢谢。

EN

回答 1

Stack Overflow用户

发布于 2016-02-03 13:45:59

更多的Spring方法是使用请求范围bean来提取和保存标题:

代码语言:javascript
复制
@Component
@Scope(scopeName = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UiCodeDto {
    private String uiCode;

    @Inject
    public void setCode(HttpServletRequest req) {
        uiCode = req.getHeader("uiCode");
    }

    public String getUiCode() {
        return uiCode;
    }
}

您可以像普通的bean一样使用它:

代码语言:javascript
复制
@Service
public class RandomService {

    @Inject
    UiCodeDto uiCodeDto;

    public void handle() {
        System.out.println(uiCodeDto.getUiCode());
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35176357

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档