最近一年时间一直在写 Golang ,也算是对 Golang 有了初步的掌握,再次写 Java 的时候发现有点生疏了,写代码的时候也不自觉代入了写 Golang 的思维。
正如我想要在 Java 里面想让某一个方法只执行一次的时候,我第一时间想到了 Golang 里面的 Once 功能。
sync.Once 是 Golang 的一个并发原语,它提供了一种安全地在多个 goroutine 中执行某个函数(或代码块)一次的机制。
sync.Once 类型有一个 Do 方法,该方法接收一个函数作为参数,并确保这个函数只会被执行一次,无论有多少个 goroutine 同时调用它。具体来说,第一个调用 Do 方法的 goroutine 会执行这个函数,而其他 goroutine 则会等待它完成,然后返回相同的结果。
sync.Once 可以用于一些需要全局初始化的场景,比如初始化配置信息、数据库连接等。使用 sync.Once 可以确保这些初始化只会被执行一次,并且可以安全地被多个 goroutine 共享使用。
– 来自 ChatGPT
其实和单例模式差不多,但我想要的是让方法只执行一次,我魔改了一下,直接上代码吧。
package cn.typesafe.sync; import lombok.SneakyThrows; import java.util.concurrent.Callable; public class Once<T> { private volatile T t = null; @SneakyThrows public T doOnce(Callable<T> action) { if (t == null) { synchronized (this) { if (t == null) { t = action....
2022年11月24日 SpringBoot 正式发布了 3.0 版本,带来许多新的特性,但我最关心的还是Java打包成原生二进制,运行时不再依赖jre环境,运行Java程序将和Go程序一样方便。
升级至 SpringBoot 3.0.0 说是尝鲜,但是我不想再试着搞 hello world 那种啥都没有的东西了,找到我之前写的一个Java开源项目 kafka-map 拿他开刀。
kafka-map 本身是基于 SpringBoot 2.4.x 开发的,sqlite 存储数据,且很久没有大的更新了,想要直接升级到 SpringBoot 3.0.0 是不可能的,我按照官方文档 Spring Boot 3.0 迁移指南 首先升级到最新2.7.x版本,然后就发现 service 依赖循环了,这个时候有两种选择,一是在配置文件中允许依赖循环 spring.main.allow-circular-references: true,二是梳理业务逻辑解决依赖循环的问题。作为一个合格的开发,我选择了解决依赖循环的问题,过程不表。
SpringBoot 3.0.0 升级了很多组件,其中 Jpa 依赖的 Hibernate 升级到了 6.x,我启动时又遇到了 sqlite 方言插件不可用的问题,还好 Hibernate 6.x 已经支持了 sqlite方言,切换到官方插件就好了。配置文件如下:
spring: datasource: url: jdbc:sqlite:data/kafka-map.db driver-class-name: org.sqlite.JDBC jpa: hibernate: ddl-auto: update show-sql: true properties: hibernate: dialect: org.hibernate.community.dialect.SQLiteDialect 原生二进制打包 打包原生二进制还是最折腾的,刚开始参考GraalVM Native Image Support 把打包 springboot:build-image 当成了打包原生二进制了,而且打包的过程中还遇到了 UnsupportedFeatureException: No instances of ch....
Clam AntiVirus(ClamAV)是免费而且开放源代码的杀毒软件,软件与病毒码的更新皆由社群免费发布。Github 地址:https://github.com/Cisco-Talos/clamav
安装 ClamAV yum install -y clamav* 配置 ClamAV cat > /etc/freshclam.conf <<EOF # 数据库配置文件夹 DatabaseDirectory /var/lib/clamav # 更新日志文件夹 UpdateLogFile /var/log/freshclam.log # 日志大小 LogFileMaxSize 2M # 日志记录时间 LogTime yes # 所属用户 DatabaseOwner root # 同步病毒库的地址 DatabaseMirror database.clamav.net EOF 更新病毒库 大概需要几分钟时间
freshclam 进行病毒扫描测试 clamscan -ri </path1/to/scan> </path2/to/scan> 常用配置说明
--recursive[=yes/no(*)] -r 递归查找 --infected -I 只打印受影响的文件信息 --remove[=yes/no(*)] 删除受影响的文件。(不建议使用,根据扫描结果进行手动删除,避免误删。) 配置邮箱 如果不需要邮件通知的可以忽略此步骤。
安装邮件服务 yum install -y mailx 修改配置 修改大写字母为你的邮箱配置
cat > /etc/mail.rc <<EOF set from=USERNAME@YOURDOMAIN....
银河麒麟高级服务器操作系统 V10 是针对企业级关键业务,适应虚拟化、 云计算、大数据、工业互联网时代对主机系统可靠性、安全性、性能、扩展性和 实时性的需求,依据 CMMI 5 级标准研制的提供内生安全、云原生支持、国产 平台深入优化、高性能、易管理的新一代自主服务器操作系统;同源支持飞腾、 龙芯、申威、兆芯、海光、鲲鹏等自主平台;可支撑构建大型数据中心服务器高 可用集群、负载均衡集群、分布式集群文件系统、虚拟化应用和容器云平台等, 可部署在物理服务器和虚拟化环境、私有云、公有云和混合云环境;应用于政府、 国防、金融、教育、财税、公安、审计、交通、医疗、制造等领域。
公司有个项目需要将系统部署在 kylinos上,刚开始还有点头疼,害怕各种程序无法安装和使用,等安装好服务器进行使用的时候发现这不就是基于centos的嘛,虽然基于哪个版本不知道,但是可以测试的,于是我一顿操作,最后发现它是基于Centos8的,系统内核版本是 4.19,问题不大,既然是基于Centos8的,那Centos8上能跑的程序,在这肯定也能跑,然后我就开始了愉快(痛苦)的安装docker之旅了。
配置阿里云Centos8镜像源 之所以要配置 Centos8 的镜像源是因为在安装docker的时候需要额外的一些依赖,而这些依赖在麒麟官方的源里面是没有的。
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-8.repo 配置阿里云 docker 镜像源 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo sed -i 's+download.docker.com+mirrors.aliyun.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo 定义 yum 变量&修改 repo 修改 centos 和 docker repo文件中的 $releasever 为 centos_version ,原因是在麒麟服务器操作系统V10中 $releasever被修改为了 10,而我们需要使用 centos 8的镜像源,如果你不替换,基本上仓库的每一个地址都是404。
echo "8" > /etc/yum/vars/centos_version sed -i 's/$releasever/$centos_version/g' /etc/yum.repos.d/docker-ce.repo sed -i 's/$releasever/$centos_version/g' /etc/yum.repos.d/CentOS-Base.repo 建立yum缓存 没啥可说的
yum makecache 查看docker-ce 版本 yum list docker-ce --showduplicates | sort -r docker-ce....
声明 本文章中所有内容仅供学习交流,严禁用于非法用途,否则由此产生的一切后果均与作者无关。
Fastjson <= 1.2.68 expectClass 绕过原理 当 fastjson 更新到 1.2.68 之后,大部分安全漏洞都已经封堵住了,但不排除还有人手里握着一些 0day 没有放出来。
fastjson 1.2.68 在进行反序列化的时候,会进入 ObjectDeserializer 的 deserialze 方法,而 安全人员发现 当 @type 为 java.lang.AutoCloseable 的时候会找到实现类 JavaBeanDeserializer 调用 deserialze,而 JavaBeanDeserializer 的 deserialze 方法还会继续解析得到第二个 @type 对应的值进行反序列化,并且 expectClass 则不再是 null 值,而是 java.lang.AutoCloseable。
JavaBeanDeserializer 的 deserialze 部分代码示例。
if (lexer.token() == JSONToken.LITERAL_STRING) { // 第二个 @type 的值 String typeName = lexer.stringVal(); lexer.nextToken(JSONToken.COMMA); if (typeName.equals(beanInfo.typeName)|| parser.isEnabled(Feature.IgnoreAutoType)) { if (lexer.token() == JSONToken.RBRACE) { lexer.nextToken(); break; } continue; } // 这里没有获取到 deserializer ObjectDeserializer deserializer = getSeeAlso(config, this....