Spring Boot生产中的16个最佳实践 - hubian


Spring Boot 是最流行的用于开发微服务的 Java 框架。在本文中,将重点介绍特定于 Spring Boot 的实践(并且大多数情况下,也适用于 Spring 项目)。下面列出了最佳实践,排名不分先后。

1.使用自定义BOM维护第三方依赖
这种做法是基于我在实际项目中的经验。
Spring Boot 项目本身使用并集成了大量的开源项目,这有助于我们维护这些第三方依赖。但是有些是不包含在实际项目使用中的,这就需要我们在项目中维护版本。如果一个大型项目包含很多未开发的模块,维护起来会非常麻烦。
怎么做?事实上,Spring IO Platform 就是这样做的。它本身是 Spring Boot 的一个子项目,维护着其他第三方开源库。我们可以借鉴Spring IO Platform编写自己的基础项目platform-b​​om,所有业务模块项目都要以BOM的形式引入。这样,在升级第三方依赖的时候,只需要升级这个依赖的版本即可。

<dependencyManagement> 
    <dependencies> 
        <dependency> 
            <groupId>io.spring.platform</groupId> 
            <artifactId>platform-b​​om</artifactId> 
            <version>Cairo-SR3</version> 
            <type>pom</type> 
            <scope>import</scope> 
        </dependency> 
    </dependencies> 
</dependencyManagement>

2.使用自动配置
Spring Boot 的一个主要特性是使用自动配置。这是 Spring Boot 的一部分,可简化您的代码并使其工作。当在类路径上检测到特定的 jar 文件时,会激活自动配置。
使用它的最简单方法是依赖 Spring Boot Starters。因此,如果您想与 Redis 集成,您可以首先包括:

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

如果你想与 MongoDB 集成,你需要这个:
<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-data-mongodb</artifactId> 
</dependency>

在这些启动器的帮助下,这些繁琐的配置得到了很好的集成和协同工作,并且都经过了测试和验证。这对于避免可怕的 Jar 地狱非常有帮助。

某些配置类可以通过使用以下注释属性从自动配置中排除:

@EnableAutoConfiguration(exlude = {ClassNotToAutoconfigure.class})

但只有在绝对必要时才应该这样做。

3.使用Spring Initializer启动一个新的Spring Boot项目
这个最佳实践来自 Josh Long(Spring Advocate,@starbuxman)。
Spring Initializer 提供了一种超级简单的方法来创建新的 Spring Boot 项目并根据您的需要加载可能的依赖项。
https://start.spring.io/
使用 Initializer 创建应用程序可确保您获得与 Spring 自动配置一起使用的经过测试和验证的依赖项。您甚至可能会发现一些您可能不知道的新集成。

4.考虑为常见的组织问题创建自己的自动配置
这个也来自 Josh Long(Spring Advocate,@starbuxman)——这种做法适用于高级用户。
如果您在一个严重依赖 Spring Boot 的公司或团队工作并且有共同的问题需要解决,那么您可以创建自己的自动配置。
这项任务的工作量很大,因此您需要考虑收益何时值得投资。维护单个自动配置比维护多个略有不同的自定义配置更容易。
如果将此提供的 Spring Boot 配置作为开源库发布,将大大简化成千上万用户的配置工作。

5.正确设计代码目录结构
尽管您有很大的自由度,但有一些基本规则值得遵循来设计您的源代码结构。
避免使用默认包。确保所有东西(包括你的入口点)都在一个命名良好的包中,这样你就可以避免与装配和组件扫描相关的意外;
将Application.java(应用程序的入口类)保存在顶级源目录中;
我建议将控制器和服务放在面向功能的模块中,但这是可选的。一些非常优秀的开发人员建议将所有控制器放在一起。不管怎样,坚持一种风格!
(SpringBoot六边形架构案例)

6. 保持@Controller 简洁和专注
控制器应该很简单。您可以在此处阅读 GRASP 中的控制器模式部分。您希望控制器充当协调者和委托人,而不是执行实际的业务逻辑。以下是主要做法:

  • 1.控制器应该是无状态的!控制器默认是单例的,任何状态都可能导致很多问题;
  • 2.控制器不应该执行业务逻辑,而是依赖委托;
  • 3.控制器应该处理应用程序的HTTP层,这不应该传递给服务;
  • 4. 控制器应该围绕用例/业务能力来设计。

要深入了解此内容,您需要了解有关设计 REST API 的最佳实践的更多信息。无论您是否想使用 Spring Boot,都值得学习。

