关于在子线程中获取不到HttpServletRequest对象的问题

2024-05-26 07:28

本文主要是介绍关于在子线程中获取不到HttpServletRequest对象的问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这篇文章主要分享一下项目里遇到的获取request对象为null的问题,具体是在登录的时候触发的邮箱提醒,获取客户端ip地址,然后通过ip地址定位获取定位信息,从而提示账号在哪里登录。

但是登录却发现获取request对象的时候报错了。

 具体的代码如下:这个异常是自己手动抛出的。

package cn.edu.sgu.www.mhxysy.util;import cn.edu.sgu.www.mhxysy.consts.MimeType;
import cn.edu.sgu.www.mhxysy.exception.GlobalException;
import cn.edu.sgu.www.mhxysy.restful.JsonResult;
import cn.edu.sgu.www.mhxysy.restful.ResponseCode;
import com.alibaba.fastjson.JSON;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** http工具类* @author heyunlin* @version 1.0*/
public class HttpUtils {/*** 获取HttpServletRequest对象* @return HttpServletRequest*/public static HttpServletRequest getRequest() {RequestAttributes attributes = RequestContextHolder.getRequestAttributes();if (attributes != null ) {return ((ServletRequestAttributes) attributes).getRequest();}throw new GlobalException(ResponseCode.ERROR, "获取request对象失败");}}

在项目其他地方也有用这个工具了获取HttpServletRequest对象,都能获取到,觉得很是奇怪。点进去RequestContextHolder这个类的代码里看了一下,好像找到问题了~

这是基于ThreadLocal实现的,所以有了子线程无法访问父线程中设置的数据问题,不知道开发者为什么不用InheritThreadLocal来避免这个问题0v0

于是,把涉及获取request对象ip地址获取的代码放在线程外面,这样就避免了空指针问题了~

