每日学习Java之一万个为什么?(Maven篇+RPC起步+CICD起步)(待完善)

发布于:2025-03-06 ⋅ 阅读:(16) ⋅ 点赞:(0)

为什么要用Maven代替Idea构建项目

1.标准化和可移植性

  • 标准化构建过程:Maven使用一个标准的构建生命周期(clean,compile,test,package,install,deploy等)这意味着无论你在哪个开发环境中工作,只要遵循Maven的规范,项目的构建工程都是一致的。
  • 跨平台兼容性:由于Maven构建文件pom.xml是基于XML格式的文本文件(POM project object module),可以在任何支持Java的平台上运行,而不需要依赖特定的IDE或者操作系统。

2.依赖管理和版本控制

  • 集中式依赖管理:Maven提供了强大的依赖管理功能,通过xml文件定义项目所需的库以及版本。IDEA也可以管理依赖,但Maven更加灵活和强大,特别是处理复杂的依赖关系时。
  • 自动下载和更新依赖:Maven可以从中央仓库或私有仓库自动下载所需的依赖库,并且能够自动处理依赖冲突和版本更新问题。

3.构建脚本的复用性和自动化

  • 构建脚本的复用性:Maven的xml文件是一个独立的配置文件,可以在不同的开发环境和CICD流水线中使用。这样,团队成员之间的协作更加流畅,减少了因环境差异导致的问题。
  • 自动化构建:Maven可以轻松集成到CI\CD工具:Jenkins、GitLab CI、CircleCI等中,实现自动化构建、测试和部署。相比之下,IDEA构建通常需要手动触发,并且不太适合自动化流水线。

4.插件生态系统
丰富的插件支持:Maven 拥有一个庞大的插件生态系统,提供了各种各样的功能扩展,如代码生成、文档生成、静态分析等。这些插件可以通过简单的配置添加到 pom.xml 中,无需额外的手动配置。
自定义构建逻辑:如果标准的构建生命周期不能满足需求,你可以通过编写自定义 Maven 插件来扩展构建过程。
5. 项目结构规范化
约定优于配置:Maven 强调“约定优于配置”的理念,它为项目提供了一个默认的标准目录结构(如 src/main/java, src/test/java 等)。这种标准化的结构不仅提高了项目的可读性,还使得新加入团队的成员能够快速上手。
减少人为错误:由于大多数项目都遵循相同的结构和命名规则,减少了人为配置错误的可能性。
6. 团队协作和版本控制
团队协作友好:Maven 的构建配置文件是文本文件,易于版本控制系统的管理(如 Git)。这使得团队成员可以轻松共享和同步项目的构建配置。
减少环境差异:Maven 通过 pom.xml 文件统一管理项目的构建配置,减少了由于不同开发人员使用的 IDE 设置不同而导致的构建差异。
7. 与外部工具和服务的集成
集成测试框架:Maven 可以无缝集成多种测试框架(如 JUnit, TestNG),并自动执行单元测试、集成测试等。
发布和部署:Maven 提供了内置的发布和部署机制,可以将构建好的 artifact 发布到远程仓库或部署到生产环境。
8. 性能优化
增量构建:Maven 支持增量构建,即只重新编译那些发生了变化的模块或文件,从而提高构建效率。
多模块项目支持:对于大型的多模块项目,Maven 提供了良好的支持,可以并行编译多个模块,进一步提升构建速度。
9. IDEA 对 Maven 的支持
虽然 IDEA 本身也提供了强大的构建和依赖管理功能,但它对 Maven 也有非常好的支持。你可以直接在 IDEA 中导入 Maven 项目,并利用其图形化界面来管理依赖、执行构建命令等。事实上,许多开发者会同时使用 Maven 和 IDEA,以便充分利用两者的优点。

RPC前置知识反射与lang包

分析RPC中的工厂设计模式

UserService userService = ServiceProxyFactory.getProxy(UserService.class);

public class ServiceProxyFactory {

    public static <T> T getProxy(Class<T> serviceClass) {
        return (T) Proxy.newProxyInstance(
                serviceClass.getClassLoader(),
                new Class[]{serviceClass},
                new ServiceProxy());
    }
}

