RequestContextHolder源码、理解、使用

首先看这个类的变量:

    private static final boolean jsfPresent = ClassUtils.isPresent("javax.faces.context.FacesContext", RequestContextHolder.class.getClassLoader());
    private static final ThreadLocal<RequestAttributes> requestAttributesHolder = new NamedThreadLocal("Request attributes");
    private static final ThreadLocal<RequestAttributes> inheritableRequestAttributesHolder = new NamedInheritableThreadLocal("Request context");

使用了两个ThreadLocal来存储当前线程下的request。

对于ThreadLocal可以看相应的笔记。

看看这个ThreadLocal类是怎么获取request的。在类中直接调用了ThreadLocal的get()方法,该方法会判断,如果当前线程的ThreadLocalMap存在,就直接使用这个ThreadLocalMap,ThreadLocalMap里面存放着当前线程的信息。如果当前线程的ThreadLocalMap不存在就创建一个新的ThreadLocalMap,并保存。

@Nullable
public static RequestAttributes getRequestAttributes() {
    RequestAttributes attributes = (RequestAttributes)requestAttributesHolder.get();
    if (attributes == null) {
        attributes = (RequestAttributes)inheritableRequestAttributesHolder.get();
    }

    return attributes;
}

他会返回一个T对象,就是我们RequestContextHolder的变量ThreadLocal,将RequestAttributes返回。使用ThreadLocal实现线程隔离。

public T get() {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    return setInitialValue();
}

具体的使用:

在代码中,我们并不会使用RequestAttributes,可以看看下面的RequestAttributes类,里面的方法太少了,我们没有使用框架之间都会使用servlet包下的HttpServletRequest。所以我们要将它转换成ServletRequestAttributes。它是Spring提供操作HttpServletRequest的类。

ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
public interface RequestAttributes {
    int SCOPE_REQUEST = 0;
    int SCOPE_SESSION = 1;
    String REFERENCE_REQUEST = "request";
    String REFERENCE_SESSION = "session";

    @Nullable
    Object getAttribute(String var1, int var2);

    void setAttribute(String var1, Object var2, int var3);

    void removeAttribute(String var1, int var2);

    String[] getAttributeNames(int var1);

    void registerDestructionCallback(String var1, Runnable var2, int var3);

    @Nullable
    Object resolveReference(String var1);

    String getSessionId();

    Object getSessionMutex();
}

我们来看一下ServletRequestAttributes,在ServletRequestAttributes类里面有一个HttpServletRequest request变量,看到这个变量我们应该熟悉怎么去操作它了。

public class ServletRequestAttributes extends AbstractRequestAttributes {
    public static final String DESTRUCTION_CALLBACK_NAME_PREFIX = ServletRequestAttributes.class.getName() + ".DESTRUCTION_CALLBACK.";
    protected static final Set<Class<?>> immutableValueTypes = new HashSet(16);
    private final HttpServletRequest request;
    @Nullable
    private HttpServletResponse response;
    @Nullable
    private volatile HttpSession session;
    private final Map<String, Object> sessionAttributesToUpdate;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dlage

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值