提高Spring Boot技能的9种方法

以下是提高 Spring Boot 技能的 9 种方法:

1. 外部化您的配置:
充分利用 Spring Boot 潜力的另一种方法是尽可能地尝试外部化您的配置,而不是对其进行硬编码。外部化您的配置将使您的应用程序更加灵活且更易于管理。

外部化配置的另一个优点是,您不需要仅仅因为一个小更改就关闭应用程序、进行更改、重新编译,然后重新部署应用程序。

以下是如何外部化您的配置
要外部化您的配置,您需要使用 application.properties 或 application.yml
– 配置您的属性:
在 application.properties 或 application.yml 文件中,使用配置的前缀指定属性:

 application.properties

app.bootstrap-servers=localhost:3000
app.client-id=digma-id
app.group-id=dgma-group
For application.yml

application.yml
app:
  bootstrap-servers: localhost:3000
  client-id: digma-id

- 创建配置属性类:

创建一个类来保存配置属性。用 @ConfigurationProperties 对其进行注解,以指定属性的前缀:

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import lombok.Data
@Data
@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties {
    private String bootstrapServer;
    private String clientId;
    private String groupId;
}

- 注入配置:

将配置属性注入到组件或服务中:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class DemoService {
    private final AppProperties appProperties;
    private final Logger logger = LoggerFactory.getLogger(DemoService.class);
    public DemoService(AppProperties appProperties) {
        this.appProperties = appProperties;
    }
    public void printConfiguration() {
        logger.info("App Name: {}", appProperties.getBootstrapServer());
        logger.info(
"Version: {}", appProperties.getClientId());
        logger.info(
"Version: {}", appProperties.getGroupId());
    }
}

2.你需要保持你的控制器精简
充分利用 Spring Boot 潜力的另一种方法是确保控制器保持精简。保持控制器精简将帮助您避免导致“肥胖控制器”反模式的做法。
什么是“脂肪控制器”反模式?
“胖控制器”反模式是一种编程模式,其中 Web 应用程序中的控制器因业务逻辑而过载,违反了关注点分离原则。当控制者承担过多的责任时,必然会出现以下问题:

  • 可维护性:大型控制器难以维护和理解。对业务逻辑的任何修改或添加都变得容易出错且复杂。
  • 可测试性:随着业务逻辑嵌入到控制器中,单独执行测试变得困难,这使得创建可靠的单元测试变得具有挑战性。
  • 可重用性:您很难在控制器中找到可重用的逻辑。如果应用程序的另一部分需要相同的逻辑,通常很难提取和重用。
  • 可读性:当控制器中有业务逻辑时,代码库的可读性就会降低。开发人员很难快速了解控制器的用途和功能。

为了避免“脂肪控制器”反模式,请遵循以下原则:
  • 无状态:默认情况下控制器是单例的,任何状态更改都可能导致很多问题。
  • 委托:您的控制器应该进行委托,这意味着它不应该执行业务逻辑,而应该依赖委托。
  • 封装:应用程序的 HTTP 层应该由控制器处理,而不应该由服务层处理。
  • 以用例为中心:确保您的控制器是围绕用例或业务领域构建的。

3. 全局处理异常
要充分利用 Spring Boot,您需要学习如何全局处理异常,这很重要,因为:

  • 它为您提供了对 HTTP 响应的细粒度控制,允许您根据异常类型返回自定义对象或响应。
  • 您可以定义应全局应用的其他配置,例如模型属性或响应。

  • 它可以防止每个控制器中出现重复的异常处理代码。您可以在 @ControllerAdvice 类中定义一次,确保采用一致且集中的异常处理方法,使我们的代码更易于维护。

要全局处理异常,您需要创建一个类并使用此注解来注释该类@ControllerAdvice(Web MVC 项目)@ControllerAdvice(Web MVC 项目)(Web API 项目)。@RestControllerAdvice 或
@ControllerAdvice 是为 Spring Boot MVC 应用程序设计的,它是一个注解,当应用于某个类时,会将其转换为全局控制器顾问程序,进而影响多个控制器。下面是 @ControllerAdvice 的样子。

@ControllerAdvice
public class GlobalControllerAdvice {
    // Exception handling, model attributes, and other configurations
}

@RestControllerAdvice 此注解扩展了 @ControllerAdvice。它专为 RESTful 网络服务而设计。您可以在响应形式为 JSON 或 XML 的应用程序中使用它。下面是它的样子。

 

@RestControllerAdvice
public class ControllerAdvice {
    @ResponseBody
    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(ResourceNotFoundException.class)
    public ServiceResponse<String>  
       handleResourceNotFoundException(ResourceNotFoundException ex) {
           return new ServiceResponse<>(ex.getMessage(), false);
    }

@ExceptionHandler 此注解用于处理控制器抛出的特定异常。此注解用于在控制器或类中声明使用 @ControllerAdvice 注解的方法。通过该注解,您可以自定义应用程序的行为。下面是它的外观。

@Service
@RequiredArgsConstructor
public class UserService {
    