public class ServiceProxy implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //指定序列化器
        Serializer serializer = new JdkSerializer();
        //发请求
        RpcRequest rpcRequest = RpcRequest.builder()
                .serviceName(method.getDeclaringClass().getName())
                .methodName(method.getName())
                .parameterTypes(method.getParameterTypes())
                .args(args)
                .build();

        try {
            //serialize
            byte[] bodyBytes = serializer.serialize(rpcRequest);
            //send req
            // todo:注册中心和服务发现机制解决地址硬编码问题
            try (HttpResponse httpResponse = HttpRequest.post("http://localhost:8080")
                    .body(bodyBytes)
                    .execute()) {
                byte[] result = httpResponse.bodyBytes();
                //反序列化
            RpcResponse rpcResponse = serializer.deserialize(result, RpcResponse.class);
            return rpcResponse.getData();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

编译阶段

编译成字节码: 使用Java编译器(javac)将.java文件编译成.class文件。每个类都会被编译成一个单独的.class文件,其中包含了类的元数据信息以及方法的字节码指令
例如:UserService.class, ServiceProxyFactory.class, ServiceProxy.class 等。

运行阶段

类加载
1 加载: JVM启动后,会初始化引导(Boot)类加载器、扩展类加载器和系统类加载器。当程序运行到new ServiceProxyFactory()或Proxy.newProxyInstance(…)时,JVM会使用系统类加载器去查找对应的类文件并加载它们。
2 链接:
3 验证: 检查类文件的格式是否正确,检查类中是否有不安全的操作,确保类文件符合JVM规范。
4 准备: 分配静态变量所需的内存空间,并设置默认初始值。
5 解析: 将符号引用转换为直接引用,即把常量池中的符号引用替换为实际的地址引用。
6 初始化: 执行类构造器()中的代码,对静态变量进行赋值操作。

UserService userService = ServiceProxyFactory.getProxy(UserService.class);

调用ServiceProxyFactory.getProxy(Class serviceClass)方法,传入UserService.class作为参数。
在getProxy方法内部,调用Proxy.newProxyInstance方法来创建一个新的代理实例:

参数一:类加载器 (serviceClass.getClassLoader())
参数二:代理接口列表 (new Class[]{serviceClass})
参数三:InvocationHandler 实例 (new ServiceProxy())

Proxy.newProxyInstance方法会生成一个新的代理类,这个类实现了传入的所有接口,并且所有的方法调用都会被转发到指定的InvocationHandler实现上。
方法调用
假设我们有一个方法调用userService.someMethod(param);,这里会发生以下步骤:

查找方法: JVM首先会在代理类中查找是否存在名为someMethod的方法。
调用处理器: 当找到对应的方法时,JVM不会直接执行该方法的代码,而是转而调用ServiceProxy.invoke(proxy, method, args)方法。
序列化请求: 在invoke方法内部,首先创建了一个RpcRequest对象,封装了调用的信息,然后将其序列化为字节数组。
发送HTTP请求: 使用HttpRequest.post(“http://localhost:8080”)方法发送POST请求至远程服务器,请求体包含序列化的rpcRequest字节数组。
接收响应: 接收远程服务器返回的响应,反序列化响应体中的RpcResponse对象,获取结果数据并返回给原始方法调用处。
内存分配
堆内存: Java对象(如UserService, ServiceProxy, RpcRequest, RpcResponse等)会被分配在堆内存中。
栈内存: 每个线程都有自己的栈内存,用于存储局部变量和方法调用帧。例如,在ServiceProxy.invoke方法中定义的局部变量serializer, rpcRequest, bodyBytes等都存在于当前线程的栈帧中。
方法区: 存储类的元数据信息,如字段名、方法签名等。此外,还包括字符串常量池和静态变量。

Proxy.newProxyInstatnce()静态方法分析

1.返回值(预期结果):Object 也就是说返回值是一个引用
2.修饰符(权限控制):public static 希望被JVM初始化并且被所有人使用
3.传参(ClassLoader a;Class<?>[] b ; InvocationHandler c)a、b、c三个参数分别是:

  • ClassLoader 是 Java 类加载器的一个抽象类,负责将类的字节码加载到 JVM 中,并将其转换为 Class 对象。每个类在运行时都需要通过类加载器加载到 JVM 中。

常见用途:
加载类:从文件系统、网络或其他来源加载类。
自定义类加载器:可以继承 ClassLoader 来实现自定义的类加载逻辑,例如从特定路径加载类或动态生成类。
示例:

ClassLoader classLoader = MyClass.class.getClassLoader();

在这个例子中,classLoader 是 MyClass 的类加载器,它负责加载 MyClass 及其依赖的类。

  • Class<?>[] b Class<?>[] 是一个泛型数组,表示一组 Class 对象。每个 Class 对象代表一个 Java 类或接口的运行时表示形式。

常见用途:
指定接口列表:在创建动态代理对象时,Class<?>[] 用于指定代理对象需要实现的接口列表。 反射操作:在使用反射时,Class<?>[] 可以用于表示方法参数类型或构造函数参数类型。
示例:

Class<?>[] interfaces = new Class<?>[]{MyService.class};

在这个例子中,interfaces 数组包含了一个接口 MyService,这表明代理对象需要实现 MyService 接口。

  • InvocationHandler c
    InvocationHandler 是一个接口,用于定义代理对象的方法调用处理器。当你创建一个动态代理对象时,必须提供一个实现了 InvocationHandler 接口的对象。该接口只有一个方法:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;

方法参数说明:
Object proxy:代理对象本身。
Method method:被调用的方法对象。
Object[] args:传递给方法的实际参数。
常见用途:
拦截方法调用:你可以通过实现 invoke 方法来拦截并处理代理对象上的方法调用。
动态代理:与 Proxy.newProxyInstance 结合使用,创建动态代理对象。
示例:
java
深色版本
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler {
private final Object target;

public MyInvocationHandler(Object target) {
    this.target = target;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("Before method: " + method.getName());
    Object result = method.invoke(target, args);
    System.out.println("After method: " + method.getName());
    return result;
}

}
在这个例子中,MyInvocationHandler 实现了 InvocationHandler 接口,并在 invoke 方法中添加了前置和后置处理逻辑。

综合示例
假设你有一个服务接口 MyService,并且你想为其创建一个动态代理对象。以下是完整的示例代码:

服务接口和实现类
java
深色版本
public interface MyService {
void doSomething();
}

public class MyServiceImpl implements MyService {
@Override
public void doSomething() {
System.out.println(“Doing something…”);
}
}
创建动态代理对象
java
深色版本
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DynamicProxyExample {

public static void main(String[] args) {
    // 创建目标对象
    MyService myService = new MyServiceImpl();

    // 创建 InvocationHandler
    InvocationHandler handler = new MyInvocationHandler(myService);

    // 获取类加载器
    ClassLoader classLoader = myService.getClass().getClassLoader();

    // 指定代理对象需要实现的接口
    Class<?>[] interfaces = new Class<?>[]{MyService.class};

    // 创建动态代理对象
    MyService proxy = (MyService) Proxy.newProxyInstance(classLoader, interfaces, handler);

    // 调用代理对象的方法
    proxy.doSomething();
}

}
输出结果
深色版本
Before method: doSomething
Doing something…
After method: doSomething
总结
ClassLoader a:用于加载类的类加载器,负责将类的字节码加载到 JVM 中。
Class<?>[] b:一个包含多个 Class 对象的数组,通常用于指定代理对象需要实现的接口列表。
InvocationHandler c:实现了 InvocationHandler 接口的对象,用于拦截并处理代理对象的方法调用。
这三个参数通常一起使用,特别是在创建动态代理对象时。通过 Proxy.newProxyInstance 方法,结合这三个参数,可以创建一个实现了指定接口并具有自定义行为的代理对象。

Maven中的细节

GAVP
G:groupID 公司域名倒写 (业务线设置)
A:ArtificID 组件ID 一般表示某个模块 我们有的时候模块外面还会设置一个大的项目,比如说苍穹外卖外面还包了一层sky。其中的pom.xml是用来统一管理依赖,这种设计应当涉及Maven中的依赖管理和依赖生命周期
V:Version 表示模块(产品)迭代版本 x.x.x 第一层表示大版本更新 第二层表示小模块更新 第三层表示bug修复,功能完善
P:设置打包模式,才能让服务器比如tomcat发现你

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  <modelVersion>4.0.0</modelVersion>

  <!--Maven工程在Maven仓库中的坐标:GAVP-->
  <groupId>com.qxy</groupId>  
  <artifactId>plugin_test</artifactId>
  <!--默认快照版本-->
  <!--<version>1.0-SNAPSHOT</version> -->
  <!--version:
  x(主版本,模块功能变化).y(次版本,功能修改).z(修订号,bug修改)
  修改时机:maven项目部署到maven仓库的时候需要修改版本号
  -->
  <version>1.0.0</version>
  <!--项目的类型以及打包方式
        jar 默认值 javase -> 给其他Java工程提供技术支撑
        war -> war 包 -> 进行tomcat容器部署
        pom -> 不打包 -> Maven特有的父工程 依赖管理
  -->
  <packaging>war</packaging>


  <!--  maven的配置参数:maven自带识别的参数(固定)| 自定义参数配合通配符 控制全局版本
      自定义参数命名规范:
      1.不要单层命名
      2.推荐:框架名.version
  -->
  <properties> 
    <maven.compiler.source>17</maven.compiler.source>  
    <maven.compiler.target>17</maven.compiler.target>  
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <spring.version>6.0.6</spring.version>
  </properties>

  <!--导入依赖坐标以及版本
      dependencies 依赖信息配置和管理
          dependency 单个依赖信息配置
              GAV
      GAV信息的搜索:
        1.官网搜索mvnrepository.com
        2.安装maven-search plugin
        3.记载脑子里
        4.大模型搜索

          scope : main  test  打包运行
         complie:   1     1     1     绝大部分
        provided:   1     1     0     servlet
         runtime:   0     0     1     mysql
            test:   0     1     0     junit
  -->
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.2</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>


  </dependencies>

</project>

依赖下载的三步骤:
1.在本地仓库设置一个站位文件 .lastedupdated 保证了目标依赖只会下载一次
2.开始进行jar包下载
3.下载成功后,会删除lastupdated文件
所以下载过程中报错一定需要去本地仓库把lastupdated文件给删了才能重新下载。
还有可能是网络波动。
还还有可能是阿里的网络波动。
这个时候等不及的话可以复制别人仓库的依赖信息,或者像JavaWeb一样在lib文件下粘贴jar包

Maven(IDEA module structure)中的依赖作用域Scope

Maven配置文件编写[掌握]

maven的xml规定:就是记标签

Maven的工程在maven仓库的坐标位置:GAVP

Maven标准化构建过程以及常用生命周期

↓清理:删除上一次构建的产物 删除项目下的target文件夹
↓编译:Java文件编译成class文件的过程
↓测试:检查代码是否存在异常(编译异常)||批量执行单元测试代码(测试类必须Test结尾)
↓报告:生成一个网页html , html文件中显示Maven的依赖信息配置等等
↓打包:将项目按照packaging的设置打成对应的包
↓部署:将maven项目加入到maven的仓库中(项目必须是jar包)
1、本地部署(install):将项目jar包导入到本地的maven仓库,只有当前电脑可以使用。
2、私服部署(deploy):将项目jar包导入公司局域网的仓库,然后公司范围内共享。配个私服地址和私服镜像

主动构建时机和场景:
1.清理项目:主动触发其他动作了,都要先清理。
2.重新编译:项目本已经存在的文件,运行就是找不到,可能没有被编译。
3.重新打包:se项目可能jar包被别人引用,ee项目打war包进行部署。
4.项目部署:工具项目被别的项目引入之前需要先进行部署。

构建方式:

  • 命令构建:
    进入到项目的根目录下和pom.xml文件平级才能触发mvn
mvn 构建动作 1 构建动作 2 ... 
mvn clean
mvn compile
mvn test
mvn site
mvn package
mvn install
mvn deploy
  • IDEA中可视化构建

周期 命令 插件(用周期即可)

在这里插入图片描述在这里插入图片描述

Maven中的打包命名问题以及导入插件

默认打包名称:artifactid-version.packaging
添加标签:

<build>
<finalName>maven</finalName>
<!-jdk17和打war包和site插件版本插件小配><plugins>
<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-war-plugin</artifactId>
	<version>3.2.2</version>
</plugin>
	<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-site-plugins/artifactId>
	<verslon>3.9.1s/version><!--此处换为你所需的版本号-->
	</plugin>
</plugins>
</build>

Maven中的打包资源控制问题

按照约定放置文件,不会出现漏打包和编译问题!
怎么解决?

1.比如说UserDao.xml 配置在resources/com.xxx.maven 就可以使其打包到与UserDao接口同级目录中
2.利用resources标签去控制resource包下的资源
在这里插入图片描述上述修改位.class不推荐,应当使用与.gitgnore思想相同,采用 exclude标签
在这里插入图片描述

Maven打包通用标签结构

在这里插入图片描述

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.</groupId>
    <artifactId></artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <jackson.version>2.15.2</jackson.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>${jackson.version}</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>${jackson.version}</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope> <!-- test表示仅在测试中生效-->
        </dependency>
    </dependencies>

    <build>
        <finalName>maven</finalName>

        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.*</include>
                </includes>
                <excludes>
                    <exclude>**/*.java</exclude>
                </excludes>
            </resource>
            
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.*</include>
                </includes>
            </resource>
        </resources>
    </build>
</project>

Maven中的依赖传递

首先,我们既然引入dependency ,那么你引入的依赖,也可能会引入别的dependecy。
别人引入的只有Compile级别会对你的项目有效

依赖传递:下载以来,会自动下载依赖的依赖(Compile级)
传递作用:简化依赖的导入,间接的进行了版本的检查,尽量使用依赖传递。
依赖终止条件:
1.传递的都是非compile 级
2.到了依赖的尽头
3.出现依赖冲突了

Maven中的依赖冲突

依赖冲突:
发现了重复依赖,终止后续的所有依赖传递
此时显式依赖会覆盖非显式依赖,避免了重复依赖和循环依赖,至多会出现版本不兼容。

重复jar包选择原则:

  • 谁短谁优先(第一原则):依赖chain长度,谁短谁优先
  • 谁上谁优先(第二原则):长短一致,先声明的优先

在这里插入图片描述
可以发现,Maven的自动排除冲突并不会很智能的采用高版本依赖。

手动排除冲突依赖(无法撼动规则的时候,就把竞争者干掉)

Maven中项目聚合和继承作用

Maven继承关系指定是通过父POM文件来为子模块提供统一的配置和约定。父模块多个子模块提供了共享的构建信息、插件配置、依赖管理等。

作用:

  • 共享配置:通过父pom,多个子模块可以继承相同的插件配置、版本号等,避免在子模块中重新配置,减少冗余。
  • 版本统一:父POM中指定了插件或者依赖的版本号,子模块会自动继承这些版本,确保整个项目使用统一的版本,避免版本冲突

示例:
父模块pom指定了springcore的版本号
xml
4.0.0
com.example
parent-project
1.0-SNAPSHOT
pom

<!-- Dependencies, plugin versions, etc., go here -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.3.9</version>
        </dependency>
    </dependencies>
</dependencyManagement>

子模块指定父pom的位置:
xml
4.0.0

com.example
parent-project
1.0-SNAPSHOT
…/pom.xml

<artifactId>child-module</artifactId>

在这个例子中,child-module会继承父项目parent-project中的所有配置,包括dependency,plungin,和version。

Maven中的聚合(Aggregation)

Maven中的聚合关系指的是在父模块中定义多个子模块,父模块作为一个聚合器来统一管理和构建这些子模块。聚合关系强调的是父模块对多个子模块的组织和管理,而不是配置的继承。

作用:

  • 多模块管理:父模块通过《modules》标签列出所有子模块,Maven会按照父模块定义的顺序构建这些子模块。这是用于多个模块的开发需要一起构建和发布的场景。

  • 统一构建:可以通过在父模块中执行mvn clean install 方法来同时构建所有子模块,而不需要分别构建子模块。

示例,父模块pom指定子模块:
xml
4.0.0
com.example
parent-project
1.0-SNAPSHOT
pom

<!-- 聚合模块 -->
<modules>
    <module>child-module-1</module>
    <module>child-module-2</module>
</modules>

子模块pom,指定父模块:
xml
4.0.0

com.example
parent-project
1.0-SNAPSHOT
…/pom.xml

<artifactId>child-module-1</artifactId>
继承 聚合
共享配置和构建设置 管理多个子模块的构建过程
子模块继承父模块的配置 父模块不影响子模块的配置,只是管理构建顺序
子模块继承父模块配置后,配置的修改会影响子模块 聚合之管理模块之间的关系,不影响配置的继承
需要统一版本、插件和依赖管理的大型项目 需要同时构建多个模块的项目

解释下Maven软件依赖管理和项目构建功能

依赖管理:让Maven帮我们进行jar包管理,我们只需要写少量的配置就会自动下载依赖,以及下载依赖的依赖,确保依赖链的完整以及版本没有冲突。

项目构建:项目源文件转化为可执行文件的过程和步骤,maven构建的过程对外完全透明化|使用maven构建可以在不同的开发工具拥有相同的项目结构

解释下maven项目gavp含义以及javaee的项目结构

maven-本地存储-部署到maven仓库中-gavp
g:项目所属的组织和公司名称,公司域名倒写,不要超过4层
a:artifactid 项目标识 等同于项目名
v:version版本
p:packaging 打包方式以及项目类型 jar war pom

maven的构建六步骤,以及每个步骤作用

clean complie test report package deploy

写出maven的依赖作用域scope含义以及四个值范围

compile

GitLab+Jenkins+K8s了解

(CI)、持续交付(CD)以及容器化应用的自动化部署。以下是如何将这三者结合起来使用的详细步骤和配置方法。

整体架构概述
GitLab:作为代码仓库和 CI/CD 管道的触发器。
Jenkins:作为 CI/CD 工具,负责构建、测试和部署应用程序。
Kubernetes (K8s):用于容器编排和管理,提供高可用性和弹性扩展。

io:vertix依赖了解

核心功能
异步非阻塞 I/O:
Vert.x 使用 Netty 底层库实现了高效的异步非阻塞 I/O 操作,使得应用能够在高并发场景下表现出色。
事件总线(Event Bus):
提供了一个分布式的事件总线,允许不同的 Verticle(Vert.x 组件)之间进行通信,支持点对点、发布/订阅模式。
HTTP 和 Web 服务:
支持 HTTP/HTTPS 协议,提供 RESTful API 开发的能力,并且可以集成 WebSocket、SockJS 等实时通信协议。
数据存储和访问:
提供了多种数据库的客户端库,如 MongoDB、Redis、JDBC 等,方便与各种数据存储系统交互。
消息队列和流处理:
集成了 Kafka、RabbitMQ 等消息队列系统,支持流处理和消息驱动架构。
微服务框架:
提供了构建微服务的工具,包括服务发现、负载均衡等功能。
多语言支持:
Vert.x 支持多种编程语言,如 Java、Kotlin、Groovy、JavaScript(通过 Nashorn 或 GraalVM)、Ruby、Python 等。

cn:hutool

核心功能
Hutool 的设计目标是提供一个“小而全”的工具包,让 Java 开发变得更加简洁和高效。以下是 Hutool 提供的一些主要功能模块:

Bean 操作:
cn.hutool.core.bean.BeanUtil:用于 Bean 的拷贝、属性获取与设置等操作。
日期时间操作:
cn.hutool.core.date.DateUtil:提供日期格式化、解析、计算等功能。
集合操作:
cn.hutool.core.collection.CollUtil:提供集合的创建、遍历、过滤等便捷方法。
字符串操作:
cn.hutool.core.util.StrUtil:提供字符串的拼接、分割、替换等操作。
文件操作:
cn.hutool.core.io.FileUtil:提供文件读写、复制、删除等操作。
加密解密:
cn.hutool.crypto.DigestUtil 和 cn.hutool.crypto.SecureUtil:支持多种加密算法,如 MD5、SHA、AES 等。
HTTP 客户端:
cn.hutool.http.HttpUtil:提供简单的 HTTP 请求发送功能。
JSON 处理:
cn.hutool.json.JSONUtil:用于 JSON 数据的生成和解析。
日志门面:
cn.hutool.log.LogFactory:提供了一个统一的日志接口,支持多种日志框架。
定时任务:
cn.hutool.cron.CronUtil:提供类似 Crontab 的定时任务调度功能。
其他:
还包括更多实用工具类,如正则表达式操作、URL 编码解码、对象序列化等。


网站公告

今日签到

点亮在社区的每一天
去签到