java定时器任务中获取request对象 @Scheduled 获取request 对象 quartz中获取request对象
一、问题描述
1、在java定时任务中,使用 @Scheduled 注解来实现;遇到一个需要通过 request 对象获取相对路径的问题,尝试过过 静态获取 和 使用 直接注入HttpServletRequest对象 的办法,都没有解决问题,会导致抛出异常如下:
ERROR [org.springframework.scheduling.support.TaskUtils$LoggingErrorHandler]
- Unexpected error occurred in scheduled task.
2、使用 @Autowired 注入 HttpServletRequest ,会抛出如下异常:
ava.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131)
at org.springframework.web.context.support.WebApplicationContextUtils.currentRequestAttributes(WebApplicationContextUtils.java:273)
二、问题解决
1、通过 ContextLoader 获取 getCurrentWebApplicationContext 方法解决。
(SSM 架构的,非 Spring Boot的 2022年9月21日22:36:03)
WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
ServletContext servletContext = webApplicationContext.getServletContext();
String realPath = servletContext.getRealPath(File.separator);
( org.springframework.web.context.ContextLoader )
三、补充说明
1、评论中,大家反馈的 空指针 情况, 获取到 WebApplicationContext 对象为空情况,经过测试,是在Spring Boot项目中,会出现这种情况,经常测试,简单解决办法是,直接 注入ServletContext 对象即可。
@Slf4j
@Component
public class Task {
@Autowired
private ServletContext servletContext2;
@Autowired
private HttpServletRequest request;
@Scheduled(cron = "0/10 * * * * ? ")
public void task(){
Thread th = Thread.currentThread();
log.warn("start==={}",th.getName());
/**
* spring boot 项目下: WebApplicationContext 为空。
* 需要手动注入:servletContext2 即可
*/
// WebApplicationContext web = ContextLoader.getCurrentWebApplicationContext();
// ServletContext servletContext = web.getServletContext();
String realPath = servletContext2.getRealPath(File.separator);
log.warn("end === realPath {}",realPath);
}
}
2、原项目环境是:SSM 架构的,非 Spring Boot的, 使用的 Spring 版本为 4.3 。
3、本文表述有一点误解, 定时任务中,无法获取到 request 对象的, 是可以获取到 servlet的上下文对象ServletContext 的。
因未描述清楚项目环境,导致影响了大家解决问题的速度, 本人深表歉意 。
2022年9月21日22:35:43