教程

Spring Boot 中的 application.yml 和 application.properties

1、概览 Spring Boot 中的一个常见做法是使用外部配置来定义属性。这样,就可以在不同的环境中使用相同的应用程序代码。 外部配置可以使用 properties 文件、YAML 文件、环境变量和命令行参数。 本文将带你了解 properties 文件和 YAML 文件的主要区别。 2、Properties 配置 默认情况下,Spring Boot 可以访问在 application.properties 文件中设置的配置,该文件使用键值格式: spring.datasource.url=jdbc:h2:dev spring.datasource.username=SA spring.datasource.password=password 如上,每一行都是一个单独的配置,因此需要为 key 使用相同的前缀来表达分层数据。在本例中,每个 key 都属于 spring.datasource。 2.1、Properties 中的占位符 在值中,可以使用 ${} 语法的占位符来引用其他 key、系统属性或环境变量的内容: app.name=MyApp app.description=${app.name} is a Spring Boot application 2.2、列表 如果同类 properties 具有不同的值,可以用数组索引来表示列表结构: application.servers[0].ip=127.0.0.1 application.servers[0].path=/path1 application.servers[1].ip=127.0.0.2 application.servers[1].path=/path2 application.servers[2].ip=127.0.0.3 application.servers[2].path=/path3 2.3、多文档 自 2.4.0 版起,Spring Boot 支持创建多文档 properties 文件。简单地说,可以将单个物理文件拆分成多个逻辑文档。 这样,就可以在同一个 properties 文件中声明多个 Profile: logging.file.name=myapplication.log bael.property=defaultValue #--- spring.config.activate.on-profile=dev spring.datasource.password=password spring.datasource.url=jdbc:h2:dev spring.

Spring Boot 优雅停机

本文将带你了解如何在 Spring Boot 应用中配置优雅停机。 1、优雅停机 从 Spring Boot 2.3 开始,Spring Boot 所支持的四种嵌入式 Web 服务器(Tomcat、Jetty、Undertow 和 Netty)都支持在 Servlet 和响应式平台上的优雅关机功能。 只需在 application.properties 文件中将 server.shutdown 属性设置为 graceful,即可启用优雅停机: server.shutdown=graceful 在优雅停机阶段,Tomcat、Netty 和 Jetty 会停止接受新的 Web 请求。而 Undertow 会继续接受,但会立即向客户端发送 503 Service Unavailable 响应。 默认情况下,该属性的值等于 immediate,这意味着服务器会立即关闭。 在优雅关机时,可能有一些之前的请求仍在处理中。在这种情况下,服务器会等待这些活动请求在指定时间内完成。 可以使用 spring.lifecycle.timeout-per-shutdown-phase 配置属性来配置超时时间: spring.lifecycle.timeout-per-shutdown-phase=1m 如上,在优雅停机时,对于那些仍在处理的请求,服务器等待最多一分钟。该属性的默认值为 30 秒。 2、总结 本文介绍了如何在 Spring Boot 中配置优雅停机,以及如何配置服务器停机超时时间。 Ref:https://www.baeldung.com/spring-boot-web-server-shutdown

Spring MVC Async 和 WebFlux

1、概览 本文将带你了解 Spring Async 和 Spring WebFlux 之间的区别。 2、场景 本文分别用 Spring Async 和 Spring WebFlux 来实现一个简单的 Web 应用。 Web 请求会通过一个延迟时间为 200 毫秒的 Filter,然后 Controller 需要 500 毫秒来计算并返回结果。 最后使用 Apache ab 分别进行负载测试,并使用 JConsole 监控应用的行为。 3、Spring MVC Async Spring 3.0 引入了 @Async 注解。@Async 的目标是允许应用在单独的线程上运行重负载的任务。此外,调用方可以等待结果(如果感兴趣)。因此,返回类型不能是void,而可以是 Future、CompletableFuture 或 ListenableFuture 之一。 Spring 3.2 引入了 org.springframework.web.context.request.async 包,它与 Servlet 3.0 一起为 Web 层带来了异步的支持。因此,自 Spring 3.2 起,@Async 可以在 @Controller 或 @RestController 类中使用。 当客户端发起请求时,请求会经过过滤器链(filter chain)中所有匹配的过滤器(filter),直到到达 DispatcherServlet 实例。 然后,Servlet 会对请求进行异步调度。它通过调用 AsyncWebRequest#startAsync 将请求标记为已启动,将请求处理转移到 WebSyncManager 的实例,然后在不提交响应的情况下完成其工作。过滤器链也按相反的方向遍历执行到根节点。

在生产环境中关闭 Swagger-UI

