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的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@Componentpublic class Task {@Autowiredprivate ServletContext servletContext2;@Autowiredprivate 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的。
因未描述清楚项目环境,导致影响了大家解决问题的速度, 本人深表歉意 。
9月21日22:35:43