【已解决】请教 “Sa-Token 集成 xxl-job,报错:非 web 上下文无法获取 HttpServletRequest” 如何解决
1. xxl-job 报错日志
2024-09-11 17:19:04 [com.xxl.job.core.thread.JobThread#run]-[133]-[xxl-job, JobThread-3-1726046344528] <br>----------- xxl-job job execute start -----------<br>----------- Param:
2024-09-11 17:19:04 [com.xxl.job.core.thread.JobThread#run]-[204]-[xxl-job, JobThread-3-1726046344528] <br>----------- JobThread Exception:java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:118)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at com.xxl.job.core.handler.impl.MethodJobHandler.execute(MethodJobHandler.java:31)
at com.xxl.job.core.thread.JobThread.run(JobThread.java:166)
Caused by: org.mybatis.spring.MyBatisSystemException
at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:97)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:439)
at jdk.proxy2/jdk.proxy2.$Proxy90.insert(Unknown Source)
at org.mybatis.spring.SqlSessionTemplate.insert(SqlSessionTemplate.java:272)
at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:59)
at com.baomidou.mybatisplus.core.override.MybatisMapperProxy$PlainMethodInvoker.invoke(MybatisMapperProxy.java:149)
at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:90)
at jdk.proxy3/jdk.proxy3.$Proxy114.insert(Unknown Source)
at com.baomidou.mybatisplus.extension.service.IService.save(IService.java:60)
at com.dragon.springboot3vue3.service.impl.CategoryServiceImpl.saves(CategoryServiceImpl.java:27)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:351)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:713)
at com.dragon.springboot3vue3.service.impl.CategoryServiceImpl$$SpringCGLIB$$0.saves(<generated>)
at com.dragon.springboot3vue3.handler.XxlJobHandler.demoJobHandler(XxlJobHandler.java:22)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
... 3 more
Caused by: org.apache.ibatis.exceptions.PersistenceException:
### Error updating database. Cause: cn.dev33.satoken.exception.NotWebContextException: 非 web 上下文无法获取 HttpServletRequest
### The error may exist in com/dragon/springboot3vue3/mapper/CategoryMapper.java (best guess)
### The error may involve com.dragon.springboot3vue3.mapper.CategoryMapper.insert
### The error occurred while executing an update
### Cause: cn.dev33.satoken.exception.NotWebContextException: 非 web 上下文无法获取 HttpServletRequest
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:199)
at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:184)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:425)
... 18 more
Caused by: cn.dev33.satoken.exception.NotWebContextException: 非 web 上下文无法获取 HttpServletRequest
at cn.dev33.satoken.spring.SpringMVCUtil.getRequest(SpringMVCUtil.java:44)
at cn.dev33.satoken.spring.SaTokenContextForSpringInJakartaServlet.getStorage(SaTokenContextForSpringInJakartaServlet.java:56)
at cn.dev33.satoken.context.SaHolder.getStorage(SaHolder.java:69)
at cn.dev33.satoken.stp.StpLogic.isSwitch(StpLogic.java:2595)
at cn.dev33.satoken.stp.StpLogic.getLoginIdDefaultNull(StpLogic.java:1012)
at cn.dev33.satoken.stp.StpUtil.getLoginIdDefaultNull(StpUtil.java:360)
at com.dragon.springboot3vue3.handler.MybatisPlusHandler.insertFill(MybatisPlusHandler.java:27)
at com.baomidou.mybatisplus.core.MybatisParameterHandler.lambda$insertFill$0(MybatisParameterHandler.java:164)
at java.base/java.util.Optional.ifPresent(Optional.java:178)
at com.baomidou.mybatisplus.core.MybatisParameterHandler.insertFill(MybatisParameterHandler.java:162)
at com.baomidou.mybatisplus.core.MybatisParameterHandler.process(MybatisParameterHandler.java:115)
at java.base/java.util.Collections$SingletonSet.forEach(Collections.java:5125)
at com.baomidou.mybatisplus.core.MybatisParameterHandler.processParameter(MybatisParameterHandler.java:83)
at com.baomidou.mybatisplus.core.MybatisParameterHandler.<init>(MybatisParameterHandler.java:72)
at com.baomidou.mybatisplus.core.MybatisXMLLanguageDriver.createParameterHandler(MybatisXMLLanguageDriver.java:46)
at org.apache.ibatis.session.Configuration.newParameterHandler(Configuration.java:705)
at org.apache.ibatis.executor.statement.BaseStatementHandler.<init>(BaseStatementHandler.java:70)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.<init>(PreparedStatementHandler.java:42)
at org.apache.ibatis.executor.statement.RoutingStatementHandler.<init>(RoutingStatementHandler.java:47)
at org.apache.ibatis.session.Configuration.newStatementHandler(Configuration.java:719)
at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:48)
at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.apache.ibatis.plugin.Invocation.proceed(Invocation.java:61)
at com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor.intercept(MybatisPlusInterceptor.java:106)
at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:59)
at jdk.proxy2/jdk.proxy2.$Proxy146.update(Unknown Source)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61)
at jdk.proxy2/jdk.proxy2.$Proxy146.update(Unknown Source)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:197)
... 22 more
<br>----------- xxl-job job execute end(error) -----------
2024-09-11 17:19:04 [com.xxl.job.core.thread.TriggerCallbackThread#callbackLog]-[197]-[xxl-job, executor TriggerCallbackThread] <br>----------- xxl-job job callback finish.
[Load Log Finish]
2.解决方案
2.1 分析报错原因:
xxl-job 执行业务方法新增, mp 自动填充创建者ID 使用了 StpUtil.getLoginIdDefaultNull(),此时是非 web 上下文,所以报错 非 web 上下文无法获取 HttpServletRequest
2.2 解决方案--只需修改 mp 自动填充 creatorId 代码
/**
* MybatisPlus 自动填充策略处理器
*/
@Component
public class MybatisPlusHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
// 获取 createTime 属性,如果 createTime 为空,则设置为当前时间
Object createTime = getFieldValByName("createTime", metaObject);
if (createTime == null) {
this.setFieldValByName("createTime", LocalDateTime.now(), metaObject);
}
this.setFieldValByName("ts", LocalDateTime.now(), metaObject);
try {
Object loginId = StpUtil.getLoginIdDefaultNull();
this.setFieldValByName("creatorId", loginId, metaObject);
} catch (Exception e){
// creatorId 为 0 表示是定时任务添加数据
this.setFieldValByName("creatorId", "0", metaObject);
}
}
@Override
public void updateFill(MetaObject metaObject) {
// 属性名
this.setFieldValByName("ts", LocalDateTime.now(), metaObject);
}
}