文档章节

jfinal中使用ThreadLocal来绑定request和response

SPPan
 SPPan
发布于 2017/06/05 14:54
字数 1172
阅读 118
收藏 0

在一个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方法,以给定一个特定的初始值。

© 著作权归作者所有

共有 人打赏支持
SPPan
粉丝 10
博文 29
码字总数 15103
作品 0
成都
程序员
私信 提问
对jfinal和php的一些思考。

jfinal是个java框架,php是门脚本语言,两者本是不相关的。但是社区里jfinal和php的讨论比较多,也就把这两者联系起来了。本人java用了五年,php用了近一年,对比着学习两门语言也有了一些感...

高山流水情
2016/06/14
3.5K
31
JFinal Extensions 2.0 发布,JFinal 扩展

Jfinal-Ext转眼间已经发布半年了。我对jfinal-ext的定位是 一个对jfinal周边设施进行完善的项目,如整合常用的第三方库。目前大部分是我个人的经验总结通过jfinal进行扩展作为技术积累,只有...

绝望的八皮
2013/04/15
4.1K
16
JFinal Extensions 1.0 发布,JFinal 扩展

Jfinal-ext是对java极速web框架 jfinal 的一个扩充,主要利用jfinal的plugin机制集成各种第三方框架,像spring一样,简化开发者的学习应用成本,使用时请将jfinal.jar先引入工程。 Jfinal-e...

绝望的八皮
2012/10/14
1K
13
【开源访谈】 JFinal作者 詹波 访谈实录

关于开源访谈 开源访谈是开源中国推出的一系列针对国内优秀开源软件作者的访谈,以文字的方式记录并传播。我们希望开源访谈能全面的展现国内开源软件、开源软件作者的现状,着实推动国内开源...

丫头潘潘
2013/07/11
11.1K
68
jfinal如何支持大数据量的查询?或都说有没方法支持jdbc fetch?

jfinal如何支持大数据量的查询?或都说有没方法支持jdbc fetch? 半新手,今天写了个跑批的,需要从一个数据库中查询出大量的数据(约60W),Db.find是一口气查询到客户端机器的内存中,导致O...

灵溪小鱼
2015/11/05
974
8

没有更多内容

加载失败,请刷新页面

加载更多

基于vue2定义自己的图表echart组件

先安装echarts cnpm i echarts -S,然后定义父组件 <template> <div> <echarts :option="echartOpion"></echarts> </div></template><script> import echarts from './e......

莫沫达
9分钟前
0
0
详解CSS的Flex布局

本文由云+社区发表 Flex是Flexible Box 的缩写,意为"弹性布局",是CSS3的一种布局模式。通过Flex布局,可以很优雅地解决很多CSS布局的问题。下面会分别介绍容器的6个属性和项目的6个属性。每...

腾讯云加社区
21分钟前
0
0
一些感想

人生的意义是什么 不知不觉已人到中年,其实上学的时候经常会思考这些问题————大概是因为闲,大学毕业参加工作经历的事情越来越多,反而不会去想这些缥缈的事情了,也许是因为最近看了一...

looqy
21分钟前
0
0
迭代器模式 Iterator 行为型 设计模式(二十)

  在计算机中,Iterator意为迭代器,迭代有重复的含义,在程序中,更有“遍历”的含义      如果给定一个数组,我们可以通过for循环来遍历这个数组,这种遍历就叫做迭代      对于...

SEOwhywhy
29分钟前
2
0
【 58沈剑 架构师之路】InnoDB,5项最佳实践,知其所以然

缓存讲了一个月《缓存架构,一篇足够》。今天,开始写数据库。 第一篇,说说MySQL两个最常用的存储引擎,MyISAM和InnoDB。照自己的理解,把一些知识点总结出来,不只说知识点,多讲“为什么”...

张锦飞
32分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部