Spring Boot 最佳实践
本文翻译自国外论坛 medium,原文地址:https://medium.com/@raviyasas/spring-boot-best-practices-for-developers-3f3bdffa0090
Spring Boot 是一种广泛使用且非常流行的企业级高性能框架。以下是一些最佳实践和一些技巧,我们可以使用它们来改进 Spring Boot 应用程序并使其更加高效。这篇文章会有点长,完整读完文章需要一些时间。
1.正确的包目录风格
- 正确的包目录将有助于轻松理解代码和应用程序的流程。
- 我们可以使用有意义的包目录来构建我们的应用程序。
- 我们可以将所有控制器包含在单独的包中,将服务包含在单独的包中,将 util 类包含在单独的包中等等。这种风格在小型微服务中非常方便。
- 如果我们正在处理庞大的代码库,则可以使用基于功能模块的方法。我们可以根据我们的要求来决定。
基于类型
基于功能模块
推荐博主开源的 H5 商城项目waynboot-mall,这是一套全部开源的微商城项目,包含三个项目:运营后台、H5 商城前台和服务端接口。实现了商城所需的首页展示、商品分类、商品详情、商品 sku、分词搜索、购物车、结算下单、支付宝/微信支付、收单评论以及完善的后台管理等一系列功能。 技术上基于最新得 Springboot3.0、jdk17,整合了 MySql、Redis、RabbitMQ、ElasticSearch 等常用中间件。分模块设计、简洁易维护,欢迎大家点个 star、关注博主。
github 地址:https://github.com/wayn111/waynboot-mall
2.使用设计模式
没什么好说的,设计模式已经是现代编程中编写可维护、可扩展代码的最佳实践。
3.使用 Spring Boot starter
- 这是 Spring Boot 的一个很酷的功能。
- 我们可以非常轻松地使用启动器依赖项,而无需一一添加单个依赖项。这些入门依赖项已与所需的依赖项捆绑在一起。
- 例如,如果我们添加 spring-boot-starter-web 依赖项,默认情况下它会与 jackson、spring-core、spring-mvc 和 spring-boot-starter-tomcat 依赖项捆绑在一起。
- 所以我们不需要关心单独添加依赖项。
- 它还可以帮助我们避免版本不匹配。
4.使用生产版本的依赖项
- 始终建议使用最新的稳定 GA 版本。
- 有时它可能会因 Java 版本、服务器版本、应用程序类型等而有所不同。
- 不要使用同一包的不同版本,如果存在多个依赖项,请始终使用
<properties>
指定版本。
5.使用 Lombok
- 作为一名 Java 开发人员,我们可能听说过 Lombok 项目。
- Lombok 是一个 Java 库,可用于减少代码并允许我们使用其注释编写干净的代码。
- 例如,我们可能在某些类(如实体、请求/响应对象、dtos 等)中使用大量的 getter 和 setter 行。
- 但如果你使用 Lombok,它只是一行,你可以根据你的要求使用@Data、@Getter 或@Setter。
- 我们也可以使用 Lombok 记录器注释。推荐@Slf4j。
6.将构造函数注入与 Lombok 一起使用
- 当我们谈论依赖注入时,有两种类型。
- 一种是“构造函数注入”,另一种是“setter 注入”。除此之外,我们还可以使用非常流行的@Autowired 注释来使用“字段注入”。
- 但我们强烈建议使用构造函数注入而不是其他类型。因为它允许应用程序在初始化时初始化所有必需的依赖项。
- 这对于单元测试非常有用。
- 重要的是,我们可以使用 Lombok 的 @RequiredArgsConstructor 注释来使用构造函数注入。
7.使用 slf4j 日志
- 日志记录非常重要。
- 如果我们的应用程序在生产过程中出现问题,日志记录是找出根本原因的唯一方法。
- 因此,在添加记录器、日志消息类型、记录器级别和记录器消息之前应该仔细考虑。
- 不要使用 System.out.print()
- 建议将 Slf4j 与 Spring Boot 中默认的日志框架 logback 一起使用。
- 始终使用 slf4j 的
{}
占位符语法,避免在记录器消息中使用字符串插值。因为字符串插值会消耗更多的内存。 - 我们可以使用 Lombok @Slf4j 注释非常轻松地创建日志记录器。
- 如果我们处于微服务环境中,则可以使用 ELK 技术栈。
8.控制器仅用于路由
- 控制器专用于路由。
- 它是无状态且单身的。
- DispatcherServlet 将检查控制器上的 @RequestMapping
- 控制器是请求的最终目标,请求将交给服务层并由服务层处理。
- 业务逻辑不应位于控制器中。
9.使用 Service 层来实现业务逻辑
- 完整的 Service 层业务逻辑包含验证、缓存等。
- Service 服务与持久层通信并接收结果。
- Service 服务也是单例的。
10.避免空指针异常
- 为了避免 NullPointerException,我们可以使用 java.util 包中的 Optional。
- 我们还可以使用空安全库。例如:Apache Commons StringUtils
- 对已知对象调用 equals() 和 equalsIgnoreCase() 方法。
- 使用 valueOf() 而不是 toString()
- 使用基于 IDE 的 @NotNull 和 @Nullable 注释。
11.使用集合框架的最佳实践
- 对我们的数据集使用适当的集合。
- 将 forEach 与 Java 8 功能结合使用,并避免使用旧版 for 循环。
- 使用接口类型而不是实现。
- 使用 isEmpty() 而不是 size() 以获得更好的可读性。
- 不返回空值,可以返回空集合。
- 如果我们使用对象作为要存储在基于哈希的集合中的数据,则应重写 equals() 和 hashCode() 方法。
12.使用分页
- 这将提高应用程序的性能。
- 如果我们使用 Spring Data JPA,则 PagingAndSortingRepository 使分页的使用变得非常容易且几乎不费吹灰之力。
13.使用缓存
- 在谈论应用程序性能时,缓存是另一个重要因素。
- 默认情况下,Spring Boot 通过 ConcurrentHashMap 提供缓存,我们可以通过 @EnableCaching 注解来实现这一点。
- 如果我们对默认缓存不满意,可以使用 Redis、Hazelcast 或任何其他分布式缓存实现。
- Redis 和 Hazelcast 是内存缓存方法。我们还可以使用数据库缓存实现。
14.使用自定义异常处理程序和全局异常处理
- 这在使用大型企业级应用程序时非常重要。
- 除了一般异常之外,我们可能还会有一些场景来识别某些特定的错误情况。
- 异常顾问可以使用 @ControllerAdvice 创建,我们可以创建具有有意义细节的单独异常。
- 它将使得将来识别和调试错误变得更加容易。
15.使用自定义响应对象
- 自定义响应对象可用于返回包含某些特定数据的对象,并满足 HTTP 状态代码、API 代码、消息等要求。
- 我们可以使用构建器设计模式来创建具有自定义属性的自定义响应对象。
16.删除不必要的代码、变量、方法和类。
- 未使用的变量声明将占用一些内存。
- 删除未使用的方法、类等,因为它会影响应用程序的性能。
- 尽量避免嵌套循环,我们可以使用 map 代替。
17.使用注释
- 注释是一个很好的做法。
- 不要对一切代码发表注释。相反,我们可以使用类、函数、方法、变量等有意义的单词编写描述性代码。
- 删除注释代码、误导性注释和故事型注释。
- 我们可以使用注释进行警告,并解释一些乍一看难以理解的内容。
18.对类、方法、函数、变量和其他属性使用有意义的词语。
- 这看起来很简单,但影响却是巨大的。
- 始终使用正确的有意义且可搜索的命名约定以及正确的大小写。
- 通常,我们在声明类、变量和常量时使用名词或短语。例如:字符串 firstName,const isValid
- 我们可以使用带有形容词的动词和短语来表示函数和方法。例如:readFile()、sendData()
- 避免使用缩写变量名和意图揭示的名称。例如: int i;字符串 getExUsr;
- 如果我们有意义地使用此功能,则可以减少声明注释行。由于它具有有意义的名称,新开发人员可以通过阅读代码轻松理解。
19.使用正确的大小写进行声明
有许多不同的大小写,如大写、小写、驼峰命名、帕斯卡命名、蛇命名、大蛇式命名、短横线命名等。
但我们需要确定哪个案例专用于哪个变量。
通常我会遵循如下方式,
类 — 帕斯卡命名
方法和变量 — 驼峰命名
常量 — 大蛇式命名
数据库相关字段 — 短横线命名
这只是一个例子,它可能与我们在公司遵循的标准不同。
20.简单点
- 始终尝试编写简单、可读的代码。
- 同样简单的逻辑可以用不同的方式实现,但是如果不可读或不理解就很难理解。
- 有时复杂的逻辑会消耗更多的内存。
- 编写代码时尝试使用 KISS、DRY 和 SOLID 原则。我将在以后的文章中解释这一点。
21.使用通用的代码格式样式
- 格式样式因开发人员而异。编码风格的改变也被认为是一种改变,并且会使代码合并变得非常困难。
- 为了避免这种情况,团队可以采用通用的编码格式。
22.使用 SonarLint 插件
- 这对于识别小错误和最佳实践非常有用,以避免不必要的错误和代码质量问题。
- 我们可以将插件安装到我们最喜欢的 IDE 中。
最后
至此本文讲解内容到此完毕感谢阅读,希望本文能对你有所帮助。
关注公众号【waynblog】每周分享技术干货、开源项目、实战经验、高效开发工具等,您的关注将是我的更新动力!
Spring Boot 最佳实践的更多相关文章
- Spring Boot 2 实践记录之 封装依赖及尽可能不创建静态方法以避免在 Service 和 Controller 的单元测试中使用 Powermock
在前面的文章中(Spring Boot 2 实践记录之 Powermock 和 SpringBootTest)提到了使用 Powermock 结合 SpringBootTest.WebMvcTest ...
- Spring Boot 2 实践记录之 使用 ConfigurationProperties 注解将配置属性匹配至配置类的属性
在 Spring Boot 2 实践记录之 条件装配 一文中,曾经使用 Condition 类的 ConditionContext 参数获取了配置文件中的配置属性.但那是因为 Spring 提供了将上 ...
- Spring Boot 2 实践记录之 MyBatis 集成的启动时警告信息问题
按笔者 Spring Boot 2 实践记录之 MySQL + MyBatis 配置 中的方式,如果想正确运行,需要在 Mapper 类上添加 @Mapper 注解. 但是加入此注解之后,启动时会出现 ...
- Java 小记 — Spring Boot 的实践与思考
前言 本篇随笔用于记录我在学习 Java 和构建 Spring Boot 项目过程中的一些思考,包含架构.组件和部署方式等.下文仅为概要,待闲时逐一整理为详细文档. 1. 组件 开源社区如火如荼,若在 ...
- Spring Boot 2 实践记录之 Redis 及 Session Redis 配置
先说 Redis 的配置,在一些网上资料中,Spring Boot 的 Redis 除了添加依赖外,还要使用 XML 或 Java 配置文件做些配置,不过经过实践并不需要. 先在 pom 文件中添加 ...
- Spring JDBC最佳实践(1)
原文地址:https://my.oschina.net/u/218421/blog/38513 Spring提供了两种使用JDBC API的最佳实践,一种是以JdbcTemplate为核心的基于Tem ...
- Spring Validation最佳实践及其实现原理,参数校验没那么简单!
之前也写过一篇关于Spring Validation使用的文章,不过自我感觉还是浮于表面,本次打算彻底搞懂Spring Validation.本文会详细介绍Spring Validation各种场景下 ...
- Spring Boot分布式系统实践【1】-架构设计
前言 [第一次尝试去写一个系列,肯定会有想不到的地方,欢迎大家留言指正] 本系列将介绍如果从零构建一套分布式系统.同时也是对自己过去工作的一个梳理过程. 本文先整理出构建系统的主要技术选型,以及技术框 ...
- Spring Boot 入门实践
一.Eclipse配置Spring Boot环境 1.查看eclipse版本信息: 2.登录:http://spring.io/tools/sts/all 看eclipse对应的插件版本对应的ecli ...
- Spring Boot 2 实践记录之 Powermock 和 SpringBootTest
由于要代码中使用了 Date 类生成实时时间,单元测试中需要 Mock Date 的构造方法,以预设其行为,这就要使用到 PowerMock 在 Spring Boot 的测试套件中,需要添加 @Ru ...
随机推荐
- C#使用词嵌入向量与向量数据库为大语言模型(LLM)赋能长期记忆实现私域问答机器人落地
本文将探讨如何使用c#开发基于大语言模型的私域聊天机器人落地.大语言模型(Large Language Model,LLM 这里主要以chatgpt为代表的的文本生成式人工智能)是一种利用深度学习方法 ...
- TextArea设置MaxLength的代码(未测试在不同浏览器下的兼容性)
function SetTextAreaMaxLength(controlId,length) { // JScript File for TextArea // Keep user from ent ...
- [Flink] Flink Job运行状态正常,但日志中偶报“FlinkException: The file LOG does not exist on the TaskExecutor.”
0 序言 Flink : 1.12 job start running time : 2022-12-27 17:40:47 problem throw time : 2023-05-11 16:41 ...
- 2020-10-25:go中channel的close流程是什么?
福哥答案2020-10-25:
- Linux:论如何在虚拟机上挂载多个镜像?
欢迎来到千汐 博客名称:千秋云染博客网址:https://www.cnblogs.com/skyrainmom 寄语:在混乱不堪的世界里你只管前行,时间替会证明一切 world cookie 我可 ...
- react-router-dom 6.0路由详解
React react-router-dom 6.0路由使用 由于react路由版本的更新迭代,记录路由知识点 新react-router-dom地址,点击查看详情. 下面为使用的例子 Install ...
- 小程序使用echarts 在一个页面打印多个饼图的坑
一.下载echarts微信版 下载地址:https://github.com/ecomfe/echarts-for-weixin 或者直接云盘下载 https://pan.baidu.com/s/1i ...
- 【C#/.NET】使用ASP.NET Core对象池
Nuget Microsoft.Extensions.ObjectPool 使用对象池的好处 减少初始化/资源分配,提高性能.这一条与线程池同理,有些对象的初始化或资源分配耗时长,复用这些对象减少初始 ...
- 案例分享-被*队友的mybatis蠢哭的一天
昨晚加班的时候被队友拉着看一个mybatis的问题,耗费了我一个小时时间,最后差点没被我打死,实在是觉得滑稽,今天回家写下来跟大伙分享一下. 问题现象 Invalid bound statement ...
- 花了一周时间,总算把mysql的加锁搞清楚了,再也不怕间隙锁和next-key了
接触mysql都知道在mysql中有很多锁,共享锁(S).排他锁(X).间隙锁(gap).next-key,当然还有意向锁.表锁等.今天不讲别的,专门来看下innodb引擎下的锁是什么样子的. 现在有 ...