- 简介
在微服务开发中,常常需要将一些公共字段填充至请求的实体中,如当前登录用户信息、请求时间戳等。使用ThreadLocal
可以实现这些公共字段的自动填充,避免在每个业务方法中重复填充,提高代码的复用性。
本文将介绍使用SpringBoot
框架中ThreadLocal
实现公共字段自动填充,并提供两个示例以说明具体实现方式。
- 实现步骤
2.1 创建ThreadLocal类
首先,我们需要创建一个类,用于存储需要填充的公共字段,可以命名为ThreadLocalHolder
。
public class ThreadLocalHolder {
private static final ThreadLocal<User> userThreadLocal = new ThreadLocal<>();
public static void setUser(User user) {
userThreadLocal.set(user);
}
public static User getUser() {
return userThreadLocal.get();
}
public static void clear() {
userThreadLocal.remove();
}
}
在上述代码中,我们定义一个ThreadLocal
对象,用于存储用户信息,其中setUser
方法用于设置用户信息,getUser
方法用于获取用户信息,clear
方法用于清空ThreadLocal
中的值。
2.2 创建拦截器
接下来,创建一个拦截器,在请求进入控制层之前,将ThreadLocal
中的信息填充到请求的参数中。
@Component
public class ThreadLocalInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 假设Header中包含了用户ID,可以使用这个ID获取用户信息
String userId = request.getHeader("userId");
User user = userService.getUserById(userId);
ThreadLocalHolder.setUser(user);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
ThreadLocalHolder.clear();
}
}
在上述代码中,我们在preHandle
方法中获取用户信息,并将其设置到ThreadLocal
中,然后在postHandle
方法中清空ThreadLocal
中的值,以免因为线程重用导致数据污染。
2.3 使用注解进行字段填充
最后,我们需要为需要自动填充字段的请求实体加上注解,以标识哪些字段需要自动填充。
@Data
public class Order {
@AutoFillField(fillMethod = "fillAuditing")
private String auditor;
private String content;
private Date createTime;
public void fillAuditing() {
this.auditor = ThreadLocalHolder.getUser().getName();
}
}
在上述代码中,我们定义了一个Order
实体类,其中auditor
字段标识为需要自动生成,content
和createTime
字段不需要自动生成。我们使用了AutoFillField
注解,并指定了填充方法为fillAuditing
,在该方法中,我们从ThreadLocalHolder
中获取当前用户信息,并将其填充到auditor
字段中。
- 示例说明
下面提供两个示例,以说明具体实现方式。
3.1 示例1:获取请求头中用户ID,并填充到字段中
-
在
ThreadLocalHolder
类中,定义了一个ThreadLocal
对象,用于存储用户信息。 -
创建拦截器,在请求进入控制层之前,从请求的
Header
中获取用户ID,并通过该ID获取用户信息,并设置到ThreadLocalHolder
中。 -
在需要自动填充的字段上,加上
AutoFillField
注解,并指定填充方法为从ThreadLocalHolder
中获取当前用户信息。
@Data
public class Order {
@AutoFillField(fillMethod = "fillAuditing")
private String auditor;
private String content;
private Date createTime;
public void fillAuditing() {
this.auditor = ThreadLocalHolder.getUser().getName();
}
}
3.2 示例2:获取请求参数,并填充到字段中
-
创建拦截器,在请求进入控制层之前,获取请求参数中的某个字段,并设置到
ThreadLocalHolder
中。 -
在需要自动填充的字段上,加上
AutoFillField
注解,并指定填充方法为从ThreadLocalHolder
中获取当前请求参数中的值。
@Data
public class Order {
@AutoFillField(fillMethod = "fillContent")
private String content;
private Date createTime;
public void fillContent() {
this.content = ThreadLocalHolder.getRequest().getParameter("content");
}
}
- 总结
本文简单介绍了使用SpringBoot
框架中ThreadLocal
实现公共字段自动填充,并提供了两个示例。
需要注意的是,使用ThreadLocal
时必须要注意内存泄漏的问题,因为ThreadLocal
的值不会随着线程池的回收而回收。在拦截器中一定要使用ThreadLocalHolder.clear()
清理缓存,避免因线程池复用引发的数据污染问题。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringBoot ThreadLocal实现公共字段自动填充案例讲解 - Python技术站