当前位置: 首页 > news >正文

wordpress app 插件谷歌seo工具

wordpress app 插件,谷歌seo工具,创业做app哪个网站好,少女前线b站服结论 SecurityUtils.getSubject().getPrincipal()实际用的也是ThreadLocal,而ThreadLocal和线程绑定,异步会导致存数据丢失,注意! 业务背景 最近,系统偶尔会出现excel导入成功,但系统却提示存在进行中的…

结论

SecurityUtils.getSubject().getPrincipal()实际用的也是ThreadLocal,而ThreadLocal和线程绑定,异步会导致存数据丢失,注意!

业务背景

最近,系统偶尔会出现excel导入成功,但系统却提示存在进行中的导入的问题(并且等待了较长的时间还是不行)。这边跟进排查一下。

实现现状

导入的时候,会对参数进行校验,其中就有数据重复校验。
看了一下,前辈是用redis的set来进行的去重校验操作。用LoginUser获取用户id,固定前置+用户id拼接作为redis的key,需要去重的字段拼接成map作为值。主业务方法结束的时候用传入的LoginUser的用户id去拼接key来删除key(因为校验方法是框架带的,所以无法传参将LoginUser传进去)。
判断是否存在正在进行的导入是直接拼接key来查redis,key存在则说明有正在进行中的导入。

 private boolean hashCacheExcelVerifyDataGroupVerify(SdSchoolQuestionBankTestPaperVerify verify, String prefix) {LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();boolean groupVerifySuccess = true;if (verify == null) {return groupVerifySuccess;}try {//校验成功,成功返回true、失败返回falseString userId = loginUser.getId();String key = prefix + userId;Map<String, Object> map = new HashMap<>();map.put("xxxNo", verify.getTestPaperName().trim() + verify.getXxxNo().trim());//有效期设置为30分钟long expireTime = 30 * 60;SetOperations setOperations = redisTemplate.opsForSet();setOperations.getOperations().expire(key, expireTime, TimeUnit.SECONDS);Set members = setOperations.members(key);if (!members.contains(map)) {//如果不存在,将数据缓存到redis中,并设置有效期为30分钟,当执行完导入操作之后删除缓存setOperations.add(key, map);} else {groupVerifySuccess = false;}} catch (Exception e) {log.error("去重校验失败", e);}return groupVerifySuccess;}

上面的方案总体来说是可以实现的,只不过具体实现的时候出现了一些小毛病。
一眼看过去,先设置过期时间,再设置值,这不是虚空设过期时间(如果导入一条数据,直接永不过期)。不过一般导入的数量也不是一条,按理说过半个小时应该能用才对。不过还是改了再说,把设置过期时间的代码放到setOperations.add(key, map)下面。
接着查,发现执行完业务代码之后,只有成功才会删除key,原来问题出在这。于是给异常后面加上一个finally,在finally里面删除key,这下,无论你啥时候过期,删除了就屁事没有。
测试环境验证一下。非常好,没问题,提测,问题解决,简简单单。

一波又起

到第二天,业务反馈,又出现一直处于导入中的情况。并且该账号半个小时以内并没有用过该excel导入。

奇怪了,仔细又查了一遍代码,不应该呀,在finally里面有删除。无论如何肯定会执行删除操作呀。然后去看被限制人的导入,半个小时内并没有导入。
上redis一看,还真有缓存,卧槽,见鬼了。再去看半个小时内是否有导入,还真有,再细看过期时间和导入时间,居然还对的上。
emm,有情况。突然想到LoginUser的获取和ThreadLocal有点像,会不会是异步导致的问题。于是本地启动去测,用工具跑了很多次(只用了一个账号)。异步前后获取到的用户都是同一个,于是认为LoginUser比ThreadLocal牛逼,在异步的时候还会去提前更改盒子里的内容。(其实是因为只有一个用户,用来用去都只有一个用户,各个线程里面存的都是该用户,当然获取到的是一致的)

灵光一闪

到第二天,突然想到,A导入,却导致B被限制。那应该要多用户去测才对。于是更改测试方式,结果获取到的结果显示,异步前后获取到的LoginUser不一致。卧槽!!!难崩,原来是这个原因,原来我猜想是对的。
因为新实现的导入都是直接用一个key作为判断是否存在正常导入的依据,并且异步之后删除key用的也是通过传参传入的LoginUser,而校验用的是ThreaLocal,自然不会出现这种问题。

解决方案

那看来得改校验重复的实现方案了,用我最喜欢的ThreadLocal。创建一个ThreadLocal静态变量,这样里面存的数据都和线程相关,异步之后一直是同一个线程,自然不会出现错误的情况,最后在finally里面清空ThreadLocal,完美。
后续,果然没有再出现过错误限制导入的情况。

原因分析

因为异步用到了线程池。请求进来的时候,会校验用户信息,并将用户信息存入LoginUser中,以供全局使用。在线程执行结束之后,线程回到线程池,但线程对应的ThreadLocal的数据却没有清空。一般情况下,如果都是走Controller进来的请求都不会有问题,因为每次请求进来都会将新的用户信息set进去。但当异步的时候,就没有set用户信息的过程,线程内的用户信息还是上一次进入Controller用该线程的用户的用户信息。也就存在数据对不上的情况。而在异步中直接使用SecurityUtils.getSubject().getPrincipal()也就是犯了上面的错。

总的来说,就是SecurityUtils.getSubject().getPrincipal()实际用的也是ThreadLocal,而ThreadLocal和线程绑定,异步会导致数据丢失,注意!

http://www.khdw.cn/news/45157.html

相关文章:

  • 做网站找哪里刷关键词排名软件
  • java 网站开发需要多久中国最新新闻
  • 外贸平台哪个好对网站提出的优化建议
  • 网站建设色360投放广告怎么收费
  • 云南 房地产网站建设软文营销文章300字
  • 郑州移动网站建设百度入口
  • 网站平台建设呈现全新亮点怎么找关键词
  • 专做装修的网站有趣软文广告经典案例
  • 一个网站如何做外链网络营销推广合同
  • 最靠谱的网站建设公司网站seo关键词排名查询
  • 苏州微网站开发百度指数是什么
  • 微信微网站 留言板衡阳网站优化公司
  • 驻马店住房和城乡建设部网站百度竞价多少钱一个点击
  • 公主坟网站建设信息流广告哪个平台好
  • 如何网站建设网络推广怎么做方案
  • 做网站费用东莞网络推广优化排名
  • web网页版登录入口网站推广和优化系统
  • 标准物质网站建设游戏推广代理app
  • 老外做摄影网站花多少钱今日热点新闻事件标题
  • wordpress移动新闻seo搜索排名优化
  • aspnet网站开发实例新手怎么做电商运营
  • 香港网站源码建立网站平台需要多少钱
  • 做修图网站电脑配置营销网站建设哪家好
  • 韩国美食做视频网站有哪些迅雷下载磁力天堂
  • 学硬件好还是学软件好谷歌优化排名哪家强
  • 一个人做b2b2c网站建网站专业
  • wordpress在线问答插件在线优化工具
  • 麻涌建设网站江北seo页面优化公司
  • 关于做花茶网站的策划书培训班招生方案
  • 好一点的app开发公司重庆seo代理