二言目
type: channel
link: https://blog.piemoe.com/
description: 热爱生活，热爱编码
items: QQ炫舞手游传统模式自制制作
items: Mac常用Java开发环境 docker-compose版
items: Openvpn搭建及使用方法
items: Swagger 枚举字段显示在接口文档中，并自定义枚举返回
items: Centos7 更改 Go 环境国内代理
items: 常用的@Superwarnning 注解大全
items: 使用SpringCloud Alibaba结合Springboot3.0 搭建一个demo
items: Maven配置多线程打包
items: 使用Optional增强Mybatis-plus体验
items: 通过注解或Lambda方式进行数据脱敏
items: 使用TeamCity实现hexo自动化部署

QQ炫舞手游传统模式自制制作
type: item
date: 2023-02-25T13:52:00+08:00
description: QQ炫舞手游传统模式自制制作本篇文章通过讲解qq炫舞手游传统模式的一些参数，使得传统自制歌曲脱离官方编辑器成为可能在线试用： 点击在线试用 本人通过本篇文章制作出来的传统自制歌曲编辑器预览：主页转码歌曲编辑模式选择+可预览按键进度完成制作，自动生成二维码，总计用时，30sCT自制公式注：只针对炫舞手游官方编辑器首先了解一些参数ET：代表歌曲进入时间 EnterTime（Adjust）以下参数以300bpm 举例：节拍：300bpm固定一个节拍为 3200ms ，设为X关卡小节：一个节拍为4个关卡小节，每个关卡小节 800ms ，设为Y ：设为Z关卡小节数全歌时长为公式为：​ET + 关卡时间 - 提前显示小节数 = ET + (关卡小节数 * 节拍时间) - 提前显示小节数 = ET + ( Z * X ) - Y = ET + ( Z * X ) - Z/4 = 歌曲时长ms因此， 300bpm 歌曲计算公式为ET + ( Z * 4 * Y ) - 800 = ET + ( Z * 3200 ) - 800 = 歌曲时长ms若已知一首歌曲时长为 3:12.940 ，则毫秒数为 192940（ 3 * 60 * 1000 + 12940 ）套用公式ET + ( Z * 4 * Y ) - 800 = ET + ( Z * 3200 ) - 800 = 192940故 ET 计算方式ET = （ 192940 + 800 ) / 800 商为Z，即关卡小节数为：242 余数乘4即ET，为： 0.175 * 4 = 140 因此 ET为140ET调节方式关卡小节数Z = 242 - m ET = 140 + 800m 即 ET： 140 + 800 * 2 = 1740 则关卡小节数Z为: 242 - 2 = 240注： 理论上 ，ET为整数较好，所以需要微调ET，但要兼顾歌曲整体时长最终计算方法关卡小节数 = ( 歌曲时长毫秒数 + Y ) / Y 【整数部分】 关卡小节数 = ( 歌曲时长毫秒数 + Y ) / Z * 4 【整数部分】 ET = （ ( 歌曲时长毫秒数 + Y ) % Y ）【小数部分】* Y ET = （ ( 歌曲时长毫秒数 + Y ) % Z * 4 ）【小数部分】* Y综上，ET针对的是全歌曲，变动的是整个歌曲时长，所谓ET找P值，若歌曲源文件无时长改动，修改ET实际对P点意义不大，只是将歌曲在编辑器中裁剪了一番，可能会降低P的手感，也可能让关卡小节时间卡在了歌曲本身的节拍上，从而增加手感，但会造成一定的问题。此方式制作歌曲只需考虑歌曲时长、ET、关卡小节数即可，必填参数为音乐BPM 、ET(毫秒) 、关卡小节数，其他相同。相关常见速度关卡小节值 Y理论值 误差为 ± 1ms bpm关卡小节值 Y （ms）节拍值 Z （ms）380631.5789（非整）2526.3758（非整）360666.6667（非整）2666.6667（非整）340705.8823（非整）2823.5294（非整）32075030003008003200280857.1429（非整）3428.5714（非整）260923.0769（非整）3692.3077（非整）240100040002201090.9091（非整）4363.6364（非整）200120048001801333.3333（非整）5333.3333（非整）16015006000综上，160、180、200、240、300、320歌曲节拍较为稳定。提升建议从一个有效beat到另一个有效beat时间为2Y（2歌关卡小节值），无间断为Y（一个关卡小节值），按键总时长皆为Y（一个关卡小节值）。300bpm，一次为 1.6秒 ，按键时长为 800 ms 左右， 三键单键平均时长为266ms左右，五键为160ms左右，六键为133ms左右，七键为 114 ms 左右 ，键越多，留给单键按键时间越少，难度越高。320bpm，三键单键平均时长为250ms左右，五键为150ms左右，六键为125ms左右，七键为107ms左右340bpm，三键单键平均时长为235ms左右，五键为141ms左右，六键为117ms左右，七键为100ms左右。360bpm，三键单键平均时长为222ms左右，五键为133ms左右，六键为111ms左右，七键为95毫秒左右。由于键位方向不同，故不存在时间重叠的概念。实际单键平均时长要小于以上理论值（大神要P的）。可见，时间递增不多，但难度系数递增。五六七键差距太大是由于按键时长缩减但键数增加导致的大脑反应和手速难度系数倍增，故五键P多不代表能按到六七键故，短键（5键以下）连P增加分数，五键尽量P，great和cool意义不大，六七键尽量绿一点，拉开分数，但…

