詹学伟
詹学伟
Published on 2024-04-26 / 28 Visits
0
0

java.lang.IllegalStateException: No thread-bound request found

记录工作中的一个踩坑点

背景:

项目使用ssm,mybatis+mybatis plus,定时任务用的spring的@Scheduled注解,

现状:

同事在定时任务中注入业务service对数据库写操作,程序报错

错误信息:

### Error updating 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 com/mpi/imes/dao/sys/SysLogDao.java (best guess)
### The error may involve com.mpi.imes.dao.sys.SysLogDao.insert!selectKey
### The error occurred while handling results
### SQL: SELECT SEQ_SYS_LOG.NEXTVAL FROM DUAL
### 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.
 at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:77)
 at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446)
 at com.sun.proxy.$Proxy21.insert(Unknown Source)
 at org.mybatis.spring.SqlSessionTemplate.insert(SqlSessionTemplate.java:278)
 at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:58)
 at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59)
 at com.sun.proxy.$Proxy530.insert(Unknown Source)
 at com.baomidou.mybatisplus.service.impl.ServiceImpl.insert(ServiceImpl.java:98)
 at com.mpi.imes.service.sys.SysLogServiceImpl.saveLog(SysLogServiceImpl.java:37)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(Nat

原因:

因为整合了mybatis-plus,mybatis-plus有一个自动填充数据的拦截器,比如新增数据自动填充时间、创建人,修改的时候自动填充修改时间,再看该拦截器:

这里因为是定时任务调用(非web请求调用),会导致这里的request.getSession出错,错误就是上面截图,具体原因可以看源码。

临时解决方案,针对IllegalStateException一场特殊处理

public class BaseMetaObjectHandler extends MetaObjectHandler {

	@Autowired
	private HttpServletRequest request;

	@Override
	public void insertFill(MetaObject metaObject) {
		try {
			AdminContext adminContext = (AdminContext) request.getSession()
					.getAttribute(AdminContext.SESSION_CONTEXT_NAME);
			if (adminContext != null) {
				setFieldValByName("creatorId", adminContext.getAdminId(), metaObject);
				setFieldValByName("creator", adminContext.getName(), metaObject);
				setFieldValByName("createTime", System.currentTimeMillis(), metaObject);
			} else {
				setFieldValByName("creatorId", 0L, metaObject);
				setFieldValByName("createTime", System.currentTimeMillis(), metaObject);
			}
		} catch (Exception e) {
			if (e instanceof IllegalStateException) {
				return;
			}
			throw new RuntimeException(e.getMessage());
		}
	}

	@Override
	public void updateFill(MetaObject metaObject) {
		try {
			AdminContext adminContext = (AdminContext) request.getSession()
					.getAttribute(AdminContext.SESSION_CONTEXT_NAME);
			if (adminContext != null) {
				setFieldValByName("updaterId", adminContext.getAdminId(), metaObject);
				setFieldValByName("updater", adminContext.getName(), metaObject);
				setFieldValByName("updateTime", System.currentTimeMillis(), metaObject);
			} else {
				setFieldValByName("updaterId", 0L, metaObject);
				setFieldValByName("updateTime", System.currentTimeMillis(), metaObject);
			}
		} catch (Exception e) {
			if (e instanceof IllegalStateException) {
				return;
			}
			throw new RuntimeException(e.getMessage());
		}
	}

}

感悟

很多时候,我们遇到问题,就一股脑的去网络搜索,大概率也会搜到类似的问题,甚至相同的问题。但是我觉得除了解决问题外,我们更应该思考问题、分析问题,解决问题的同时,锻炼自己独立思考分析能力

针对上面这个问题,后来我就感觉自己是被网络信息给误导,导致我刚开始没有独立去思考问题、去分析问题,一味地想在网络中寻找到一样的问题,然后解决掉。其实中途很多次我有想过上面的原因,但是都被网络信息淹没。

处理问题,首先靠自己独立思考,先找到原因,再解决问题,举一反三,处理其他问题。一味靠网络来得到答案,往往只能知其然,但不知其所以然,我们要做的,就是锻炼自己的思考和分析能力,并知其然知其所以然。


Comment