3.0.4

1. 使用文档

Spring Cloud CircuitBreaker 项目包含 Resilience4J 和 Spring Retry 的实现。Spring Cloud CircuitBreaker 中实现的 API 位于 Spring Cloud Commons 中。这些 API 的使用文档位于 Spring Cloud Commons 文档

1.1. 配置 Resilience4J 断路器

1.1.1. 启动器

Resilience4J 实现有两个启动器,一个用于响应式应用程序,另一个用于非响应式应用程序。

  • org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j - 非响应式应用程序

  • org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j - 响应式应用程序

1.1.2. 自动配置

您可以通过将 spring.cloud.circuitbreaker.resilience4j.enabled 设置为 false 来禁用 Resilience4J 自动配置。

1.1.3. 默认配置

要为所有断路器提供默认配置,请创建一个 Customizer bean,该 bean 传递 Resilience4JCircuitBreakerFactoryReactiveResilience4JCircuitBreakerFactoryconfigureDefault 方法可用于提供默认配置。

@Bean
public Customizer<Resilience4JCircuitBreakerFactory> defaultCustomizer() {
    return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id)
            .timeLimiterConfig(TimeLimiterConfig.custom().timeoutDuration(Duration.ofSeconds(4)).build())
            .circuitBreakerConfig(CircuitBreakerConfig.ofDefaults())
            .build());
}
响应式示例
@Bean
public Customizer<ReactiveResilience4JCircuitBreakerFactory> defaultCustomizer() {
    return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id)
            .circuitBreakerConfig(CircuitBreakerConfig.ofDefaults())
            .timeLimiterConfig(TimeLimiterConfig.custom().timeoutDuration(Duration.ofSeconds(4)).build()).build());
}
自定义 ExecutorService

如果您想配置执行断路器的 ExecutorService,可以使用 Resilience4JCircuitBreakerFactory

例如,如果您想使用上下文感知的 ExecutorService,您可以执行以下操作。

@Bean
public Customizer<ReactiveResilience4JCircuitBreakerFactory> defaultCustomizer() {
    return factory -> {
        ContextAwareScheduledThreadPoolExecutor executor = ContextAwareScheduledThreadPoolExecutor.newScheduledThreadPool().corePoolSize(5)
            .build();
        factory.configureExecutorService(executor);
    };
}

1.1.4. 指定断路器配置

与提供默认配置类似,您可以创建一个 Customizer bean,该 bean 传递 Resilience4JCircuitBreakerFactoryReactiveResilience4JCircuitBreakerFactory

@Bean
public Customizer<Resilience4JCircuitBreakerFactory> slowCustomizer() {
    return factory -> factory.configure(builder -> builder.circuitBreakerConfig(CircuitBreakerConfig.ofDefaults())
            .timeLimiterConfig(TimeLimiterConfig.custom().timeoutDuration(Duration.ofSeconds(2)).build()), "slow");
}

除了配置创建的断路器之外,您还可以自定义断路器,在将其返回给调用者之前。为此,您可以使用 addCircuitBreakerCustomizer 方法。这对于向 Resilience4J 断路器添加事件处理程序很有用。

@Bean
public Customizer<Resilience4JCircuitBreakerFactory> slowCustomizer() {
    return factory -> factory.addCircuitBreakerCustomizer(circuitBreaker -> circuitBreaker.getEventPublisher()
    .onError(normalFluxErrorConsumer).onSuccess(normalFluxSuccessConsumer), "normalflux");
}
响应式示例
@Bean
public Customizer<ReactiveResilience4JCircuitBreakerFactory> slowCustomizer() {
    return factory -> {
        factory.configure(builder -> builder
        .timeLimiterConfig(TimeLimiterConfig.custom().timeoutDuration(Duration.ofSeconds(2)).build())
        .circuitBreakerConfig(CircuitBreakerConfig.ofDefaults()), "slow", "slowflux");
        factory.addCircuitBreakerCustomizer(circuitBreaker -> circuitBreaker.getEventPublisher()
            .onError(normalFluxErrorConsumer).onSuccess(normalFluxSuccessConsumer), "normalflux");
     };
}

1.1.5. 断路器属性配置