Mac常用Java开发环境 docker-compose版
type: item
date: 2023-04-12T15:21:00+08:00
description: version: '3.2' services: redis5: image: redis:5 container_name: redis5 restart: always environment: - ALLOW_EMPTY_PASSWORD=yes command: redis-server --appendonly yes --requirepass 123456 volumes: - redis:/data #数据文件挂载 ports: - 6379:6379 nacos-registry: image: nacos/nacos-server:v2.2.3 container_name: nacos environment: - PREFER_HOST_MODE=hostname - MODE=standalone - SPRING_DATASOURCE_PLATFORM=mysql - MYSQL_SERVICE_HOST=mysql - MYSQL_SERVICE_DB_NAME=nacos - MYSQL_SERVICE_PORT=3306 - MYSQL_SERVICE_USER=root - MYSQL_SERVICE_PASSWORD=123456 - MYSQL_SERVICE_DB_PARAM=characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true # volumes: # - /docker/service/env/nacos:/home/nacos/init.d ports: - "8848:8848" - "9555:9555" - "9848:9848" - "9849:9849" restart: on-failure external_links: - mysql:db #可以用db这个域名访问mysql服务 depends_on: - mysql mysql: image: mysql container_name: mysql command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --lower_case_table_names=1 --log_bin_trust_function_creators=1 --max_allowed_packet=100G --tmp_table_size=256M --key_buffer_size=512M --innodb_log_file_size=1024M restart: always environment: MYSQL_ROOT_PASSWORD: 123456 #设置root帐号密码 ports: - 3306:3306 volumes: - mysql8:/var/lib/mysql #数据文件挂载 volumes: redis: external: true mysql8: external: true

