背景介绍:某工厂设备管理项目中一个定时任务用于生成设备维护工单,在点击下方立即执行按钮时,会抛出下图所示的异常信息或者出现“No SecurityManager accessible to the calling code”

java.util.concurrent.ExecutionException: com.sugon.utils.RRException: 执行定时任务失败at java.util.concurrent.FutureTask.report(FutureTask.java:122)at java.util.concurrent.FutureTask.get(FutureTask.java:192)at com.sugon.utils.ScheduleJob.executeInternal(ScheduleJob.java:55)at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:75)at org.quartz.core.JobRunShell.run(JobRunShell.java:202)at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
Caused by: com.sugon.utils.RRException: 执行定时任务失败at com.sugon.utils.ScheduleRunnable.run(ScheduleRunnable.java:40)at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)at java.util.concurrent.FutureTask.run(FutureTask.java:266)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.reflect.InvocationTargetExceptionat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:498)at com.sugon.utils.ScheduleRunnable.run(ScheduleRunnable.java:37)... 5 more
Caused by: org.apache.shiro.UnavailableSecurityManagerException: No SecurityManager accessible to the calling code, either bound to the org.apache.shiro.util.ThreadContext or as a vm static singleton.  This is an invalid application configuration.

分析:简单来说定时任务执行时会开辟一个新的线程用来执行当前JOB,新线程在执行JOB逻辑时触发了UnavailableSecurityManagerException,请注意异常提示信息:“No SecurityManager accessible to the calling code, either bound to the org.apache.shiro.util.ThreadContext or as a vm static singleton.  This is an invalid application configuration.”,简而言之就是在当前线程中找不到shiro框架必要的SecurityManager对象,要解决这个问题要么绑定SecurityManager对象到ThreadContext中,要么将SecurityManager声明为VM静态单例。由于在spring框架中,所以采用将SecurityManager对象绑定到每个线程的ThreadContext对象(shiro提供的用来绑定/解绑对象到当前线程的方式或手段)中。

解决思路:简单来说可以在每个JOB逻辑执行前判断下当前线程是否已有SecurityManager实例,如果没有则从Spring容器中获取SecurityManager并绑定到当前ThreadContext中。大致代码如下:

SecurityManager securityManager = ThreadContext.getSecurityManager();
if (securityManager == null) {securityManager = SpringContextUtils.getBean("securityManager", DefaultWebSecurityManager.class);ThreadContext.bind(securityManager);
}

考虑到如果项目中有多个JOB的话,重复代码大量出现在多个地方。本着高可用的原则,采用注解+切面的方式,对每个JOB执行前都增加上述逻辑,实现代码如下,每个代码已简化结构和去除注释:

1、声明校验性注解

public @interface ShiroSecurityManagerChecker {
}

2、编写逻辑处理AOP,对每个采用@ShiroSecurityManagerChecker注解的逻辑执行前都执行确保每个线程存在SecurityManager的逻辑

@Aspect
@Component
public class ShiroSecurityManagerCheckerAspect {@Pointcut("@annotation(com.sugon.annotation.ShiroSecurityManagerChecker)")public void dataFilterCut() {}@Before("dataFilterCut()")public void dataFilter(JoinPoint point) {SecurityManager securityManager = ThreadContext.getSecurityManager();if (securityManager == null) {securityManager = SpringContextUtils.getBean("securityManager", DefaultWebSecurityManager.class);ThreadContext.bind(securityManager);}}}

3、在需要的地方添加注解,demo如下,按需添加:

@ShiroSecurityManagerChecker
public void process() {}

总结:由于shiro中大部分功能都依赖于SecurityManager对象,所以在多线程环境下一定要多注意SecurityManager是否存在。当然如果多线程执行逻辑中不涉及Shiro相关内容,则无视!一般来说只要是出现UnavailableSecurityManagerException异常或者提示找不到SecurityManager对象(No SecurityManager accessible to the calling code)等,都可以从此切入点考虑下。

以上,完了!!