1、概览 在开发环境下使用 Swagger UI 可以很方便地查看、测试 REST 服务。但是出于安全考虑,在生产环境中往往需要禁用 Swagger UI。 2、Swagger 配置 要 使用 SpringDoc 设置 Swagger,需要在配置 Bean 中对其进行定义。 创建 SwaggerConfig 类: @Configuration public class SwaggerConfig { @Bean public OpenAPI openAPI() { return new OpenAPI().info(new Info().title("SpringDoc Disable SwaggerUI example") .description("SpringDoc Disable SwaggerUI application") .version("v0.0.1")); } } 默认情况下,该配置 Bean 会添加到 Spring Context 中。这样,Swagger 可以在所有环境中使用。 3、使用 Spring Profile 在 Spring 中,可以使用 @Profile 注解来启用或禁用 Bean。 使用 SpEL 表达式来指定在哪些环境中激活 Swagger。 @Profile({"!prod && swagger"}) 如上,在 swagger Profile,且不是 prod Profile 的情况下才会启注解的 Bean。

自定义 Keycloak 的登录页面

1、概览 Keycloak 是第三方授权服务器,用于管理 Web 或移动应用的身份验证和授权。它为用户提供了一个默认的登录页面。 本文将带你了解如何自定义 Keycloak 服务器的登录页面。 本文在 《自定义 Keycloak 主题》 基础上进行实现。 2、独立 Keycloak 服务器 继续以 custom 主题为例,先看看独立服务器。 2.1、管理控制台设置 进入 Keycloak 目录,然后在 bin 文件夹中运行如下命令,启动服务器: kc.[sh|bat] start-dev --spi-theme-static-max-age=-1 --spi-theme-cache-themes=false --spi-theme-cache-templates=false 使用上述命令启动服务器后,只需刷新页面,就能看到更改。 现在,在 themes/custom 目录中新建一个名为 login 的文件夹。为了简单起见,先将 themes/keycloak/login 目录中的所有内容复制到这里。这是默认的登录页面主题。 然后,进入管理控制台(http://localhost:8080/admin/master/console),使用 initial1/zaq1!QAZ 凭证登录,并进入 Realm 的 “Themes” 选项卡: 为 Login Theme 选择 custom,然后保存更改。 现在就可以尝试一些自定义功能了。不过在此之前,先来看看默认登录页面: 2.2、添加自定义内容 现在,假设我们需要更改背景。 打开 login/resources/css/login.css 并更改 class 定义: .login-pf body { background: #39a5dc; background-size: cover; height: 100%; } 刷新页面即可看到效果: 接下来,尝试更改用户名和密码的标签。

自定义 Keycloak 主题

1、概览 Keycloak 是一个开源的身份和访问管理(Identity and Access Management,IAM)解决方案,可以作为第三方授权服务器来管理 Web 或移动应用的身份验证和授权。 本文将带你了解如何自定义 Keycloak 的主题,为终端用户的网页提供不同的外观。 本文以之前的文章为基础:《Keycloak 指南》和《在 Spring Boot 中嵌入 Keycloak》。因此,对于初学者来说,最好先阅读这两篇文章。 2、Keycloak 的主题 2.1、默认主题 Keycloak 中预置了几个主题,并与发行版绑定在一起。 对于单机版服务器,可在 ../lib/lib/main/org.keycloak.keycloak-themes-20.0.3.jar(可使用任何标准 ZIP 压缩工具打开)的主题目录下的不同文件夹中找到这些主题: base:包含 HTML 模板和 Message Bundle 的骨架主题;所有主题(包括自定义主题)一般都继承自 base 主题 keycloak:包含用于美化页面的图片和样式表;如果我们不提供自定义主题,则默认使用该主题 keycloak.v2:基于 React 的主题;新管理控制台的一部分;旧控制台已过时,将在 Keycloak 21 中移除。 不建议修改现有主题。相反,应该创建一个新主题,从上述两个主题中继承。 要创建一个新的自定义主题,需要在 themes 目录中添加一个新的文件夹,称之为 custom。如果想要完全重建,则建议从 base 文件夹中复制内容。 在本例中,我们并不打算替换所有内容,因此从 keycloak 目录中获取内容。 2.2、主题类型 Keycloak 支持五种主题: Welcome:用于欢迎页 Login:用于登录、OTP、授予、注册和忘记密码页面 Account:用于用户账户管理页面 Admin Console:用于管理控制台 Email:用于服务器发送的电子邮件 上述列表中的最后四个主题可以通过独立服务器的管理控制台进行设置。当我们在 themes 目录下创建一个新文件夹后,服务器重启后就可以选择该文件夹。 使用凭证 initial1 / zaq1!QAZ(在 上一文章 中设置的)登录管理控制台,并转到 Realm 的 “Themes” 选项卡:

使用 Arthas 在 Spring 运行时获取配置值和配置来源

背景 众所周之,Spring / Spring Boot 应用的配置注入方式非常多: System Properties / System Env application.properties / application.yaml Spring Profile Spring Cloud Config 还有很多配置注入的方式你可以参阅 中文文档,可谓是令人眼花缭乱。 获取运行时具体配置 对于开发人员来说,在运行时怎样确定某个配置是否生效?它的具体值是什么? 通过 Arthas,只要一行命令就可以获取到。 例如,获取 server.port 的具体值: vmtool --action getInstances --className org.springframework.context.ConfigurableApplicationContext --express 'instances[0].getEnvironment().getProperty("server.port")'@String[7001] 获取具体的配置来源 但是这个配置是从哪里来的? 对于 spring boot 应用,可以打开一个新的 terminal 窗口,执行 telnet 127.0.0.1 3658 连接上Arthas。 直接 watch 下面的函数。 在原来窗口用上面的 vmtool 命令来获取 server.port 的值。 从 watch 返回结果中可以看到,server.port 值来源于 application.yml: watch org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertySource findConfigurationPropertyPress Q or Ctrl+C to abort.Affect(class count: 1 , method count: 2) cost in 217 ms, listenerId: 5method=org.

在 Spring Boot 中嵌入 Keycloak 服务器

1、概览 Keycloak 是由 Red Hat 管理和在 Java 中由 JBoss 开发的开源身份和访问管理解决方案。 本文将带你了解如何在 在 Spring Boot 中嵌入 Keycloak 服务器,这样就能轻松启动预配置的 Keycloak 服务器。 Keycloak 也可以作为 独立服务器 运行,但需要下载并通过管理控制台进行设置。 2、Keycloak 预配置 服务器包含一组 Realm,每个 Realm 都是用户管理的独立单元。要对其进行预配置,我们需要指定一个 JSON 格式的 Realm 定义文件。 使用 Keycloak Admin 控制台 配置的所有内容都以 JSON 格式进行持久化。 我们的授权服务器将使用名为 baeldung-realm.json 的 JSON 文件进行预配置。文件中的几个相关配置如下: users:默认用户是 john@test.com 和 mike@other.com;对应的凭证也在这里。 clients:定义一个 ID 为 newClient 的客户端 standardFlowEnabled:设置为 true,激活 newClient 的授权码(Authorization Code)授权模式。 redirectUris:newClient 在成功验证后将重定向到的服务器 URL webOrigins:置为 +,为所有 redirectUris 的 URL 提供 CORS 支持 Keycloak 服务器会默认签发 JWT Token,因此无需为此进行单独配置。接下来看看 Maven 的配置。

Spring 中的 @ConditionalOnProperty 注解

1、概览 本文将带你了解 Spring 中 @ConditionalOnProperty 注解的作用和用法。 2、@ConditionalOnProperty 的作用 通常,在开发基于 Spring 的应用时,需要根据配置属性是否存在,或者配置属性有指定的值来有条件地创建一些 Bean。 例如,我们需要注册一个 DataSource Bean,并且要根据属性值设置为 prod 还是 test 来创建生产数据库或测试数据库。 这正是 @ConditionalOnProperty 注解的用武之地。 简而言之,@ConditionalOnProperty 只有在环境属性存在且具有指定值的情况下才会启用 Bean 注册。默认情况下,指定的属性必须已定义且等于指定的值。 熟悉了 @ConditionalOnProperty 注解的用途后,接着来深入了解一下如何使用。 3、@ConditionalOnProperty 注解实践 开发一个基本的电子邮件通知系统来示范 @ConditionalOnProperty 的使用。 首先,创建一个简单的服务来发送通知消息。 定义 NotificationSender 接口: public interface NotificationSender { String send(String message); } 接下来,提供一个 NotificationSender 接口的实现来发送电子邮件: public class EmailNotification implements NotificationSender { @Override public String send(String message) { return "Email Notification: " + message; } } 现在,来看看如何使用 @ConditionalOnProperty 注解。

Spring 中的 @DynamicPropertySource 注解

1、概览 当代应用通常需要连接到各种外部服务,如 PostgreSQL、Apache Kafka、Cassandra、Redis 和其他外部 API。 本文将带你了解 Spring 如何通过引入动态属性(@DynamicPropertySource)来帮助测试此类应用。 2、问题:动态属性 假设我们正在开发一个使用 PostgreSQL 作为数据库的应用。 创建 JPA 实体: @Entity @Table(name = "articles") public class Article { @Id @GeneratedValue(strategy = IDENTITY) private Long id; private String title; private String content; // get、set 省略 } 我们需要编写测试来确保应用按预期运行,由于该测试需要与真实数据库创建连接,我们应该事先建立一个 PostgreSQL 实例。 在测试执行过程中,有不同的方法来设置此类基础工具。事实上,这类解决方案主要有三类: 专门为测试设置一个单独的数据库服务器 使用一些轻量级的、测试专用的替代品,如 H2 让测试本身管理数据库的生命周期 由于未区分测试环境和生产环境,与使用 H2 等测试替身相比,有更好的选择。第三个选项不仅可以与真实数据库一起使用,还可以为测试提供更好的隔离性。此外,借助 Docker 和 Testcontainers 等技术,实现第三个选项非常容易。 如果使用 Testcontainers 等技术,测试流程如下: 在所有测试前设置 PostgreSQL 等组件。通常,这些组件会监听随机端口。 运行测试。 卸载组件。 如果 PostgreSQL 容器每次都监听随机端口,那么我们就应该以某种方式动态设置和更改 spring.datasource.url 配置属性。基本上,每个测试都应该有自己的配置属性版本。 当配置是静态的时候,可以使用 Spring Boot 的配置管理工具轻松地对其进行管理。但是,当我们面对的是动态配置时,同样的任务就会变得比较麻烦。