jfinal中使用ThreadLocal来绑定request和response
博客专区 > SPPan 的博客 > 博客详情
jfinal中使用ThreadLocal来绑定request和response
SPPan 发表于4个月前
jfinal中使用ThreadLocal来绑定request和response
  • 发表于 4个月前
  • 阅读 9
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云实验室 1小时搭建人工智能应用,让技术更容易入门 免费体验 >>>   

在一个web项目中,总会有情况遇到无法直接取到request或者response的时候。例如在jfinal中使用freemarker自定义指令,就无法拿到对应的request和response,于是threadLocal的作用很强大了,以下代码使用jfinal中使用freemarker自定义指令获取request为例。

1、新增一个LocalThreadMapHolder类,用于保存当前线程请求的request和response,定义如下:

package net.sppan.cms.common;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.jfinal.kit.Kv;
/**
 * request 和 response 获取钩子
 * @author SPPan
 *
 */
public class LocalThreadMapHolder {
	private static ThreadLocal<Kv> threadLocal = new ThreadLocal<>();
	public static final String REQUEST_KEY = "request_key";
	public static final String RESPONSE_KEY = "response_key";
	
	public static void setThreadLocal(Kv kv){
		threadLocal.set(kv);
	}
	
	public static Kv getThreadLocal(){
		return threadLocal.get();
	}
	
	/**
	 * 获取request
	 * @return
	 */
	public static HttpServletRequest getRequest(){
		return (HttpServletRequest) getThreadLocal().get(REQUEST_KEY);
	}
	/**
	 * 获取response
	 * @return
	 */
	public static HttpServletResponse getResopnse(){
		return (HttpServletResponse) getThreadLocal().get(RESPONSE_KEY);
	}
}

2、定义一个拦截器,用于在接受到有请求的时候将当前线程的request和response放入到threadLocal中。


package net.sppan.cms.interceptor;
import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.kit.Kv;
import net.sppan.cms.common.LocalThreadMapHolder;
/**
 * 请求线程钩子拦截器
 * 
 * @author SPPan
 *
 */
public class LocalThreadHolderInterceptor implements Interceptor{
	@Override
	public void intercept(Invocation inv) {
		Kv kv = Kv.by(LocalThreadMapHolder.REQUEST_KEY, inv.getController().getRequest()).set(LocalThreadMapHolder.RESPONSE_KEY, inv.getController().getResponse());
		LocalThreadMapHolder.setThreadLocal(kv);
		inv.invoke();
	}
}

3、使用拦截器进行拦截。

@Override
public void configInterceptor(Interceptors me) {
	me.addGlobalActionInterceptor(new LocalThreadHolderInterceptor());
}

4、在自定义指令中获取request和response。


//获取request
HttpServletRequest request = LocalThreadMapHolder.getRequest();
//获取response
HttpServletResponse resopnse = LocalThreadMapHolder.getResopnse();

以下是在网上收集的关于ThreadLocal相关的资料

一、概述

ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是threadlocalvariable(线程局部变量)。也许把它命名为ThreadLocalVar更加合适。线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是Java中一种较为特殊的线程绑定机制,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。

从线程的角度看,每个线程都保持一个对其线程局部变量副本的隐式引用,只要线程是活动的并且 ThreadLocal 实例是可访问的;在线程消失之后,其线程局部实例的所有副本都会被垃圾回收(除非存在对这些副本的其他引用)。

通过ThreadLocal存取的数据,总是与当前线程相关,也就是说,JVM 为每个运行的线程,绑定了私有的本地实例存取空间,从而为多线程环境常出现的并发访问问题提供了一种隔离机制。

ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单,在ThreadLocal类中有一个Map,用于存储每一个线程的变量的副本。

概括起来说,对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。

二、API说明

ThreadLocal()

创建一个线程本地变量。

T get()

返回此线程局部变量的当前线程副本中的值,如果这是线程第一次调用该方法,则创建并初始化此副本。

protected T initialValue()

返回此线程局部变量的当前线程的初始值。最多在每次访问线程来获得每个线程局部变量时调用此方法一次,即线程第一次使用 get() 方法访问变量的时候。如果线程先于 get 方法调用 set(T) 方法,则不会在线程中再调用 initialValue 方法。

若该实现只返回 null;如果程序员希望将线程局部变量初始化为 null 以外的某个值,则必须为 ThreadLocal 创建子类,并重写此方法。通常,将使用匿名内部类。initialValue 的典型实现将调用一个适当的构造方法,并返回新构造的对象。

void remove()

移除此线程局部变量的值。这可能有助于减少线程局部变量的存储需求。如果再次访问此线程局部变量,那么在默认情况下它将拥有其 initialValue。

void set(T value)

将此线程局部变量的当前线程副本中的值设置为指定值。许多应用程序不需要这项功能,它们只依赖于 initialValue() 方法来设置线程局部变量的值。

在程序中一般都重写initialValue方法,以给定一个特定的初始值。

标签: Java JFinal
共有 人打赏支持
粉丝 6
博文 30
码字总数 15436
×
SPPan
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: