Mybatis-Plus租户id结合定时任务 @Scheduled 注解使用踩的坑
因为业务需求需要加定时任务,所以图方便直接使用了@Scheduled 注解加Cron表达式进行每30分钟跑一次定时任务,但是运行的时候突然发现报了个No thread-bound request found: Are you referring to request attributes outside of an actual web request
也就是定时任务拿不到request请求
详细日志
2022/12/02-15:22:00 ERROR [pool-1-thread-1] org.springframework.scheduling.support.TaskUtils$LoggingErrorHandler - Unexpected error occurred in scheduled task.
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: java.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.
### The error may exist in file [F:\workspace\project\target\classes\mapper_xml\xxxxMapper.xml]
### The error may involve com.jsh.erp.datasource.mappers.ApplicantMapper.selectApplicantInterviewTime
### The error occurred while executing a query
### Cause: java.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.
解决方案
一、技术有问题,@Scheduled 注解定时任务不可能拿到HttpServletRequest请求, 直接改变技术架构
二、配置mybatis-plus Config类,过滤表,将定时任务需走数据库的表通通过滤,不使用租户id
@Bean
public PaginationInterceptor paginationInterceptor(HttpServletRequest request) {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
List<ISqlParser> sqlParserList = new ArrayList<>();
TenantSqlParser tenantSqlParser = new TenantSqlParser();
tenantSqlParser.setTenantHandler(new TenantHandler() {
@Override
public Expression getTenantId() {
String token = request.getHeader("X-Access-Token");
Long tenantId = Tools.getTenantIdByToken(token);
if (tenantId != 0L) {
return new LongValue(tenantId);
} else {
//超管
return null;
}
}
@Override
public String getTenantIdColumn() {
return "tenant_id";
}
@Override
public boolean doTableFilter(String tableName) {
if ("t_xxxx".equals(tableName)) {//你要过滤的表名
return true;
}
});
}