您可以在应用程序的配置属性文件中配置 CircuitBreakerTimeLimiter 配置或实例。属性配置的优先级高于 Java Customizer 配置。

从上到下优先级递减。

  • 方法(id) 配置 - 在特定方法或操作上

  • 服务(组) 配置 - 在特定应用程序服务或操作上

  • 全局默认配置

ReactiveResilience4JCircuitBreakerFactory.create(String id, String groupName)
Resilience4JCircuitBreakerFactory.create(String id, String groupName)
全局默认属性配置
resilience4j.circuitbreaker:
    configs:
        default:
            registerHealthIndicator: true
            slidingWindowSize: 50

resilience4j.timelimiter:
    configs:
        default:
            timeoutDuration: 5s
            cancelRunningFuture: true
配置属性配置
resilience4j.circuitbreaker:
    configs:
        groupA:
            registerHealthIndicator: true
            slidingWindowSize: 200

resilience4j.timelimiter:
    configs:
        groupC:
            timeoutDuration: 3s
            cancelRunningFuture: true
实例属性配置
resilience4j.circuitbreaker:
 instances:
     backendA:
         registerHealthIndicator: true
         slidingWindowSize: 100
     backendB:
         registerHealthIndicator: true
         slidingWindowSize: 10
         permittedNumberOfCallsInHalfOpenState: 3
         slidingWindowType: TIME_BASED
         recordFailurePredicate: io.github.robwin.exception.RecordFailurePredicate

resilience4j.timelimiter:
 instances:
     backendA:
         timeoutDuration: 2s
         cancelRunningFuture: true
     backendB:
         timeoutDuration: 1s
         cancelRunningFuture: false
  • ReactiveResilience4JCircuitBreakerFactory.create("backendA")Resilience4JCircuitBreakerFactory.create("backendA") 将应用 instances backendA properties

  • ReactiveResilience4JCircuitBreakerFactory.create("backendA", "groupA")Resilience4JCircuitBreakerFactory.create("backendA", "groupA") 将应用 instances backendA properties

  • ReactiveResilience4JCircuitBreakerFactory.create("backendC")Resilience4JCircuitBreakerFactory.create("backendC") 将应用 global default properties

  • ReactiveResilience4JCircuitBreakerFactory.create("backendC", "groupC")Resilience4JCircuitBreakerFactory.create("backendC", "groupC") 将应用 global default CircuitBreaker properties and config groupC TimeLimiter properties

有关 Resilience4j 属性配置的更多信息,请参阅 Resilience4J Spring Boot 2 配置

1.1.6. 支持舱壁模式

如果 resilience4j-bulkhead 位于类路径中,Spring Cloud CircuitBreaker 将使用 Resilience4j 舱壁包装所有方法。您可以通过将 spring.cloud.circuitbreaker.bulkhead.resilience4j.enabled 设置为 false 来禁用 Resilience4j 舱壁。

Spring Cloud CircuitBreaker Resilience4j 提供了两种舱壁模式的实现

  • 一个使用信号量的 SemaphoreBulkhead

  • 一个使用有界队列和固定线程池的 FixedThreadPoolBulkhead

默认情况下,Spring Cloud CircuitBreaker Resilience4j 使用 FixedThreadPoolBulkhead。要修改默认行为以使用 SemaphoreBulkhead,请将属性 spring.cloud.circuitbreaker.resilience4j.enableSemaphoreDefaultBulkhead 设置为 true

有关舱壁模式实现的更多信息,请参阅 Resilience4j 舱壁

Customizer<Resilience4jBulkheadProvider> 可用于提供默认的 BulkheadThreadPoolBulkhead 配置。

@Bean
public Customizer<Resilience4jBulkheadProvider> defaultBulkheadCustomizer() {
    return provider -> provider.configureDefault(id -> new Resilience4jBulkheadConfigurationBuilder()
        .bulkheadConfig(BulkheadConfig.custom().maxConcurrentCalls(4).build())
        .threadPoolBulkheadConfig(ThreadPoolBulkheadConfig.custom().coreThreadPoolSize(1).maxThreadPoolSize(1).build())
        .build()
);
}

1.1.7. 指定舱壁配置