    private final UserRepository userRepository;
    var response = new ServiceResponse<UserDto>();
        var user = userRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("User", "id", id));
        UserDto userDto = mapper.toDto(user);
        response.setData(userDto, true);
        log.info(
"Fetched user => {}", userDto);
        return response;
}

在 Spring Boot 应用程序中使用 @ControllerAdvice 或 @RestControllerAdvice 允许您在 Spring Boot 应用程序的多个控制器中集中异常处理和其他配置。

4.利用延迟初始化
SpringApplication 允许您作为开发人员延迟初始化您的 Spring Boot 应用程序。当启用延迟初始化时,bean 将在需要时创建,而不是在应用程序启动期间创建。启用延迟初始化可减少应用程序启动所需的时间。

延迟初始化会导致许多与 Web 相关的 Bean 在收到 HTTP 请求之前不会进行初始化。

延迟初始化的缺点是它延迟了应用程序问题的发现。如果您延迟初始化配置错误的 bean,则该 bean 在启动期间不会发生故障,并且只有在初始化该 bean 时才会出现问题。

您需要确保 JVM 有足够的内存来容纳应用程序的所有 Bean,而不仅仅是那些在启动期间初始化的 Bean。在启用延迟初始化之前,您需要微调 JVM 的堆大小。

可以使用以下方式以编程方式启用延迟初始化:

  • SpringApplicationBuilder 上的方法lazyInitialization
  • SpringApplication 上的 setLazyInitialization 方法。
  • spring.main.lazy-initialization 属性

5.充分利用STARTER POM
就像 AutoConfiguration 消除了配置通用功能的痛苦一样,Starter POM 消除了在以下环境中查找和配置通用依赖项的痛苦您的项目。
spring-boot-starter-data-jpa 是使用 Spring Data JPA 的入门工具。它包括以下编译的依赖项:

  • spring-boot-starter-jdbc:此启动器包含 JDBC 必需的库。
  • hibernate-core:这是 Hibernate 的主要库,它是一个对象关系映射 (ORM) 解决方案。
  • spring-data-jpa:此库提供核心 Spring Data JPA 功能。
  • spring-boot-starter-aop:该库支持 Spring Boot 中的面向方面编程,解决了横切问题,实现更简洁、模块化的代码。
  • spring-aspects: 当您需要 AspectJ 提供的高级功能(例如编织到第三方库)时,通常会使用此库。

因此,您无需搜索并添加所有这些依赖项并担心它们的兼容版本,只需添加一个 Starter POM — spring-boot-starter-data-jpa

6.使用SPRING BOOT CLI
Spring Boot CLI是Spring Boot团队提供的命令行工具。该工具允许您创建 Spring Boot Web 应用程序。显然,您需要安装它才能使用它,以下是安装方法。

On Mac:
$ sdk install springboot 

On Windows:
> scoop bucket add extras
> scoop install spring boot 

7. 掌握您偏好的构建工具
充分利用 Spring Boot 的一种方法是掌握您喜欢的构建工具。如果您更喜欢 Maven 或 Gradle 构建工具,则必须掌握它,了解其缺点,并且同样知道如何减轻您偏好的构建工具的缺点。
Maven 构建工具的一个常见抱怨是速度慢,缓解这一缺点的最佳方法是安装和使用Mvnd
Gradle 构建工具的一个常见缺点是方法名称一直在变化,因此缓解这一问题的唯一方法是让自己及时了解每个新版本的 Gradle 附带的新功能和已弃用的功能。

8. 认真对待可观察性
可观察性基本上是使用日志、指标和跟踪等外部输出来测量应用程序内部状态的过程。
Spring Boot 应用程序中的可观察性

执行器端点
确保充分发挥 Spring Boot 潜力的一种方法是使用 Spring Boot 执行器。该库允许您深入了解有关应用程序的操作信息。
一旦该库位于类路径上,默认情况下您就可以使用多个端点。
将 spring-boot-actuator 依赖项添加到包管理器以启用 spring-boot 执行器。

For Maven

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

For Gradle

dependencies {
   implementation 'org.springframework.boot:spring-boot-starter-actuator'
}

您需要知道的一点是,Actuator 的大部分端点都已禁用,只剩下 /health 和 /info 这两个端点处于启用状态。

要启用所有端点,请转到应用程序属性文件(application.properties)或应用程序文件(application.yml),然后添加以下内容

For application.properties
management.endpoints.web.exposure.include=*


For application.yml
management:
  endpoints:
    web:
      exposure:
        include: "*"


一些有趣的执行器端点

  • /health: 此端点向您显示应用程序的基本健康信息。它是最常用的端点之一,并且默认情况下公开。

您可以将此端点与外部监控工具(例如 Grafana、Prometheus)集成,以便在应用程序的运行状况发生变化时收到警报。
  • /info:此端点将向您显示应用程序信息。当您想要公开应用程序名称、版本和任何自定义属性等详细信息时,这非常有用。

从该端点获取的详细信息可以帮助其他开发人员或系统了解您的应用程序上下文。
  • /beans:此端点向您显示应用程序中所有 Spring bean 的完整列表。 