Openvpn搭建及使用方法
type: item
date: 2023-03-02T10:23:00+08:00
description: Openvpn搭建及使用方法前置操作echo 1 > /proc/sys/net/ipv4/ip_forward sysctl -p /etc/sysctl.conf搭建步骤拉取镜像docker pull kylemanna/openvpn创建全局变量OVPN_DATA="/data/openvpn" mkdir $OVPN_DATA配置公网ipIP="xxx.xxx.xxx.xxx"初始化将保存配置文件和证书的容器。容器将提示输入密码以保护新生成的证书颁发机构使用的私钥tcp：docker run -v ${OVPN_DATA}:/etc/openvpn --rm kylemanna/openvpn ovpn_genconfig -u tcp://${IP}udp：docker run -v ${OVPN_DATA}:/etc/openvpn --rm kylemanna/openvpn ovpn_genconfig -u udp://${IP}密钥配置docker run -v ${OVPN_DATA}:/etc/openvpn --rm -it kylemanna/openvpn ovpn_initpki例子Enter PEM pass phrase: 输入123456（你是看不见的） Verifying - Enter PEM pass phrase: 输入123456（你是看不见的） Common Name (eg: your user, host, or server name) [Easy-RSA CA]:回车一下 Enter pass phrase for /etc/openvpn/pki/private/ca.key:输入123456启动打开VPN服务器进程tcp：docker run --name openvpn -v ${OVPN_DATA}:/etc/openvpn -d -p 1194:1194 --cap-add=NET_ADMIN --name openvpn kylemanna/openvpnudp：docker run --name openvpn -v ${OVPN_DATA}:/etc/openvpn -d -p 1194:1194/udp --cap-add=NET_ADMIN --name openvpn kylemanna/openvpn生成不带密码的客户端证书docker run -v ${OVPN_DATA}:/etc/openvpn --rm -it kylemanna/openvpn easyrsa build-client-full CLIENTNAME nopass检索带有嵌入式证书的客户端配置docker run -v ${OVPN_DATA}:/etc/openvpn --rm kylemanna/openvpn ovpn_getclient example > example.ovpn客户端下载Community Downloads | OpenVPNOpenVPN-2.5.7-I602-amd64.msi删除docker run -v ${OVPN_DATA}:/etc/openvpn --rm -it kylemanna/openvpn easyrsa revoke $DNAME docker run -v ${OVPN_DATA}:/etc/openvpn --rm -it kylemanna/openvpn easyrsa gen-crl docker run -v ${OVPN_DATA}:/etc/openvpn --rm -it kylemanna/openvpn rm -f /etc/openvpn/pki/reqs/"$DNAME".req docker run -v ${OVPN_DATA}:/etc/openvpn --rm -it kylemanna/openvpn rm -f /etc/openvpn/pki/private/"$DNAME".key docker run -v ${OVPN_DATA}:/etc/openvpn --rm -it kylemanna/openvpn rm -f /etc/openvpn/pki/issued/"$DNAME".crt