与提供默认的“舱壁”或“线程池舱壁”配置类似,您可以创建一个 Customizer bean,该 bean 传递 Resilience4jBulkheadProvider

@Bean
public Customizer<Resilience4jBulkheadProvider> slowBulkheadProviderCustomizer() {
    return provider -> provider.configure(builder -> builder
        .bulkheadConfig(BulkheadConfig.custom().maxConcurrentCalls(1).build())
        .threadPoolBulkheadConfig(ThreadPoolBulkheadConfig.ofDefaults()), "slowBulkhead");
}

除了配置创建的舱壁之外,您还可以自定义舱壁和线程池舱壁,在将其返回给调用者之前。为此,您可以使用 addBulkheadCustomizeraddThreadPoolBulkheadCustomizer 方法。

舱壁示例
@Bean
public Customizer<Resilience4jBulkheadProvider> customizer() {
    return provider -> provider.addBulkheadCustomizer(bulkhead -> bulkhead.getEventPublisher()
        .onCallRejected(slowRejectedConsumer)
        .onCallFinished(slowFinishedConsumer), "slowBulkhead");
}
线程池舱壁示例
@Bean
public Customizer<Resilience4jBulkheadProvider> slowThreadPoolBulkheadCustomizer() {
    return provider -> provider.addThreadPoolBulkheadCustomizer(threadPoolBulkhead -> threadPoolBulkhead.getEventPublisher()
        .onCallRejected(slowThreadPoolRejectedConsumer)
        .onCallFinished(slowThreadPoolFinishedConsumer), "slowThreadPoolBulkhead");
}

1.1.8. 舱壁属性配置

您可以在应用程序的配置属性文件中配置 ThreadPoolBulkhead 和 SemaphoreBulkhead 实例。属性配置的优先级高于 Java Customizer 配置。

resilience4j.thread-pool-bulkhead:
    instances:
        backendA:
            maxThreadPoolSize: 1
            coreThreadPoolSize: 1
resilience4j.bulkhead:
    instances:
        backendB:
            maxConcurrentCalls: 10

有关 Resilience4j 属性配置的更多信息,请参阅 Resilience4J Spring Boot 2 配置

1.1.9. 收集指标

Spring Cloud Circuit Breaker Resilience4j 包括自动配置以设置指标收集,只要正确的依赖项位于类路径中即可。要启用指标收集,您必须包含 org.springframework.boot:spring-boot-starter-actuatorio.github.resilience4j:resilience4j-micrometer。有关这些依赖项存在时生成的指标的更多信息,请参阅 Resilience4j 文档

您不必直接包含 micrometer-core,因为它由 spring-boot-starter-actuator 引入

1.2. 配置 Spring Retry 断路器

Spring Retry 为 Spring 应用程序提供声明式重试支持。该项目的一个子集包括实现断路器功能的能力。Spring Retry 通过组合其 CircuitBreakerRetryPolicy有状态重试 来提供断路器实现。使用 Spring Retry 创建的所有断路器都将使用 CircuitBreakerRetryPolicyDefaultRetryState 创建。这两个类都可以使用 SpringRetryConfigBuilder 进行配置。

1.2.1. 默认配置

要为所有断路器提供默认配置,请创建一个 Customizer bean,该 bean 传递 SpringRetryCircuitBreakerFactoryconfigureDefault 方法可用于提供默认配置。

@Bean
public Customizer<SpringRetryCircuitBreakerFactory> defaultCustomizer() {
    return factory -> factory.configureDefault(id -> new SpringRetryConfigBuilder(id)
        .retryPolicy(new TimeoutRetryPolicy()).build());
}

1.2.2. 指定断路器配置

与提供默认配置类似,您可以创建一个 Customizer bean,该 bean 传递 SpringRetryCircuitBreakerFactory

@Bean
public Customizer<SpringRetryCircuitBreakerFactory> slowCustomizer() {
    return factory -> factory.configure(builder -> builder.retryPolicy(new SimpleRetryPolicy(1)).build(), "slow");
}

除了配置创建的断路器之外,您还可以自定义断路器,在将其返回给调用者之前。为此,您可以使用 addRetryTemplateCustomizers 方法。这对于向 RetryTemplate 添加事件处理程序很有用。