当您想要分析 bean 依赖性、调试依赖注入问题并尝试了解应用程序的结构时,这会派上用场。
  • /loggers:此端点向您显示应用程序中记录器的配置。 

使用此端点,您可以动态调整应用程序日志级别,启用/禁用特定包的日志记录。当您想要在运行时进行实时调试和故障排除时,这会派上用场。
  • /httptrace:此端点显示应用程序的 HTTP 跟踪信息。默认情况下,它仅显示最后 100 个 HTTP 请求-响应交换。

此端点对于诊断和分析应用程序的 HTTP 流量的行为非常有用,并帮助您识别和解决问题。
  • /metrics:此端点是应用程序指标。这些指标可以包括 JVM 内存使用情况、HTTP 请求计数等。此端点需要依赖于 micrometer-core。

此端点可帮助您监控应用程序的性能、检测异常并就如何优化或调整基础设施做出明智的决策。
  • /shutdown:当您到达此端点时,它将正常关闭您的 Spring Boot 应用程序。这是一项危险的操作,因此应妥善保护此端点。

谨慎使用此端点;在需要正常关闭的受控环境中使用此端点。
  • /env:此端点显示应用程序环境中定义的属性。这些属性可以包括系统属性、环境变量以及 application.properties 或 application.yml 中的属性。

该端点将帮助您了解应用程序的运行时环境、检查配置值、诊断和分析与配置相关的问题。
  • /mappings:此端点显示应用程序中所有 @RequestMapping 路径的列表。

通过此端点,您可以快速查看控制器的映射,这对于 API 文档来说非常方便。
  • /configprops:此端点显示整理的 @ConfigurationProperties 列表。

您可以查看属性的结构,找到错误配置,并确保您的应用程序使用正确的配置。
Spring Boot Actuator 通过 /actuator/health、/actuator/metrics 和 /actuator/env 等端点提供对应用程序内部结构的关键洞察。这些端点提供健康状态、详细指标和环境属性。

使Micrometer 收集指标
Micrometer 是一种多功能指标实用程序,支持各种监控系统,例如 Prometheus、Datadog 等。它提供了一系列仪器类型,是应用指标的首选解决方案,为选择监控工具提供了灵活性。

Spring Boot 中的日志记录Spring Boot 的日志记录依赖于 Commons Logging,但仍可适应不同的日志实现。它提供了 Logback、Log4J2 和 Java Util Logging 的默认配置,简化了日志记录设置和兼容性。

使用 OpenTelemetry 进行分布式跟踪
OpenTelemetry 在基于微服务的应用程序中提供端到端跟踪和可观察性。 Spring Boot 与 OpenTelemetry 无缝集成,支持代理检测和微米跟踪。使用生态系统工具引导您的可观察性并使可观察性数据变得有意义

digma.ai 等持续反馈工具可以使从不可观察性到完全可观察性的过程变得更加容易,但更重要的是,确保可观察性数据变得有影响力,而不仅仅是漂亮的仪表板。 Digma 和类似工具可以分析可观察性数据对您的代码意味着什么,以检测常见的反模式和问题,并在编码时为您提供反馈。

9. 测试,测试,测试
有了 Spring Boot,编写单元测试和集成测试就不再那么令人头疼,而是变得更令人满意。
Spring Boot 是开发具有强大测试功能的应用程序的绝佳选择。出于以下原因:

  • Spring Boot 与 JUnit、Mockito 和 Spring Test 等流行的测试框架无缝集成。
  • Spring Boot 提供了广泛的测试注释,包括 @SpringBootTest、@DataJpaTest 和 @WebMvcTest,它们有助于为特定类型的测试配置应用程序上下文,从而简化流程。
  •  Spring Boot 允许您利用 Spring 框架的庞大生态系统,例如用于安全测试的 Spring Security 和用于数据库相关测试的 Spring Data。
  • Spring Boot 对 Mockito 等模拟框架的支持使您可以访问用于生成测试数据的实用程序,从而使您能够构建更强大的应用程序。
  • Spring Boot 与 TestContainers 很好地集成,可以快速跟踪您的集成测试。
  • 如果您正在构建分布式应用程序,则测试是不可协商的。

测试驱动开发发生的一件伟大的事情是测试容器的使用。该开发相当新,值得庆幸的是 Spring Boot 集成了 Testcontainers。

Testcontainers 是一个功能强大的测试库,它提供简单且轻量级的一次性通用数据库实例,用于通过 Docker 容器中包装的真实服务引导集成测试。使用测试容器,您可以编写和运行与生产中使用的相同类型的服务或数据库对话的测试,而无需模拟或内存中服务。

测试容器的好处

  • 再现性:每个测试都在干净的环境中运行,因为这消除了可能由过时或冲突状态引起的任何问题。
  • 隔离:测试容器自动创建隔离的测试环境。这种隔离的环境有助于避免与外部依赖项的干扰。
  • 易于使用:TestContainers 与 JUnit、Mockito、TestNG 等流行测试框架之间无缝集成,因此降低了设置单独测试环境的复杂性这意味着您可以使用相同的环境(容器)来托管您的软件,无论您是在构建、测试还是部署您的软件在生产中的应用。