Spring Boot是一种广泛使用且非常流行的企业级高性能框架。以下是一些最佳实践和一些技巧,您可以使用它们来改进 Spring Boot 应用程序并使其更加高效。这篇文章会有点长,完整读完文章需要一些时间。
正确的包装风格
- 正确的打包将有助于轻松理解代码和应用程序的流程。
- 您可以使用有意义的包装来构建您的应用程序。
- 您可以将所有控制器包含在单独的包中,将服务包含在单独的包中,将 util 类包含在单独的包中……等等。这种风格在小型微服务中非常方便。
- 如果您正在处理庞大的代码库,则可以使用基于功能的方法。您可以根据您的要求来决定。
根据类型组织
根据功能组织
使用 Spring Boot 启动器
- 这是 Spring Boot 的一个很酷的功能。
- 我们可以非常轻松地使用起始依赖项,而无需一一添加单个依赖项。这些入门依赖项已与所需的依赖项捆绑在一起。
- 例如,如果我们添加spring-boot-starter-web依赖项,默认情况下它会与jackson、spring-core、spring-mvc 和 spring-boot-starter-tomcat 依赖项捆绑在一起。
- 所以我们不需要关心单独添加依赖。
- 它还可以帮助我们避免版本不匹配。
使用正确版本的依赖项
- 始终建议使用最新的稳定GA版本。
- 有时它可能会因 Java 版本、服务器版本、应用程序类型等而有所不同。
- 不要使用同一包的不同版本,如果存在多个依赖项,请始终使用 <properties> 指定版本。
Lombok
- 作为一名 Java 开发人员,您可能听说过Lombok 项目。
- Lombok 是一个 Java 库,可用于减少代码并允许您使用其注释编写干净的代码。
- 例如,您可能在某些类(如实体、请求/响应对象、dtos 等)中使用大量的 getter 和 setter 行。
- 但如果你使用Lombok,它只是一行,你可以根据你的要求使用@Data、@Getter或@Setter 。
- 您也可以使用Lombok记录器注释。推荐@Slf4j 。
将构造函数注入与 Lombok 一起使用
- 当我们谈论依赖注入时,有两种类型。
- 一种是“构造函数注入”,另一种是“ setter注入”。除此之外,您还可以使用非常流行的@Autowired注释来进行“字段注入” 。
- 但我们强烈建议使用构造函数注入而不是其他类型。因为它允许应用程序在初始化时初始化所有必需的依赖项。
- 这对于单元测试非常有用。
- 重要的是,我们可以使用Lombok 的@RequiredArgsConstructor注解来使用构造函数注入。
使用 slf4j 日志记录
- 日志记录非常重要。
- 如果您的应用程序在生产过程中出现问题 ,日志记录是找出根本原因的唯一方法。
- 因此,在添加记录器、日志消息类型、记录器级别和记录器消息之前应该仔细考虑。
- 不要使用 System.out.print()
- 建议将 Slf4j 与 Spring Boot 中默认的日志框架 logback 一起使用。
- 始终使用 slf4j { } 并避免在记录器消息中使用字符串插值。因为字符串插值会消耗更多的内存。
- 您可以使用 Lombok @Slf4j注释非常轻松地创建记录器。
- 如果您处于微服务环境中,则可以使用ELK堆栈。
仅使用控制器进行路由
- 控制器专用于路由。
- 它是无状态和单例的。
- DispatcherServlet 将检查控制器上的@RequestMapping
- 控制器是请求的最终目标,请求将被交给服务层并由服务层处理。
- 业务逻辑不应该位于控制器中。
使用服务来实现业务逻辑
- 完整的业务逻辑包括验证、缓存等。
- 服务与持久层通信并接收结果。
- 服务也是单例的。
避免空指针异常
- 为了避免NullPointerException,您可以使用java.util 包中的Optional 。
- 您还可以使用空安全库。例如:Apache Commons StringUtils
- 对已知对象调用equals()和equalsIgnoreCase()方法。
- 使用valueOf()而不是toString()
- 使用基于 IDE 的@NotNull和@Nullable注释。
使用集合框架的最佳实践
- 为您的数据集使用适当的集合。
- 将forEach与 Java 8 功能结合使用,并避免使用旧版 for 循环。
- 使用接口类型而不是实现。
- 使用isEmpty()而不是size()可以获得更好的可读性。
- 不要返回空值,可以返回空集合。
- 如果您使用对象作为要存储在基于哈希的集合中的数据,则应重写 equals() 和 hashCode() 方法。
使用分页
- 这将提高应用程序的性能。
- 如果您使用Spring Data JPA,则PagingAndSortingRepository使分页的使用变得非常容易且几乎不费吹灰之力。
使用缓存
- 在谈论应用程序性能时,缓存是另一个重要因素。
- 默认情况下,Spring Boot 通过ConcurrentHashMap提供缓存,您可以通过@EnableCaching注解来实现这一点。
- 如果您对默认缓存不满意,可以使用Redis、Hazelcast或任何其他分布式缓存实现。
- Redis 和 Hazelcast 都是内存缓存方法。您还可以使用数据库缓存实现。
使用自定义异常处理程序和全局异常处理
- 当使用大型企业级应用程序时,这一点非常重要。
- 除了一般的异常之外,我们可能还会有一些场景来识别一些特定的错误情况。
- 异常顾问可以使用@ControllerAdvice创建,我们可以创建具有有意义细节的单独异常。
- 它将使将来识别和调试错误变得更加容易。
使用自定义响应对象
- 自定义响应对象可用于返回包含某些特定数据的对象,并满足 HTTP 状态代码、API 代码、消息等要求。
- 我们可以使用构建器设计模式来创建具有自定义属性的自定义响应对象。
删除不必要的代码、变量、方法和类。
- 未使用的变量声明将占用一些内存。
- 删除未使用的方法、类等,因为它会影响应用程序的性能。
- 尽量避免嵌套循环。您可以使用地图代替。
使用注释
- 不要滥用注释。不要对所有代码写注释。相反,您可以使用类、函数、方法、变量等有意义的单词编写描述性代码。
- 删除注释代码、误导性注释和故事型注释。
- 您可以使用注释来警告并解释一些乍一看难以理解的内容。
对类、方法、函数、变量和其他属性使用有意义的词语
- 这看起来很简单,但影响却是巨大的。
- 始终使用正确的有意义且可搜索的命名约定以及正确的大小写。
- 通常,我们在声明类、变量和常量时使用名词或短语。例如:字符串firstName,const isValid
- 您可以使用带有形容词的动词和短语来表示函数和方法。例如:readFile()、sendData()
- 避免使用缩写变量名和意图揭示的名称。例如: int i; 字符串 getExUsr;
- 如果您有意义地使用它,则可以减少声明注释行。由于它具有有意义的名称,新开发人员可以通过阅读代码轻松理解。
使用正确的大小写进行声明
- 有许多不同的大小写,如大写、小写、驼峰命名、帕斯卡命名、蛇命名、SCREAMING_SNAKE_CASE、短横线命名等。
- 但我们需要确定哪个案例专用于哪个变量。
- 通常,我遵循,
类 — PascalCase
方法和变量——驼峰命名法
常量 — SCREAMING_SNAKE_CASE
数据库相关字段—snake_case
- 这只是一个例子。它可能与您在公司遵循的标准不同。
简单点
- 始终尝试编写简单、可读的代码。
- 同样的简单逻辑可以用不同的方式实现,但是如果不可读或不理解就很难理解。
- 有时复杂的逻辑会消耗更多的内存。
- 编写代码时尝试使用KISS、DRY和SOLID原则。
使用通用的代码格式样式
- 格式样式因开发人员而异。编码风格的改变也被认为是一种改变,并且会使代码合并变得非常困难。
- 为了避免这种情况,团队可以采用通用的编码格式。