@Bean
public Customizer<SpringRetryCircuitBreakerFactory> slowCustomizer() {
    return factory -> factory.addRetryTemplateCustomizers(retryTemplate -> retryTemplate.registerListener(new RetryListener() {

        @Override
        public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {
            return false;
        }

        @Override
        public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {

        }

        @Override
        public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {

        }
    }));
}

2. 构建

2.1. 基本编译和测试

要构建源代码,您需要安装 JDK 17。

Spring Cloud 使用 Maven 进行大多数与构建相关的活动,并且您应该能够通过克隆您感兴趣的项目并键入以下内容来快速入门

$ ./mvnw install
您也可以自己安装 Maven(>=3.3.3)并在以下示例中使用 mvn 命令代替 ./mvnw。如果您这样做,您可能还需要添加 -P spring,如果您的本地 Maven 设置不包含 Spring 预发布工件的存储库声明。

请注意,您可能需要增加 Maven 可用的内存量,方法是设置一个名为 MAVEN_OPTS 的环境变量,其值为类似 -Xmx512m -XX:MaxPermSize=128m 的字符串。我们尝试在 .mvn 配置中涵盖这一点,因此,如果您发现需要进行此操作才能使构建成功,请提交工单以将设置添加到源代码管理中。

需要中间件(例如 Redis)进行测试的项目通常要求安装并运行本地 [Docker](www.docker.com/get-started) 实例。

2.2. 文档

spring-cloud-build 模块具有一个“docs”配置文件,如果启用它,它将尝试从 src/main/asciidoc 构建 Asciidoc 源文件。在此过程中,它将查找 README.adoc 并通过加载所有包含文件来处理它,但不会解析或渲染它,只是将其复制到 ${main.basedir}(默认为 $/tmp/releaser-1706275114670-0/spring-cloud-circuitbreaker/docs,即项目的根目录)。如果 README 中有任何更改,它将在 Maven 构建后显示为正确位置的已修改文件。只需提交并推送更改即可。

2.3. 代码操作

如果您没有 IDE 偏好,我们建议您在处理代码时使用 Spring Tools SuiteEclipse。我们使用 m2eclipse Eclipse 插件来支持 Maven。只要其他 IDE 和工具使用 Maven 3.3.3 或更高版本,它们也应该可以正常工作。

2.3.1. 激活 Spring Maven 配置文件

Spring Cloud 项目需要激活 'spring' Maven 配置文件才能解析 Spring 里程碑和快照存储库。使用您首选的 IDE 设置此配置文件为活动状态,否则可能会遇到构建错误。

2.3.2. 使用 m2eclipse 导入到 Eclipse 中

我们建议在使用 Eclipse 时使用 m2eclipse Eclipse 插件。如果您尚未安装 m2eclipse,可以在“Eclipse 市场”中找到它。

较旧版本的 m2e 不支持 Maven 3.3,因此在将项目导入到 Eclipse 后,您还需要告诉 m2eclipse 对项目使用正确的配置文件。如果您看到许多与项目中的 POM 相关的不同错误,请检查您是否安装了最新版本。如果无法升级 m2e,请将“spring”配置文件添加到您的 settings.xml 中。或者,您可以将父 POM 的“spring”配置文件中的存储库设置复制到您的 settings.xml 中。

2.3.3. 不使用 m2eclipse 导入到 Eclipse 中

如果您不想使用 m2eclipse,可以使用以下命令生成 Eclipse 项目元数据

$ ./mvnw eclipse:eclipse

生成的 Eclipse 项目可以通过从“文件”菜单中选择“导入现有项目”来导入。

3. 贡献

Spring Cloud 在非限制性 Apache 2.0 许可证下发布,并遵循非常标准的 Github 开发流程,使用 Github 跟踪器来处理问题并将拉取请求合并到主分支。如果您想做出贡献,即使是很小的贡献,也请不要犹豫,但请遵循以下准则。

3.1. 签署贡献者许可协议

在我们接受非微不足道的补丁或拉取请求之前,我们需要您签署 贡献者许可协议。签署贡献者协议不会授予任何人对主存储库的提交权限,但它确实意味着我们可以接受您的贡献,如果您这样做,您将获得作者署名。可能会要求活跃的贡献者加入核心团队,并获得合并拉取请求的能力。

