1、简介 Spring Boot 有许多有用的功能,包括外部化配置和轻松访问 Properties 文件中定义的属性。上一篇文章 介绍了实现这一点的各种方法。
本文将带你了解 Spring Boot 中的 @ConfigurationProperties 注解。
2、项目设置 按照惯例,在 pom.xml 中将 spring-boot-starter-parent 添加为 <parent>:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.0.0</version> <relativePath/> </parent> 为了验证文件中定义的属性,还需要一个 JSR-380 实现,hibernate-validator 就是其中之一,它由 spring-boot-starter-validation 依赖提供。
把它也添加到 pom.xml 中:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> 更多详细信息可参阅 Hibernate Validator 入门。
3、示例属性 官方文档建议将配置属性隔离到单独的 POJO 中。
如下:
@Configuration @ConfigurationProperties(prefix = "mail") public class ConfigProperties { private String hostName; private int port; private String from; //Get、Set 方法 } 通过 @Configuration 注解,Spring 会在 Application Context 中创建一个 Spring Bean。
1、概览 本文将带你了解如何通过 Java 配置和 @PropertySource 在 Spring 中设置和使用 Properties,以及 Properties 在 Spring Boot 中的工作原理。
2、通过注解注册 Properties 文件 Spring 3.1 引入了新的 @PropertySource 注解,作为一种方便的机制,用于将属性源添加到环境中。
可以将此注解与 @Configuration 注解结合使用:
@Configuration @PropertySource("classpath:foo.properties") public class PropertiesWithJavaConfig { //... } 另一种非常有用的注册新 Properties 文件的方法是使用占位符,它允许在运行时动态选择不同的文件:
@PropertySource({ "classpath:persistence-${envTarget:mysql}.properties" }) ... 2.1、定义多个属性位置 @PropertySource 注解是可重复的(Java 8 的可重复注解特性)。因此,如果使用的是 Java 8 或更高版本,就可以使用此注解来定义多个属性位置:
@PropertySource("classpath:foo.properties") @PropertySource("classpath:bar.properties") public class PropertiesWithJavaConfig { //... } 当然,也可以使用 @PropertySources 注解并指定一个 @PropertySource 数组。这不仅适用于 Java 8 或更高版本,也适用于任何受支持的 Java 版本:
@PropertySources({ @PropertySource("classpath:foo.properties"), @PropertySource("classpath:bar.properties") }) public class PropertiesWithJavaConfig { //.
1、概览 本文将带你了解如何使用 Spring Boot 中的框架支持来编写测试,包括可以独立运行的单元测试,以及在执行测试之前加载 Spring Application Context 的集成测试。
2、项目设置 本文中的示例项目是一个 “雇员管理 API”,提供了对 Employee 资源的一些操作。是一个典型的MVC三层架构,从 Controller 到 Service 最后到持久层。
3、Maven 依赖 首先,添加测试依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <version>2.5.0</version> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>test</scope> </dependency> spring-boot-starter-test 是主要的依赖,它包含了测试所需的大部分依赖。
H2 DB 是内存数据库,非常方便用于测试。
3.1、JUnit 4 从 Spring Boot 2.4 开始,JUnit 5 的 Vintage 引擎已从 spring-boot-starter-test 中移除。如果仍想使用 JUnit 4 编写测试,则需要添加以下 Maven 依赖:
<dependency> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-core</artifactId> </exclusion> </exclusions> </dependency> 4、使用 @SpringBootTest 进行集成测试 顾名思义,集成测试的重点是集成应用的不同层。这也意味着不涉及模拟(Mock)。
问题回溯 2023 年 Q2 某日运营反馈一个问题,商品系统商家中心某批量工具模板无法下载,导致功能无法使用(因为模板是动态变化的)
商家中心报错如下(JSON串):
{"code":-1,"msg":"失败"} 负责的同事看到失败后立即与我展开讨论(因为不是关键业务,所以不需要回滚,修复即可),我们发现新功能模板下载的代码与之前的代码有所不同,恰好之前的功能又可以正常运行,所以同事对现有代码进行改造然后预发布测试完成后再次上线。
其他业务代码:
/** * 模板下载 */ @RequestMapping("/doBatchWareSetAd") public void doBatchWareSetAd(@RequestParam MultipartFile file, HttpServletResponse response) { wareBatchBusiness.doBatchWareSetAd(file, response, getLongOrgCode(), getCurrentUserPin(), getCurrentUserId()); } 上线的结果是:仍然无法使用。
其实也正常:因为两种代码在预发布都可以正常运行,在线上出错只可能是因为其他原因,只不过我们不了解底层原理,害怕它 “可能” 有问题罢了,最终查询得到的结论是权限系统管理员在线上环境没有给我们配置相应的文件,导致请求为空,导致请求失败。
探索 @ResponseBody 与主动写入响应流的关系 我们都知道 @ResponseBody 注解可以帮助我们把返回对象转化为 JSON,方便展示和交互。
那它到底是如何工作的呢,请看下面的讲解:
代码案例 1 @RequestMapping("/test1") @ResponseBody public Map<String, String> test1(HttpServletResponse response) { Map<String, String> map = new HashMap<>(); map.put("1", "1"); return map; } // 响应 JSON报文 Debug 代码,发现其核心处理类为:RequestResponseBodyMethodProcessor。
方法:org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor#handleReturnValue 会处理其相关返回值。
真正的核心处理方法:org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor#writeWithMessageConverters。
关键 DEBUG 记录如下图所示:
1、概览 本文将带你了解 Spring Boot 应用中的日志配置。
2、初始设置 通过 Spring Initializr 初始化一个 Spring Boot 应用:
创建唯一的类 LoggingController:
@RestController public class LoggingController { Logger logger = LoggerFactory.getLogger(LoggingController.class); @RequestMapping("/") public String index() { logger.trace("A TRACE Message"); logger.debug("A DEBUG Message"); logger.info("An INFO Message"); logger.warn("A WARN Message"); logger.error("An ERROR Message"); return "Howdy! Check out the Logs to see the output..."; } } 启动应用后,只需访问 http://localhost:8080/,就能触发这些日志输出。
3、日志零配置 就日志记录而言,Spring Boot 唯一必须的依赖是 Apache Commons Logging。它是由 Spring 的 spring-jcl 模块提供的。
如果使用的是 Spring Boot Starter(几乎总是使用 Spring Boot Starter),就根本不用担心导入 spring-jcl 的问题。这是因为每个 Starter,比如 spring-boot-starter-web,都依赖于 spring-boot-starter-logging,它已经导入了 spring-jcl。
1、概览 Spring Boot 通过 Hibernate Validator(Bean Validation 的实现)对数据验证提供了强大的支持。
本文将通过一个实际的 REST 应用带你了解如何在 Spring Boot 中校验数据。
2、Maven 依赖 在 pomx.ml 中添加 spring-boot-starter-web、spring-boot-starter-jpa 和 H2 database 依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>2.1.214</version> <scope>runtime</scope> </dependency> 从 Boot 2.3 开始,还需要明确添加 spring-boot-starter-validation 依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> 3、示例 Domain 类 定义一个 JPA 实体类,User:
@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; @NotBlank(message = "Name is mandatory") private String name; @NotBlank(message = "Email is mandatory") private String email; // 构造函数、Set、Set 方发省略 } User 实体类很简单,它展示了如何使用 Bean Validation 的约束来限制 name 和 email 字段。
1、概览 本文将带你了解如何在 Spring Boot 中使用 H2 内存数据库。与其他数据库一样,Spring Boot 生态系统对 H2 提供了开箱即用的支持。
2、依赖 添加 h2 和 spring-boot-starter-data-jpa 依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> 3、Datasource 配置 默认情况下,Spring Boot 会配置应用使用用户名 sa 和空密码连接到内存数据库。
不过,你也可以通过在 application.properties 文件中添加以下属性来更改这些参数:
spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password=password spring.jpa.database-platform=org.hibernate.dialect.H2Dialect 相应的 YAML 配置如下:
spring: datasource: url: jdbc:h2:mem:mydb username: sa password: password driverClassName: org.h2.Driver jpa: spring.jpa.database-platform: org.hibernate.dialect.H2Dialect 内存数据库会在应用重启后会丢失数据,可以通过使用基于文件的存储来改变这种行为。
更新 spring.datasource.url 属性:
spring.datasource.url=jdbc:h2:file:/data/demo 相应的 YAML 配置如下:
spring: datasource: url: jdbc:h2:file:/data/demo H2 数据库还可以在 其他模式 下运行。
1、概览 Spring Boot 的自动配置功能让配置 Spring 变得更容易。
本文将带你了解 org.springframework.boot.autoconfigure 和 org.springframework.boot.autoconfigure.condition 包中的核心注解。
2、@SpringBootApplication 使用此注解来标记 Spring Boot 应用的 main 类:
@SpringBootApplication class VehicleFactoryApplication { public static void main(String[] args) { SpringApplication.run(VehicleFactoryApplication.class, args); } } @SpringBootApplication 封装了 @Configuration、@EnableAutoConfiguration 和 @ComponentScan 注解,均为默认属性。
3、@EnableAutoConfiguration @EnableAutoConfiguration 顾名思义就是启用自动配置。这意味着 Spring Boot 会在其 classpath 上查找自动配置 Bean,并自动应用它们。
注意,必须将此注解与 @Configuration 一起使用:
@Configuration @EnableAutoConfiguration class VehicleFactoryConfig {} 4、自动配置的条件注解 通常,在编写自定义自动配置时,我们希望 Spring 有条件地使用它们。这可以通过本节中的注解来实现这一目标。
可以将本节中的注解放在 @Configuration 类或 @Bean 方法上。
4.1、@ConditionalOnClass 和 @ConditionalOnMissingClass 只有注解参数中的类存在/不存在时,Spring 才会使用标记的自动配置 Bean:
1、概览 本文将带你了解如何使用 Spring Security OAuth 和 Spring Boot 以及 Keycloak 作为授权服务器来实现单点登录(SSO)。
我们会使用 4 个不同的应用:
授权服务器 - 中央认证机制 资源服务器 - Foo 资源的提供者 两个客户端应用 - 使用 SSO 的应用 简单地说,当用户试图通过一个客户端应用访问资源时,他们会被重定到授权服务器进行身份认证。Keycloak 会对用户进行登录,在登录第一个应用后,如果使用同一浏览器访问第二个客户端应用,用户无需再次输入凭据。
使用 OAuth2 的授权码(Authorization Code)模式。
Spring Security 将此功能称为 OAuth 2.0 登录,而 Spring Security OAuth 将其称为 SSO。
2、授权服务器 以前,通过 Spring Security OAuth 可以将授权服务器设置为 Spring 应用。
不过,Spring Security OAuth 已被 Spring 弃用,现在可以使用 Keycloak 作为授权服务器。
因此,这次我们在 Spring Boot 应用中把授权服务器设置为嵌入式 Keycloak 服务器。
在 预配置 中,我们将定义两个客户端,即 ssoClient-1 和 ssoClient-2,分别对应每个客户端应用。
1、概览 本文将带你了解如何在 YAML 中定义列表,以及如何在 Spring Boot 中把 YAML 列表映射为 Java List 对象。
2、回顾一下 YAML 中的列表 简而言之,YAML 是一种人类可读的数据序列化标准,为编写配置文件提供了一种简洁明了的方法。YAML 的优点在于它支持多种数据类型,如 List、Map 和标量(Scalar)类型。
YAML 列表中的元素使用 - 字符定义,它们的缩进级别相同:
yamlconfig: list: - item1 - item2 - item3 - item4 相比之下,在 properties 中定义列表则使用的是索引值:
yamlconfig.list[0]=item1 yamlconfig.list[1]=item2 yamlconfig.list[2]=item3 yamlconfig.list[3]=item4 与 properties 文件相比,YAML 的分层性质大大提高了可读性。YAML 的另一个功能是可以为不同的 Spring Profile 定义不同的属性。从 Boot 2.4.0 版开始,properties 文件也可以这样做。
Spring Boot 为 YAML 配置提供了开箱即用的支持。根据设计,Spring Boot 会在启动时从 application.yml 中加载配置属性,无需任何额外工作。
3、将 YAML 列表绑定至简单的 List Spring Boot 提供了 @ConfigurationProperties 注解,以简化将外部配置数据映射到对象模型的逻辑。