记一次“Shiro+任务调度”开发过程中出现UnavailableSecurityManagerException解决思路相关推荐

  1. 无法安装Hyper-V:虚拟机监控程序已在运行中的详细解决思路

    如题,很多盆友在VMware的Windows Server 2012中安装Hyper-V时遇到这样的报错: Hyper-V是微软的一款虚拟化产品,与VMware有着类似的功能,如果你的Windows ...

  2. maven打包报错找不到符号,由于找不到类中方法的解决思路

    maven打包报错找不到符号,若pom文件引用正常,报错的类有修改能正常启动执行程序,很有可能因为该类属于公共工具类,在外层目录,通过pom引用的,修改后工具类后,打包时没有将其重新打包,导致该出引用 ...

  3. 嵌入式系统开发过程中遇到的——volatile

    嵌入式 系统开发过程中遇到的-- volatile 对于不同的计算机体系结构,设备可能是端口映射,也可能是内存映射的 .如果系统结构支持独立的 I/O 地址空间,并且是端口映射,就必须使用汇编语言完成 ...

  4. 项目开发过程中的收获与思考

    2013年7月,我正式毕业了,到公司入职,也就正式成为了一名菜鸟程序员.到今天,2014年1月3日,目前主要的工作是公司一个项目中的一个功能模块,到我进入项目组算起,已经过了四个月了.因此,想写点东西 ...

  5. 潘正磊谈微软研发团队管理和Visual Studio开发过程中的敏捷实践

    潘正磊谈微软研发团队管理之道 http://www.infoq.com/cn/interviews/team-management-panzhenglei 先给我们介绍一下你自己和你自己现在所做的事情 ...

  6. 对日软件开发过程中的质量管理

    对日软件开发过程中的质量管理 2004-04-01 ----记系统开发事业本部大连开发部质量管理活动系列之一 NECSI系统开发事业本部主要承接日本客户委托开发的软件项目,承担从功能设计(FD).详细 ...

  7. 开发过程中的自言自语

    最近一段时间,喜欢边开发,边整理开发资料,把开发过程中和一步一步学的新的玩意儿遇到的问题整理下来.然后一步一步自我解答. 我觉得带着思考学东西还是感觉不错,至少证明自己真的在学,而不是为了学而学. 思 ...

  8. Asp.net开发过程中,我们会遇到很多Exception

    在Asp.net开发过程中,我们会遇到很多Exception,不处理这些Exception的话会出现很难看的页面. 还有一些我们未预料到的Exception,当发生Exception时,我们也必须进行 ...

  9. 小视频开发过程中最关注的两点关键

    小视频凭借它独有的特征在互联网领域获得了属于自己的一席之地,斩获搞笑.游戏.美食等行业后,在教育.财经等方面还拥有更加可观的发展前景.那么,在小视频开发过程中应该怎样结合它的能力实现业务上的突破呢? ...

最新文章

  1. 最全的 Spring 依赖注入方式,你都会了吗?
  2. 英伟达开源行人生成/重识别代码
  3. ArcGIS JS API 4.X实现动态地图服务子图层显隐控制
  4. 2021互联网大厂中秋礼盒哪家强?!
  5. boost::signals2模块thread_safe_signals 库替代线程模型的基本测试
  6. 如何设置鼠标滚轮html,win7如何设置鼠标滚轮
  7. DistBelief 框架下的并行随机梯度下降法 - Downpour SGD
  8. 考研计算机考试408背诵,今年上岸计算机准研究生分享一下计算机考研(408)经验...
  9. 兼容多浏览器的CSS背景透明
  10. mysql心得笔记_mysql总结笔记
  11. Makefile 管理工具 — Automake and Autoconf
  12. html网页中获取vf数据到mysql_vfp教程之用FoxWeb在网上快速发布你的FOXPRO数据库
  13. Quartz 定时任务 cron 表达式详解
  14. 微信服务号获取地理位置
  15. QQ空间无法点赞或者QQ空间点赞被取消
  16. android朋友圈发文字换行,朋友圈发文字怎么才显示全文 多按几次换行(大概10次左右...
  17. 世界杯海信再出圈,三星:“谈不上愉悦”
  18. C/C++中的pi(pai)怎么打 【c语言】
  19. 零基础入门WordPress安装详细教程(图文)
  20. CSS最后一行:控制寡妇和孤儿

热门文章

  1. 操作系统学习---虚拟内存
  2. application/x-www-form-urlencoded 的contentType,POST数据内容过大,导致tomcat的request取不到参数...
  3. SSIS hang with unhandle exception
  4. PotPlayer 64 bit快捷键大全
  5. VSCode+PHPstudy配置PHP开发环境
  6. 【vue】路由Router基础详解,带你快速入门~
  7. Logistic混沌序列加密
  8. TS Interface(接口)
  9. 计算机通识/14:算法常识/算法常识-01
  10. 7-5 统计大写辅音字母 (15 分)