3.2. 行为准则

本项目遵循贡献者公约 行为准则。参与本项目即表示您同意遵守此准则。请将不可接受的行为报告给 [email protected]

3.3. 代码规范和维护

这些都不是拉取请求的必要条件,但它们都会有所帮助。它们也可以在原始拉取请求之后但在合并之前添加。

  • 使用 Spring Framework 代码格式规范。如果您使用 Eclipse,则可以使用 Spring Cloud Build 项目中的 eclipse-code-formatter.xml 文件导入格式化程序设置。如果使用 IntelliJ,则可以使用 Eclipse Code Formatter Plugin 导入相同的文件。

  • 确保所有新的 .java 文件都具有简单的 Javadoc 类注释,至少包含一个标识您的 @author 标签,最好至少包含一段关于该类的作用的文字。

  • 将 ASF 许可证头注释添加到所有新的 .java 文件中(从项目中的现有文件中复制)。

  • 如果您对 .java 文件进行了实质性修改(不仅仅是美化更改),请将自己添加为 @author

  • 添加一些 Javadoc,如果更改了命名空间,则添加一些 XSD 文档元素。

  • 一些单元测试也会有很大帮助——总得有人去做。

  • 如果没有人使用您的分支,请将其重新关联到当前的主分支(或主项目中的其他目标分支)。

  • 在编写提交消息时,请遵循 这些约定,如果您正在修复现有问题,请在提交消息末尾添加 Fixes gh-XXXX(其中 XXXX 是问题编号)。

3.4. Checkstyle

Spring Cloud Build 带有一组 Checkstyle 规则。您可以在 spring-cloud-build-tools 模块中找到它们。模块下最值得注意的文件是

spring-cloud-build-tools/
└── src
    ├── checkstyle
    │   └── checkstyle-suppressions.xml (3)
    └── main
        └── resources
            ├── checkstyle-header.txt (2)
            └── checkstyle.xml (1)
1 默认 Checkstyle 规则
2 文件头设置
3 默认抑制规则

3.4.1. Checkstyle 配置

Checkstyle 规则**默认情况下处于禁用状态**。要将 Checkstyle 添加到您的项目中,只需定义以下属性和插件。

pom.xml
<properties>
<maven-checkstyle-plugin.failsOnError>true</maven-checkstyle-plugin.failsOnError> (1)
        <maven-checkstyle-plugin.failsOnViolation>true
        </maven-checkstyle-plugin.failsOnViolation> (2)
        <maven-checkstyle-plugin.includeTestSourceDirectory>true
        </maven-checkstyle-plugin.includeTestSourceDirectory> (3)
</properties>

<build>
        <plugins>
            <plugin> (4)
                <groupId>io.spring.javaformat</groupId>
                <artifactId>spring-javaformat-maven-plugin</artifactId>
            </plugin>
            <plugin> (5)
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-checkstyle-plugin</artifactId>
            </plugin>
        </plugins>

    <reporting>
        <plugins>
            <plugin> (5)
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-checkstyle-plugin</artifactId>
            </plugin>
        </plugins>
    </reporting>
</build>
1 Checkstyle 错误时构建失败
2 Checkstyle 违规时构建失败
3 Checkstyle 也分析测试源代码
4 添加 Spring Java Format 插件,该插件将重新格式化您的代码以通过大多数 Checkstyle 格式规则
5 将 Checkstyle 插件添加到您的构建和报告阶段

如果您需要抑制某些规则(例如,行长需要更长),那么您只需在 ${project.root}/src/checkstyle/checkstyle-suppressions.xml 下定义一个包含您的抑制的文件即可。示例

projectRoot/src/checkstyle/checkstyle-suppresions.xml
<?xml version="1.0"?>
<!DOCTYPE suppressions PUBLIC
        "-//Puppy Crawl//DTD Suppressions 1.1//EN"
        "https://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
<suppressions>
    <suppress files=".*ConfigServerApplication\.java" checks="HideUtilityClassConstructor"/>
    <suppress files=".*ConfigClientWatch\.java" checks="LineLengthCheck"/>
</suppressions>