7. 围绕业务功能构建@Service
服务是 Spring Boot 的另一个核心概念。我发现最好围绕业务功能/领域/用例(无论您想如何称呼它们)来构建服务。
在应用程序中设计名称为 , 的服务比设计名称为AccountService, ,UserService的服务更合适。Payment ServiceDatabaseServiceValidationServiceCalculationService
您可以决定在 Controller 和 Service 之间使用一对一的映射,这将是理想的。但这并不意味着服务不能互相调用!

8.使数据库独立于核心业务逻辑
之前我不确定如何最好地处理 Spring Boot 中的数据库交互。阅读 Robert C. Martin 的“清晰clean架构”后,我更清楚了。
您希望您的数据库逻辑与服务分离。理想情况下,您不希望服务知道它正在与哪个数据库通信,这需要一些抽象来封装对象持久性。
Robert C. Martin 强烈指出您的数据库是一个“细节”,这意味着您的应用程序不与特定数据库耦合。过去很少有人会切换数据库,我注意到使用 Spring Boot 和现代微服务开发可以让事情变得更快。
(SpringBoot六边形架构案例)

9. 将业务逻辑排除在 Spring Boot 代码之外
考虑到“清晰clean架构”的教训,您还应该保护您的业务逻辑。将各种 Spring Boot 代码混合在一起非常诱人……不要这样做。如果您能够抵制诱惑,您将保持您的业务逻辑可重用。
部分服务通常会变成图书馆。无需从代码中删除大量 Spring 注释即可更轻松地创建。

10.推荐构造函数注入
这种做法来自 Phil Webb(Spring Boot 项目负责人,@phillip_webb)。
使您的业务逻辑不受 Spring Boot 代码影响的一种方法是使用构造函数注入。不仅@Autowired构造函数上的注解是可选的,而且它还使得在没有 Spring 的情况下实例化 bean 变得容易。

11、熟悉并发模型
在 Spring Boot 中,Controller 和 Service 默认是单例的。如果您不小心,这会引入可能的并发问题。您通常还要处理有限的线程池。请熟悉这些概念。

12、加强配置管理的外部化
这超越了 Spring Boot,尽管这是人们开始创建多个类似服务时的常见问题......
您可以手动处理 Spring 应用程序的配置。如果您正在处理多个 Spring Boot 应用程序,则需要使配置管理更加强大。

我推荐两种主要方法:

  • 1.使用配置服务器,如Spring Cloud Config;
  • 2. 将所有配置存储在环境变量中(可以基于git仓库进行配置)。

这些选项中的任何一个(第二个选项更多一些)都要求您在 DevOps 中做更少的工作,但这在微服务世界中很常见。

13.提供全局异常处理
您确实需要一种一致的方式来处理异常。Spring Boot 提供了两种主要方法:

  • 1.你应该使用HandlerExceptionResolver来定义一个全局的异常处理策略;
  • 2.还可以在控制器中添加@ExceptionHandler注解,在某些特定场景下可能会有用。

14.使用日志框架
您可能已经意识到这一点,但您应该使用 Logger 进行日志记录,而不是使用 System.out.println() 手动进行。这在 Spring Boot 中很容易完成,几乎不需要配置。只需获取该类的记录器实例:

Logger logger = LoggerFactory.getLogger(MyClass.class);

这很重要,因为它允许您根据需要设置不同的日志记录级别。

15. 测试你的代码
这不是 Spring Boot 特有的,但需要提醒一下——测试你的代码!如果您不编写测试,那么您从一开始就是在编写遗留代码。
如果其他人使用您的代码库,那么更改那里的任何内容都会变得危险。当您有多个相互依赖的服务时,这可能会更加危险。
由于存在 Spring Boot 最佳实践,您应该考虑将 Spring Cloud Contract 用于您的消费者驱动的合同,这将使您与其他服务的集成更易于使用。

16. 使用测试切片让测试更容易,更专注
这种做法来自 Madhura Bhave(Spring 开发人员,@madhurabhave23)。
使用 Spring Boot 测试代码可能会很棘手——您需要初始化数据层、连接大量服务、模拟事物……实际上并不难!答案是使用测试切片。
使用测试切片,您可以根据需要仅连接应用程序的一部分。这可以为您节省大量时间,并确保您的测试不与未使用的内容相关联。

总结:
感谢 Spring Boot,编写基于 Spring 的微服务从未如此简单。我希望通过这些最佳实践,您的实施过程不仅会变得更快,而且从长远来看会更加稳健和成功。祝你好运!