Spring Boot 配置实践
Spring Boot 2.7
- 自动配置注册的加载从 spring.factories 迁移到 AutoConfiguration下的imports。
- Spring MVC 的 requestMappingHandlerMapping Bean 不再默认为主,存在多个时注入,需要指定或注入集合。
- 引入了新的 @AutoConfiguration 注解,作用在 AutoConfiguration.imports文件中列出的自动配置类。
- 增加了一些测试相关的注解、注解属性、注解属性源。如,@SpringBootTest,@DataCouchbaseTest,@DataElasticsearchTest。
- 增加支持 Redis Sentinel 进行身份验证的用户名,spring.redis.sentinel.username。
自动配置
自动配置注册
如果您已经创建了自己的自动配置,您应该将注册从 org.springframework.boot.autoconfigure.EnableAutoConfiguration 下的 spring.factories 移动到名为 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 的文件中。
每行包含一个自动配置类的完全限定名称,而不是一个逗号分隔的列表。
spring-boot/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration
为了向后兼容,spring.factories 中的条目仍将受到尊重。
新的 @AutoConfiguration 注解
引入了新的 @AutoConfiguration 注解。 它应该用于注释新 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件中列出的顶级自动配置类,替换 @Configuration。
嵌套在 @AutoConfiguration 类中或由 @AutoConfiguration 类导入的配置类应该像以前一样继续使用 @Configuration。
为方便起见,@AutoConfiguration 还支持通过 after、afterNames、before 和 beforeNames 属性进行自动配置排序。 这可以用作@AutoConfigureAfter 和@AutoConfigureBefore 的替代品。
使用 Maven Shade 插件和 Gradle Shadow 插件构建Jars
Spring Boot 2.7 改变了发现自动配置和管理上下文类的方式。 它们现在分别在名为 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 和 META-INF/spring/org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration.imports 的文件中声明。
Maven Shade插件的配置 如果使用 maven-shade-plugin且没有依赖 spring-boot-starter-parent,添加如 AppendingTransformer配置。
|
|
Gradle Shadow插件配置 添加如下配置,以附加 .imports 为后缀的文件:
|
|
测试
单元测试:一般面向某一个简单的方法,在对应测试的方法上加上注解@Test,编写一般业务代码时,测试成本较大。
切片测试:一般面向某一个小的功能模块,在对应测试的类上加上注解@RunWith @WebMvcTest @SpringBootTesT等,用于测试某一项边界功能,介于单元测试和功能测试之间。涉及到的注解有。
功能测试:一般面向某个由多个小的功能模块组成的完整的业务功能,在对应测试的类上加上注解@RunWith @SpringBootTest等,同时也可以使用切面测试中的mock能力。
总结:实际上无论是单元测试,还是切片测试,功能测试都是实现某一项功能的测试,区别不大,只要在对应的类上加上两个功能测试模块的大注解@RunWith @SpringBootTest再配合其他的小注解即可完成所有功能模块的测试。
如果您对测试花费在设置和 Spring 应用程序上下文上的时间感兴趣,您可能需要查看 JUnit Insights,它可以包含在 Gradle 或 Maven 构建中,以生成关于 JUnit 5 如何花费时间的很好的报告。
异常处理
在 Spring Boot 中创建控制器以自定义方式处理所有错误/异常时,包括自定义异常
- 控制器是否应该实现 Spring Boot 的 ErrorController ?
- 控制器是否应该扩展 Spring 的 ResponseEntityExceptionHandler ?
pring Boot 应用程序具有用于错误处理的默认配置 - ErrorMvcAutoConfiguration。
如果没有提供额外的配置,它的基本作用是:
它创建默认的全局错误控制器 - BasicErrorController 它创建默认的“错误”静态视图“Whitelabel 错误页面”。 BasicErrorController默认连接到“/error”。如果应用程序中没有自定义的“错误”视图,则在任何控制器抛出异常的情况下,用户会登陆 /error whitelabel 页面,该页面由 BasicErrorController 填充信息。
Spring Boot 的默认 JSON 错误体可以通过定义我们自己的 ErrorAttributes 实现来定制或扩展。
|
|
HandlerExceptionResolver
DispatcherServlet 在实现的应用程序上下文中声明的任何 Spring bean HandlerExceptionResolver 都将用于拦截和处理 MVC 系统中引发的任何异常,而不是由 Controller 处理。
|
|
handler 指的是产生异常的控制器
MVC 默认创建三个这样的解析器。正是这些解析器实现了上述行为:
ExceptionHandlerExceptionResolver
将未捕获的异常与@ExceptionHandler处理程序(控制器)和任何控制器通知上的合适方法匹配。 在 @ControllerAdvice 类中搜索异常处理程序(使用 @ExceptionHandler 注释的方法)。ResponseStatusExceptionResolver
检查抛出的异常是用 @ResponseStatus 注解还是从 ResponseStatusException 派生。DefaultHandlerExceptionResolver
转换标准 Spring 异常并将它们转换为 HTTP 状态代码(我没有在上面提到这一点,因为它是 Spring MVC 内部的)。 然后它通过 Spring MVC 异常的默认处理程序。- 最后,如果没有找到,控件将被转发到错误页面视图,并在其后面带有全局错误处理程序。如果异常来自错误处理程序本身,则不执行此步骤。
- 如果没有找到错误视图(例如禁用全局错误处理程序)或跳过第 4 步,则异常由容器处理。
它们按照列出的顺序链接和处理 - 在内部 Spring 创建一个专用 bean (HandlerExceptionResolverComposite) 来执行此操作。
exception-handling-in-spring-mvc
处理 400 500 错误
# 出现错误时, 直接抛出异常
spring.mvc.throw-exception-if-no-handler-found=true
# 不要为我们工程中的资源文件建立映射
spring.resources.add-mappings=false
|
|
可以继承 org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController 重写 errorHtml 抛出异常,异常中携带必要信息,最后 @ExceptionHandler 统一拦截处理。