建议将 ${spring-cloud-build.rootFolder}/.editorconfig${spring-cloud-build.rootFolder}/.springformat 复制到您的项目中。这样,将应用一些默认的格式规则。您可以通过运行以下脚本执行此操作

$ curl https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/.editorconfig -o .editorconfig
$ touch .springformat

3.5. IDE 设置

3.5.1. Intellij IDEA

为了设置 Intellij,您应该导入我们的编码约定、检查配置文件并设置 Checkstyle 插件。以下文件可以在 Spring Cloud Build 项目中找到。

spring-cloud-build-tools/
└── src
    ├── checkstyle
    │   └── checkstyle-suppressions.xml (3)
    └── main
        └── resources
            ├── checkstyle-header.txt (2)
            ├── checkstyle.xml (1)
            └── intellij
                ├── Intellij_Project_Defaults.xml (4)
                └── Intellij_Spring_Boot_Java_Conventions.xml (5)
1 默认 Checkstyle 规则
2 文件头设置
3 默认抑制规则
4 Intellij 的项目默认设置,应用大多数 Checkstyle 规则
5 Intellij 的项目样式约定,应用大多数 Checkstyle 规则
Code style
图 1. 代码样式

转到 文件设置编辑器代码样式。在那里点击 方案 部分旁边的图标。在那里,点击 导入方案 值并选择 Intellij IDEA 代码样式 XML 选项。导入 spring-cloud-build-tools/src/main/resources/intellij/Intellij_Spring_Boot_Java_Conventions.xml 文件。

Code style
图 2. 检查配置文件

转到 文件设置编辑器检查。在那里点击 配置文件 部分旁边的图标。在那里,点击 导入配置文件 并导入 spring-cloud-build-tools/src/main/resources/intellij/Intellij_Project_Defaults.xml 文件。

Checkstyle

要使 Intellij 与 Checkstyle 协同工作,您必须安装 Checkstyle 插件。建议您还安装 Assertions2Assertj 以自动转换 JUnit 断言

Checkstyle

转到 文件设置其他设置Checkstyle。在那里点击 配置文件 部分中的 + 图标。在那里,您必须定义应从哪里获取 Checkstyle 规则。在上图中,我们从克隆的 Spring Cloud Build 存储库中获取了规则。但是,您可以指向 Spring Cloud Build 的 GitHub 存储库(例如,对于 checkstyle.xmlraw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-build-tools/src/main/resources/checkstyle.xml)。我们需要提供以下变量

请记住将 扫描范围 设置为 所有源代码,因为我们对生产和测试源代码应用 Checkstyle 规则。

3.6. 重复查找器

Spring Cloud Build 附带了 basepom:duplicate-finder-maven-plugin,它可以标记 Java 类路径上重复和冲突的类和资源。

3.6.1. 重复查找器配置

重复查找器**默认情况下处于启用状态**,并在 Maven 构建的 verify 阶段运行,但只有在您将 duplicate-finder-maven-plugin 添加到项目 pom.xmlbuild 部分时,它才会在您的项目中生效。

pom.xml
<build>
    <plugins>
        <plugin>
            <groupId>org.basepom.maven</groupId>
            <artifactId>duplicate-finder-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

对于其他属性,我们已设置了插件文档 中列出的默认值

您可以轻松地通过设置以duplicate-finder-maven-plugin为前缀的所选属性的值来覆盖它们。例如,将duplicate-finder-maven-plugin.skip设置为true以跳过构建中的重复项检查。

如果您需要在设置中添加ignoredClassPatternsignoredResourcePatterns,请确保在项目的插件配置部分中添加它们。

<build>
    <plugins>
        <plugin>
            <groupId>org.basepom.maven</groupId>
            <artifactId>duplicate-finder-maven-plugin</artifactId>
            <configuration>
                <ignoredClassPatterns>
                    <ignoredClassPattern>org.joda.time.base.BaseDateTime</ignoredClassPattern>
                    <ignoredClassPattern>.*module-info</ignoredClassPattern>
                </ignoredClassPatterns>
                <ignoredResourcePatterns>
                    <ignoredResourcePattern>changelog.txt</ignoredResourcePattern>
                </ignoredResourcePatterns>
            </configuration>
        </plugin>
    </plugins>
</build>