Swagger 枚举字段显示在接口文档中，并自定义枚举返回
type: item
date: 2023-03-01T12:17:00+08:00
description: Swagger 枚举字段显示在接口文档中，并自定义枚举返回最近使用枚举做为接收参数，接收枚举中的某一个属性，返回对应的枚举，但是发现这种方法不能在swagger文档中体现，故此拓展springfox插件来实现。⚠️ 本次修改兼容 v2 v3先来看下效果：请求参数显示枚举信息响应显示枚举信息接下来实操请求参数和响应显示枚举信息创建枚举对应显示信息注解其中 value 为入参数值，desc 为入参的描述@Target({ ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) public @interface EnableSwaggerEnum { String value() default "value"; String desc() default "desc"; } @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface EnableSwaggerResponseEnum { String value() default "value"; String desc() default "desc"; }创建一个公共修改model由于要兼容v2 和 v3,故此需要创建一个修改的公共model，用来存放修改的枚举信息。其中，displayValues是用来显示各个枚举值和信息的字符串，allowableListValues 为实际要显示的入场值。@Data public class EnumMidModel { private String displayValues; private AllowableListValues allowableListValues; }封装modelpublic class SwaggerEnumUtils { /** * 封装枚举消息 * * @param type 此解析类型具有的类型擦除 Class<?> * @param enableSwaggerEnum 自定义swagger枚举限制注释 {@link EnableSwaggerEnum} * @return {@link EnumMidModel} * @author Mc * @since 2023/3/1 20:24 */ protected static EnumMidModel getEnumMidModel(Class<?> type, EnableSwaggerEnum enableSwaggerEnum) { EnumMidModel enumMidModel = new EnumMidModel(); String value = enableSwaggerEnum.value(); String desc = enableSwaggerEnum.desc(); Object[] enumConstants = type.getEnumConstants(); // 拼装显示内容 final String displayValues = Arrays.stream(enumConstants) .filter(Objects::nonNull) .map( item -> { Object valueVal = ReflectUtil.getFieldValue(item, value); Object descVal = ReflectUtil.getFieldValue(item, desc); return valueVal.toString() + " : " + descVal.toString(); } ) .collect(Collectors.joining("】\n【", "\n【", "】")); List<String> allowableValue = Arrays.stream(enumConstants) .filter(Objects::nonNull) .map(item -> ReflectUtil.getFieldValue(item, value).toString()) .collect(Collectors.toList()); AllowableListValues allowableListValues = new AllowableListValues(allowableValue, "string"); enumMidModel.setDisplayValues(displayValues); enumMidModel.setAllowableListValues(allowableListValues);…

Centos7 更改 Go 环境国内代理
type: item
date: 2023-02-25T13:45:00+08:00
description: Go 环境国内代理# 安装go依赖 yum install go # 修改go的环境变量添加国内代理 go env -w GOPROXY=https://goproxy.cn # 或者通过以下命令，添加代理 export GO111MODULE=on export GOPROXY=https://goproxy.cn,direct

常用的@Superwarnning 注解大全
type: item
date: 2023-02-25T13:34:00+08:00
description: 常用的@Superwarnning 注解大全​ 使用idea的时候，有时避免不了会被编辑器提示警告，虽然不影响代码和程序的正常观看和运行，但总之是不美观，这时便可以用@Superwarnning注解来抑制警告来。尽量在代码编辑无法穷善的时候使用@SuppressWarnings("unchecked")//执行了未检查的转换时的警告，例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型。 @SuppressWarnings("unused") //未使用的变量 @SuppressWarnings("resource") //有泛型未指定类型 @SuppressWarnings("path") //在类路径、源文件路径等中有不存在的路径时的警告 @SuppressWarnings("deprecation") //使用了不赞成使用的类或方法时的警告 @SuppressWarnings("fallthrough") //当 Switch 程序块直接通往下一种情况而没有 break; 时的警告 @SuppressWarnings("serial")//某类实现Serializable(序列化)， 但没有定义 serialVersionUID 时的警告 @SuppressWarnings("rawtypes") //没有传递带有泛型的参数 @SuppressWarnings("finally") //任何 finally 子句不能正常完成时的警告。 @SuppressWarnings("try") // 没有catch时的警告 @SuppressWarnings("DuplicatedCode") //重复代码警告抑制 @SuppressWarnings("SpellCheckingInspection") // 抑制错误拼写 @SuppressWarnings("DuplicatedCode") // 抑制重复代码提示 @SuppressWarnings("all") //所有类型的警告 @SuppressWarnings("UnusedParameters") // 未使用的参数 // 阿里巴巴插件 @SuppressWarnings("AlibabaClassNamingShouldBeCamel") //【xXxXXxX】不符合UpperCamelCase命名风格 @SuppressWarnings（"AlibabaLowerCamelCaseVariableNaming") // 变量名【xxXX】不符合lowerCamelCase命名风格

使用SpringCloud Alibaba结合Springboot3.0 搭建一个demo
type: item
date: 2023-02-17T12:51:00+08:00
description: Springboot 3 出来也有一段时间了，Springcloud alibaba也在适配当中，本demo使用Springboot 3 + Spingcloud alibaba + nacos等组件，完成一个项目工程的简单搭建组件Nacos : 2.0.3Maven：3.0.8依赖版本springboot :3.0.4springcloud:2022.0.1springcloud alibaba :2.2.10-RC1spring-cloud-starter-alibaba-nacos-discovery:2022.0.0.0-RC1spring-cloud-starter-alibaba-nacos-config：2022.0.0.0-RC1springcloud alibaba 2.2.10-RC1 版本提供的Nacos依赖，经测试无法成功注册，故使用2022.0.0.0-RC1版本项目POM<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.0.4</version> <relativePath/> </parent> <groupId>com.piemoe</groupId> <artifactId>springboot3</artifactId> <version>0.0.1-SNAPSHOT</version> <name>springboot3</name> <description>springboot3</description> <properties> <java.version>17</java.version> </properties> ​ <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2022.0.1</version> <type>pom</type> <scope>import</scope> </dependency> ​ <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.2.10-RC1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> ​ <dependencies> ​ <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dep…

Maven配置多线程打包
type: item
date: 2023-01-10T08:47:00+08:00
description: 只需将线程计数更改为`1C，然后确认即可。若改为8表示指定8个线程进行打包编译，此处的1C表示cpu线程的倍数，可以有效利用cpu的算力。按40个模块计算，M1 mac max 打包速度从原来的58s缩减到5.23s，这个速度还是很喜人的。

使用Optional增强Mybatis-plus体验
type: item
date: 2023-01-04T18:11:00+08:00
description: MyBatis-PlusMyBatis-Plus（简称MP）是MyBatis社区的一个增强工具包，它在MyBatis的基础上进行了扩展，封装了很多有用的功能，提高了开发效率。MyBatis-Plus中包含了许多常用的增删改查的方法，还有分页查询、条件构造器、乐观锁、多租户、性能分析等功能。以下是MyBatis-Plus的一些特点：简化开发：MyBatis-Plus可以通过代码自动生成器快速生成CRUD方法的代码，极大地提高了开发效率。增删改查方法：MyBatis-Plus封装了通用的增删改查方法，无需手写SQL语句。集成分页插件：MyBatis-Plus集成了分页插件，使用简单，可以轻松实现分页操作。条件构造器：MyBatis-Plus提供了条件构造器，可以通过代码的形式构造复杂的SQL查询语句。乐观锁：MyBatis-Plus提供了乐观锁的功能，避免了并发操作时的数据冲突。多租户：MyBatis-Plus支持多租户，可以通过配置实现多租户系统的开发。性能分析：MyBatis-Plus集成了性能分析插件，可以分析SQL查询的性能瓶颈，帮助优化SQL语句，提高查询效率。总之，MyBatis-Plus是一个非常优秀的MyBatis增强工具包，其功能强大且易于使用，在实际开发中也能够显著地提高开发效率和工作效率。Java OptionalJava Optional是Java 8中引入的一个类，用于表示一个值可能存在也可能不存在。它的主要目的是减少空指针异常。Java Optional类有两个重要的方法:isPresent()和get()。isPresent()方法用于检查值是否存在，get()方法用于获取值。如果值不存在，get()方法会抛出NoSuchElementException异常。Java Optional还有很多有用的方法，比如orElse()和orElseGet()方法。这些方法可以帮助我们处理值不存在的情况。Java Optional是一个泛型类，因此可以用于处理任何类型的值。使用Java Optional的主要优点是可以避免空指针异常，提高代码健壮性。堵点MyBatis-Plus提供了很好的CURD体验，大大加强了开发的效率，其Lambda表达式式的方式也大大增强了用户的体验，但是MyBatis-Plus返回的参数仍然会在实际项目中被忽略空指针问题，笔者的朋友和同事就经常因为空指针问题（主要是忘记）经常被测试吐槽，故此通过可以使用Optional来增强Mybatis-plus的体验，一定程度上可以避免“忘记”判空带来的空指针问题。代码项目中引入MyBatis-Plus，新建OptionalBaseMapper文件，实现BaseMapper，具体代码如下：@SuppressWarnings({"DuplicatedCode", "unused"}) public interface OptionalBaseMapper<T> extends BaseMapper<T> { // ======================================= 批量插入 ======================================== /** * 批量插入 仅适用于mysql * * @param entityList 实体列表 * @return 影响行数 */ Integer insertBatchSomeColumn(Collection<T> entityList); /** * 逐条插入，适合少量数据插入，或者对性能要求不高的场景 * * 如果大量，请使用 {@link com.baomidou.mybatisplus.extension.service.impl.ServiceImpl#saveBatch(Collection)} 方法 * 使用示例，可见 RoleMenuBatchInsertMapper、UserRoleBatchInsertMapper 类 * * @param entities 实体们 */ default void insertBatch(Collection<T> entities) { entities.forEach(this::insert); } // ======================================= 查询数量 ======================================== /** * 根据 Wrapper 条件，查询总记录数 * * @param queryWrapper 实体对象封装操作类（可以为 null） */ default Optional<Long> getCount(Wrapper<T> que…

通过注解或Lambda方式进行数据脱敏
type: item
date: 2022-11-10T10:51:00+08:00
description: 前言数据脱敏是一种数据保护技术，它可以对敏感数据进行处理，使其失去原始意义，从而保护数据隐私。通俗地说，就是将原始数据中敏感信息的部分替换或删除，例如：手机号码中的一部分数字替换为星号，或是姓名中的一些字母用其他字母代替等等。数据脱敏可以保护个人隐私，防止个人信息被泄露、滥用，同时也符合现代法律法规对个人信息保护的要求，是网络安全和信息保护中不可或缺的一环。本文将通过使用注解完成对字段的自定义脱敏功能。正文本文将介绍2种脱敏的方式，分别为：注解方式脱敏和lambda方式脱敏注解脱敏定义脱敏注解@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @JacksonAnnotationsInside @JsonSerialize(using = SensitiveSerialize.class) public @interface Dm { /** * 脱敏信息类型 */ DmTypeEnum type(); /** * 前置不需要打码的长度 * 只有 {@link DmTypeEnum} 为 {@link DmTypeEnum#CUSTOMER} 时可用 */ int prefixNoMaskLen() default 0; /** * 后置不需要打码的长度 * 只有 {@link DmTypeEnum} 为 {@link DmTypeEnum#CUSTOMER} 时可用 */ int suffixNoMaskLen() default 0; /** * 用什么打码 * 只有 {@link DmTypeEnum} 为 {@link DmTypeEnum#CUSTOMER} 时可用 */ char symbol() default '*'; }type()方法为可以支持实现的脱敏信息类型，通过使用hutool工具，可以看到它支持以下枚举，故拉取出来形成类型枚举：public enum DmTypeEnum { /** * 用户自定义 */ CUSTOMER, /** * 用户id */ BACK_ID, /** * 中文名 */ CHINESE_NAME, /** * 身份证号 */ ID_CARD, /** * 座机号 */ FIXED_PHONE, /** * 手机号 */ MOBILE_PHONE, /** * 地址 */ ADDRESS, /** * 电子邮件 */ EMAIL, /** * 密码 */ PASSWORD, /** * 中国大陆车牌，包含普通车辆、新能源车辆 */ CAR_LICENSE, /** * 银行卡 */ BANK_CARD }关键语句在@JsonSerialize(using = SensitiveSerialize.class)上，@JsonSerialize 是一个注解，它可以用来指定 Java 对象序列化成 JSON 格式时的序列化规则。具体而言，它可以指定序列化时属性名的命名方式、日期格式化等等。它的作用是使得 Java 对象可以方便地转化为 JSON 格式，这对于 Web 开发、移动应用开发等场景非常有用，故此我们在这里自定义一个实现，并在注解中引用。@NoArgsConstructor @AllArgsConstructor @Slf4j public class SensitiveSerialize<T> extends JsonSerializer<T> implements ContextualSerializer { /** * 脱敏类型 */ private DmTypeEnum sensitiveTypeEnum; /** * 前几位不脱敏 */ private Integer prefixNoMaskLen; /** * 最后几位不脱敏 */ private Integer suffixNoMaskLen; /** * 打码字符 */ private char symbol; @Override public void serialize(final T value, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider) throws IOException { Object desensitized = DmUtils.desensitized(value.toString(), sensitiveTypeEnum, prefixNoMaskLen, suffixNoMaskLen, symbol); if (desensitized instanceof String) { jsonGene…

使用TeamCity实现hexo自动化部署
type: item
date: 2022-11-07T18:26:00+08:00
description: 使用TeamCity实现hexo自动化部署前言之前使用Jenkins 来跑一些自己的项目，例如java程序和博客，我都是使用Jenkins配合docker来使用（感兴趣的朋友可以看我之前的文章），但是Jenkins的配置较为繁琐，流水线文件Jenkinsfile也需要一定的脚本语言功底，尤其是部署配置到其他机器时，配置还是比较繁琐的，于是，几经搜索，最后选择了TeamCity来做自动化，综合体验下来，确实比Jenkins 要香很多！官网地址奉上：TeamCity: the Hassle-Free CI/CD Tool by JetBrains概念CI/CD首先再来回顾下DevOps和CI/CD......（此处省略1w字）DevOps和CI/CD - 知乎 (zhihu.com)什么是 CI/CD？ (持续集成/持续交付)_guofangsky 的专栏-CSDN博客_ci/cd是否收费否看一下官网的价格可以看到，如果我们的构建代理只有3个及以下，我们完全可以免费用于即使是商业用途的情况。前提{% checkbox green checked, 云服务器/vps，保证内存达到2G及以上（1GB体验很差） %}{% checkbox green checked, '版本控制，如Github/Gitee/Gitlab等' %}{% checkbox green checked,你项目需要的构建环境的，如JDK、node等等 %}正文本次我们实现hexo自动化部署部署TeamCityTeamCity 部署需要2个步骤，分别是 server 端和agent端注意⚠️，agent端最好在server端后启动。server 端提供一个可视化的面板，使我们可以定制配置构建内容。使用docker compose部署version: "3" services: teamcity-server: user: root privileged: true container_name: teamcity-server image: jetbrains/teamcity-server volumes: - /data/teamCity/data:/data/teamcity_server/datadir - /data/teamCity/log:/opt/teamcity/logs ports: - 8111:8111当看到一下内容时，代表服务端启动正常Startup confirmation is required. Open TeamCity web page in the browser. Server is running at http://localhost:8111agent端放置于项目构建的位置，主要用于构建项目，和server端可以不在同一服务器⚠️ agent 端也可以用docker部署，但会发生很多意外！且低配服务器由于内存小等原因，容易出现oom，所以建议在server端中直接push agent端，详细请看配置。使用docker compose部署（不推荐docker部署）version: "3" services: teamcity-agent-01: user: root # 使用root账号 便于创建docker镜像 container_name: teamcity-agent01 image: jetbrains/teamcity-agent:2022.10-linux-sudo privileged: true # 赋予真正的权限 environment: - SERVER_URL=http://ip:8111 # teamcity-server 地址 - AGENT_NAME=teamcity-agent01 # agent端名称 - DOCKER_IN_DOCKER=start # 允许构建docker程序 volumes: - /var/run/docker.sock:/var/run/docker.sock # 允许构建docker程序 - /data/teamCity/agent/work:/opt/buildagent/work - /data/teamCity/agent/temp:/opt/buildagent/temp - /data/teamCity/agent/tools:/buildagent/tools - /data/teamCity/agent/plugins:/opt/buildagent/plugins - /data/teamCity/agent/system:/opt/buildagent/system单机版部署version: "3" networks: env_default:…