写点什么

Web 开发小妙招:巧用 ThreadLocal 规避层层传值

  • 2022 年 7 月 06 日
  • 本文字数:1331 字

    阅读完需:约 4 分钟

本文分享自华为云社区《拦截器中巧用ThreadLocal规避层层传值》,作者:KevinQ。

Web 开发中的一点麻烦事


最近,准确地说,是一直都有的一点麻烦事:函数层层传递。什么意思呢?比如说有个很常见的需求描述是:记录用户的某次操作明细。


以在 Java 的开源框架 jfinal 中,操作添加一个用户的接口为例,有:



public class XXController() {
public void addUser() {
// 获取操作人
Integer opUserId = Integer.parseInt(getHeader("opUserId"));
// 获取其他参数...


service.addUser(...., opUserId);
renderAppMsg("添加用户成功");
}
}
复制代码


为了记录用户添加的具体操作内容以及信息错误,这个记录用户操作的记录可能需要穿透好层方法。



public class XXService() {
public void addUser(String tel, String name, String password, Integer opUserId) {
checkTel(tel, opUserId);


checkName(name, opUserId);


checkPassword(password, opUserId);
}


public void checkTel(String tel, Integer opUserId) {
check(tel, opUserId);
}


publc void check(..., Integer opUserId) {
// ...
}
}
复制代码


举得这个例子或许不是很恰当,但是相信大家可以理解这个麻烦点在哪里。


函数调用链中的每个方法并不是需要这个参数,而可能仅仅是为了向下个被调用的函数传递这个参数。


那么是否有方法帮助我们来不需要这样逐层传递,从而获取接口请求参数的方法呢。

思考


这有点类似与一个全局变量,但是这个变量对每次请求来说是变化的,那么是否有一种方式能够让我们来保存这样一种:针对每次请求的全局变量呢?


在最近学习 Shiro 的过程中,以及学习若依开源框架的过程中,我们发现其均使用到了一个强大的 Java 类:ThreadLocal。


shiro 使用 ThreadLocal 是用来保存当前登录对象,若依框架中,其中所使用的分页插件 PageUtil 使用 ThreadLocal 保存请求参数中的 pageNum 与 pageSize 等分页参数。因此我们是不是也可以使用 ThreadLocal 来达到同样的目的。

在拦截器中使用 ThreadLocal 暂存请求参数


为此,我们来尝试一下,通过 ThreadLocal 保存请求参数,通过拦截器我们可以拦截每次请求,如下是实现方式:



package com.holdoa.core.interceptor;
import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import javax.servlet.http.HttpServletRequest;
public class RequestPool implements Interceptor {
public static ThreadLocal<HttpServletRequest> localRequest= new ThreadLocal<>();
@Override
public void intercept(Invocation inv) {
localRequest.set(inv.getController().getRequest());
inv.invoke();
localRequest.remove();
}
public static HttpServletRequest getRequest() {
return localRequest.get();
}
}
复制代码


我们通过 ThreadLocal 将整个请求暂存起来,当然,为了节约内存,也可以只保存使用频次高的通用参数,比如当前登录人的信息等等。

使用参数


使用时,只需要我们通过这个线程局部变量取值即可:



String para = RequestPool.localRequest.get().getParameter("username");
复制代码


如此,我们便可以在处理每次请求的过程中,无需从 Controller 以及 Service 中的方法层层传值,只需要直接通过该局部变量取值即可。


点击关注,第一时间了解华为云新鲜技术~

发布于: 刚刚阅读数: 4
用户头像

提供全面深入的云计算技术干货 2020.07.14 加入

华为云开发者社区,提供全面深入的云计算前景分析、丰富的技术干货、程序样例,分享华为云前沿资讯动态,方便开发者快速成长与发展,欢迎提问、互动,多方位了解云计算! 传送门:https://bbs.huaweicloud.com/

评论

发布
暂无评论
Web开发小妙招:巧用ThreadLocal规避层层传值_Java_华为云开发者联盟_InfoQ写作社区