package cn.edu.sgu.www.mhxysy.chain.login.impl;import cn.edu.sgu.www.mhxysy.chain.login.UserLoginHandler;
import cn.edu.sgu.www.mhxysy.config.property.EmailProperties;
import cn.edu.sgu.www.mhxysy.config.property.SystemSettingsProperties;
import cn.edu.sgu.www.mhxysy.entity.location.Location;
import cn.edu.sgu.www.mhxysy.util.EmailUtils;
import cn.edu.sgu.www.mhxysy.util.IpUtils;
import cn.edu.sgu.www.mhxysy.util.LocationUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;/*** @author heyunlin* @version 1.0*/
@Component
public class EmailSendHandler implements UserLoginHandler {private Object params;private UserLoginHandler next;private final EmailUtils emailUtils;private final EmailProperties emailProperties;private final SystemSettingsProperties systemSettingsProperties;@Autowiredpublic EmailSendHandler(EmailUtils emailUtils,EmailProperties emailProperties,SystemSettingsProperties systemSettingsProperties) {this.emailUtils = emailUtils;this.emailProperties = emailProperties;this.systemSettingsProperties = systemSettingsProperties;}@Overridepublic void handle() {if (emailProperties.isEnable()) {String ip = IpUtils.getIp();String username = (String) params;String zoneId = systemSettingsProperties.getZoneId();// 定义日期格式DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");new Thread(() -> {try {String address = "广东广州";Location location = LocationUtils.getLocation(ip);if (systemSettingsProperties.isUseRealLocation()) {String locationAddress = location.getAddress();if (locationAddress != null) {address = locationAddress;}}String text = "您的账号" + username + "在" + address + "登录了。" +"[" + LocalDateTime.now(ZoneId.of(zoneId)).format(formatter) + "]";emailUtils.sendMessage(text);} catch (Exception e) {e.printStackTrace();}}).start();}if (next != null) {next.handle();}}@Overridepublic void setNext(UserLoginHandler next) {this.next = next;}@Overridepublic void setParams(Object params) {this.params = params;}}

总结:遇到这类问题,就把获取request对象的代码放在主线程中,避免因为ThreadLocal的缺陷导致程序异常。


好了,文章就分享到这里了,看完如果对你有所帮助,不要忘了点赞+收藏哦~

这篇关于关于在子线程中获取不到HttpServletRequest对象的问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/1003808

相关文章

Linux实现线程同步的多种方式汇总

《Linux实现线程同步的多种方式汇总》本文详细介绍了Linux下线程同步的多种方法,包括互斥锁、自旋锁、信号量以及它们的使用示例,通过这些同步机制,可以解决线程安全问题,防止资源竞争导致的错误,示例... 目录什么是线程同步?一、互斥锁(单人洗手间规则)适用场景:特点:二、条件变量(咖啡厅取餐系统)工作流

MySQL版本问题导致项目无法启动问题的解决方案

《MySQL版本问题导致项目无法启动问题的解决方案》本文记录了一次因MySQL版本不一致导致项目启动失败的经历,详细解析了连接错误的原因,并提供了两种解决方案:调整连接字符串禁用SSL或统一MySQL... 目录本地项目启动报错报错原因:解决方案第一个:第二种:容器启动mysql的坑两种修改时区的方法:本地

Java中常见队列举例详解(非线程安全)

《Java中常见队列举例详解(非线程安全)》队列用于模拟队列这种数据结构,队列通常是指先进先出的容器,:本文主要介绍Java中常见队列(非线程安全)的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一.队列定义 二.常见接口 三.常见实现类3.1 ArrayDeque3.1.1 实现原理3.1.2

springboot加载不到nacos配置中心的配置问题处理

《springboot加载不到nacos配置中心的配置问题处理》:本文主要介绍springboot加载不到nacos配置中心的配置问题处理,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录springboot加载不到nacos配置中心的配置两种可能Spring Boot 版本Nacos

SpringBoot3中使用虚拟线程的完整步骤

《SpringBoot3中使用虚拟线程的完整步骤》在SpringBoot3中使用Java21+的虚拟线程(VirtualThreads)可以显著提升I/O密集型应用的并发能力,这篇文章为大家介绍了详细... 目录1. 环境准备2. 配置虚拟线程方式一:全局启用虚拟线程(Tomcat/Jetty)方式二:异步

使用Python实现获取屏幕像素颜色值

《使用Python实现获取屏幕像素颜色值》这篇文章主要为大家详细介绍了如何使用Python实现获取屏幕像素颜色值,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 一、一个小工具,按住F10键,颜色值会跟着显示。完整代码import tkinter as tkimport pyau

Java中JSON格式反序列化为Map且保证存取顺序一致的问题

《Java中JSON格式反序列化为Map且保证存取顺序一致的问题》:本文主要介绍Java中JSON格式反序列化为Map且保证存取顺序一致的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未... 目录背景问题解决方法总结背景做项目涉及两个微服务之间传数据时,需要提供方将Map类型的数据序列化为co

python获取cmd环境变量值的实现代码

《python获取cmd环境变量值的实现代码》:本文主要介绍在Python中获取命令行(cmd)环境变量的值,可以使用标准库中的os模块,需要的朋友可以参考下... 前言全局说明在执行py过程中,总要使用到系统环境变量一、说明1.1 环境:Windows 11 家庭版 24H2 26100.4061

如何解决Druid线程池Cause:java.sql.SQLRecoverableException:IO错误:Socket read timed out的问题

《如何解决Druid线程池Cause:java.sql.SQLRecoverableException:IO错误:Socketreadtimedout的问题》:本文主要介绍解决Druid线程... 目录异常信息触发场景找到版本发布更新的说明从版本更新信息可以看到该默认逻辑已经去除总结异常信息触发场景复

Spring中管理bean对象的方式(专业级说明)

《Spring中管理bean对象的方式(专业级说明)》在Spring框架中,Bean的管理是核心功能,主要通过IoC(控制反转)容器实现,下面给大家介绍Spring中管理bean对象的方式,感兴趣的朋... 目录1.Bean的声明与注册1.1 基于XML配置1.2 基于注解(主流方式)1.3 基于Java