1 从 Spring Boot 3.1 升级
1.1 参数名称发现
Spring Boot 3.2 使用的 Spring Framework 版本不再尝试通过解析字节码来推断参数名称。如果您在依赖注入或属性绑定时遇到问题,请务必检查您是否在编译时使用了 -parameters
选项。有关更多详细信息,请参阅 "升级到 Spring Framework 6.x" wiki 的此部分。
1.2 记录的应用程序名称
每当设置 spring.application.name
属性时,默认的日志输出就会包含您的应用程序名称。如更喜欢之前格式,可将 logging.include-application-name
置 false
。
1.3 自动配置的用户详细信息服务
若在类路径存在 spring-security-oauth2-client
、spring-security-oauth2-resource-server
和 spring-security-saml2-service-provider
中的一个或多个,而且从 3.2.2 开始,既没有配置 spring.security.user.name
也没有配置 spring.security.user.password
,则自动配置的 InMemoryUserDetailsManager
现在将退出。同样,在反应式应用程序中,如果在类路径上存在 spring-security-oauth2-client
和 spring-security-oauth2-resource-server
中的一个或多个,而且从 3.2.2 开始,既没有配置 spring.security.user.name
也没有配置 spring.security.user.password
,则自动配置的 MapReactiveUserDetailsService
现在也将退出。
如果您正在使用上述依赖项之一,但仍然需要在应用程序中使用 InMemoryUserDetailsManager
或 MapReactiveUserDetailsService
,请在应用程序中定义所需的 bean,或者从 Spring Boot 3.2.2 开始,配置 spring.security.user.name
和 spring.security.user.password
中的一个或两个。
1.4 OTLP 跟踪端点
management.otlp.tracing.endpoint
的默认值已被删除。只有当 management.otlp.tracing.endpoint
有值时,才会自动配置 OtlpHttpSpanExporter
bean。要恢复旧行为,请设置 management.otlp.tracing.endpoint=http://localhost:4318/v1/traces
。
1.5 嵌套 Jar 支持
支持 Spring Boot "Uber Jar" 加载的底层代码已被重写,因为我们不再需要支持 Java 8。更新后的代码使用了一种新的 URL 格式,该格式更符合 JDK 的期望。之前的 URL 格式 jar:file:/dir/myjar.jar:BOOT-INF/lib/nested.jar!/com/example/MyClass.class
已被替换为 jar:nested:/dir/myjar.jar/!BOOT-INF/lib/nested.jar!/com/example/MyClass.class
。更新后的代码还使用了 java.lang.ref.Cleaner
(这是 JDK 9 的一部分)来管理资源。
我们已尽一切努力确保新代码在尽可能大的程度上是对之前实现的透明替换。我们预计大多数用户甚至不会注意到这种变化。您可能会注意到变化的一个领域是,如果您直接引用了启动器类之一,因为它们在新的默认启动器中有新的名称:
新 | 经典 |
---|---|
org.springframework.boot.loader.launch.JarLauncher | org.springframework.boot.loader.JarLauncher |
org.springframework.boot.loader.launch.PropertiesLauncher | org.springframework.boot.loader.PropertiesLauncher |
org.springframework.boot.loader.launch.WarLauncher | org.springframework.boot.loader.WarLauncher |
但是,如果您发现新实现存在任何意外行为,我们也提供了一个回退选项,允许您使用旧代码。
对于 Maven 用户,您可以将 spring-boot-plugin
配置中的 <loaderImplementation>
标签设置为 CLASSIC
。例如:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<loaderImplementation>CLASSIC</loaderImplementation>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
1.6 Spring Boot 3.0 中的弃用情况
在本次发布中,已删除 Spring Boot 3.0 中已弃用的类、方法和属性。升级之前,请确保您没有调用已弃用的方法。
1.7 日志关联 ID
只要使用 Micrometer 跟踪,Spring Boot 就会自动记录关联 ID。参阅更新后的文档。
如果您自己配置了跟踪 id 和 span id 的日志记录,例如以下内容:
logging.pattern.level=%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]
您现在可以将其删除。应用程序名称、跟踪 id 和 span id 现在默认包含在内。
1.8 RestClient 支持
Spring Boot 3.2 包括对新的 RestClient
接口的支持,该接口已在 Spring Framework 6.1 中引入。此接口提供了一种类似于 WebClient
设计的函数式阻塞 HTTP API。
现有和新的应用程序可能需要考虑使用 RestClient
作为 RestTemplate
的替代方案。
详参更新后的参考文档。
1.9 RestTemplate HTTP 客户端
当类路径上存在 Jetty 的 HttpClient
时,Spring Boot 的 HTTP 客户端自动检测将配置 RestTemplateBuilder
使用 Spring Framework 6.1 中新引入的 JettyClientHttpRequestFactory
。
对 JdkClientHttpRequestFactory
的支持已添加到 ClientHttpRequestFactories
。与 JettyClientHttpRequestFactory
不同,它尚未添加到自动检测中。要使用 JdkClientHttpRequestFactory
,您必须主动启用:
@Bean
RestTemplateBuilder restTemplateBuilder(RestTemplateBuilderConfigurer configurer) {
return configurer.configure(new RestTemplateBuilder())
.requestFactory(
(settings) -> ClientHttpRequestFactories.get(JdkClientHttpRequestFactory.class, settings));
}
1.10 对 JdbcClient
的支持
基于 NamedParameterJdbcTemplate
的存在,已添加了对 JdbcClient
的自动配置。如果后者是自动配置的,则会考虑 spring.jdbc.template.*
属性。
1.11 对虚拟线程的支持
Spring Boot 3.2 附带对虚拟线程的支持。要使用虚拟线程,您需要运行在 Java 21 上,并将属性 spring.threads.virtual.enabled
设置为 true
。
① Servlet Web 服务器
启用虚拟线程时,Tomcat 和 Jetty 将使用虚拟线程进行请求处理。这意味着您处理 Web 请求的应用程序代码(如控制器中的方法)将在虚拟线程上运行。
② 使用 Spring WebFlux 的阻塞执行
当虚拟线程启用时,Spring WebFlux 对阻塞执行的支持会自动配置为使用 applicationTaskExecutor
bean (如果它是一个 AsyncTaskExecutor
)。无论是默认情况下还是启用虚拟线程时,applicationTaskExecutor
都是一个 AsyncTaskExecutor
。
③ 任务执行
当启用虚拟线程时,applicationTaskExecutor
bean 将是一个配置为使用虚拟线程的 SimpleAsyncTaskExecutor
。任何使用应用程序任务执行器的地方,例如调用 @Async
方法时的 @EnableAsync
、Spring MVC 的异步请求处理以及 Spring WebFlux 的阻塞执行支持,现在都将利用虚拟线程。与以前一样,任何 TaskDecorator
bean 都会应用于自动配置的执行器,并且 spring.task.execution.thread-name-prefix
属性也会应用。其他 spring.task.execution.*
属性将被忽略,因为它们特定于基于池的执行器。
现在应用程序上下文中提供了 SimpleAsyncTaskExecutorBuilder
,可用于构建 SimpleAsyncTaskExecutor
。如果启用了虚拟线程,SimpleAsyncTaskExecutorCustomizer
bean 可用于自定义构建的 SimpleAsyncTaskExecutor
。构建器将自动配置为使用它们。
④ 任务调度
当启用虚拟线程时,taskScheduler
bean 将是一个配置为使用虚拟线程的 SimpleAsyncTaskScheduler
。将应用 spring.task.scheduling.thread-name-prefix
属性和 spring.task.scheduling.simple.*
属性。其他 spring.task.scheduling.*
属性将被忽略,因为它们特定于基于池的调度程序。
现在应用程序上下文中提供了 SimpleAsyncTaskSchedulerBuilder
,可用于构建 SimpleAsyncTaskScheduler
。如果启用了虚拟线程,SimpleAsyncTaskSchedulerCustomizer
bean 可用于自定义构建的 SimpleAsyncTaskScheduler
。构建器将自动配置为使用它们。
⑥ 使 JVM 保持活动状态
现在有一个新属性叫做 spring.main.keep-alive
。当设置为 true
时,即使所有其他线程都是虚拟线程(或守护线程),JVM 也会保持活动状态。
⑦ 特定技术集成
启用虚拟线程时,以下特定技术集成适用:
- 为 RabbitMQ 监听器自动配置了一个虚拟线程执行器。
- 为 Kafka 监听器自动配置了一个虚拟线程执行器。
- Spring Data Redis 的
ClusterCommandExecutor
将使用虚拟线程。 - Spring for Apache Pulsar 将为自动配置的
ConcurrentPulsarListenerContainerFactory
和DefaultPulsarReaderContainerFactory
使用VirtualThreadTaskExector
。
1.12 对 JVM 检查点/恢复的初始支持
Spring Boot 3.2 附带对 JVM 检查点/恢复(Project CRaC)的初始支持。有关更多详细信息,请参阅相关文档。
1.13 SSL 捆绑包重新加载
现在可以在信任材料发生变化时自动重新加载 SSL 捆绑包。捆绑包必须选择启用此功能,将其 reload-on-update
属性设置为 true
。捆绑包的使用者也必须支持重新加载。
支持重新加载的使用者包括:
- Netty Web 服务器
- Tomcat Web 服务器
有关 SSL 捆绑包重新加载的更多信息,可以在参考文档中找到。
1.14 可观测性改进
您现在可以使用 Micrometer 的 @Timed
、@Counted
、@NewSpan
、@ContinueSpan
和 @Observed
注解。如果类路径上有 AspectJ,它们的 aspects 现在将自动配置。
Micrometer Tracing 的 ObservationHandler
bean 现在自动注册到 ObservationConfig
。在 Spring Boot 3.2.0 之前,未分类的处理程序会在分类处理程序之前注册。现在这一点已被颠倒,分类的处理程序现在会在未分类的处理程序之前注册。有关详细信息,请参阅 #34399。
B3 跟踪传播的默认格式已从 single-no-parent 更改为 single。
@Scheduled
方法现在已针对可观测性进行了检测。
已添加了对 R2DBC 的可观测性支持。要启用它,请在项目中包含 io.r2dbc:r2dbc-proxy
依赖项。
① 属性
现在有一个名为 spring.reactor.context-propagation
的新配置属性,用于控制反应式管道中的上下文传播。要在您的反应式管道中自动传播观察结果、跟踪 id 和 span id,请将该属性设置为 auto
。
现在可以通过属性禁用以特定前缀开头的观察结果。例如,要防止 Spring Security 报告观察结果,请设置 management.observations.enable.spring.security=false
。
属性 management.observations.key-values.*
可用于自动将低基数键值应用于所有观察结果。例如,设置 management.observations.key-values.region=us-west
将向所有观察结果添加键 region
和值 us-west
。
② OpenTelemetry
如果在上下文中找到 OpenTelemetry MeterProvider
bean,它将自动注册到 BatchSpanProcessor
。
OpenTelemetry 的自动配置已经改进。如果上下文中有 SdkLoggerProvider
或 SdkMeterProvider
类型的 bean,它将自动注册到 OpenTelemetry
bean 上。此外,OpenTelemetry 的 Resource
现在作为 bean 暴露,并且有一个新的配置属性 management.opentelemetry.resource-attributes
,用于配置资源属性。
如果您正在使用 OpenTelemetry 并希望对应用的 SpanProcessor
有更多控制,您现在可以定义一个 SpanProcessors
类型的 bean。默认情况下,所有可用的 SpanProcessor
bean 都会应用。对于 OpenTelemetry 的 SpanExporter
,使用 SpanExporters
bean 来覆盖默认值。默认情况下,它会应用所有可用的 SpanExporter
bean。
③ Micrometer 1.12 中更广泛的示例支持
Micrometer 1.12 包括一个扩大示例支持的功能,这需要 Prometheus 2.43 或更高版本。如果您使用的是 2.43.0 之前的 Prometheus 版本,并且您正在使用 Micrometer Tracing,请升级到 Prometheus >= 2.43.0,否则指标将不再显示。
④ 测试中的可观测性
在 Spring Boot 3.2 之前,当运行集成测试时,整个 Micrometer Tracing、Brave 和 OpenTelemetry 基础设施都会被禁用。这一点已经过修改:只有最少数量的 bean 被禁用,因此不会向后端发送任何 span(有关将被禁用的 bean 列表,请参阅 #35354)。如果您有自定义的 Brave SpanHandler
或 OpenTelemetry SpanExporter
bean,请务必使用 @ConditionalOnEnabledTracing
注解对它们进行注解,这样在运行禁用了可观测性的集成测试时,它们就不会被创建。
如果您希望在启用可观测性的情况下运行集成测试,您可以在测试类上使用 @AutoConfigureObservability
注解。
1.15 Docker 镜像构建
默认的 CNB 构建器已升级
当使用 Maven 和 Gradle 插件构建镜像时,使用的默认 CNB 构建器已经更改。当应用### 直译续
GraalVM 插件到构建时,新的默认构建器是 paketobuildpacks:builder-jammy-tiny
。否则,新的默认构建器是 paketobuildpacks:builder-jammy-base
。有关这些构建器的更多信息,请参阅 Paketo 文档。
以前的默认构建器包含了基于 Ubuntu 18.04 的运行映像,而新的默认值包含了基于 Ubuntu 22.04 的运行映像。这意味着使用新的默认值构建的任何映像都将基于 Ubuntu 22.04。
Docker 主机配置
spring-boot:build-image
Maven 目标和 bootBuildImage
Gradle 任务现在使用 Docker CLI 配置文件来确定要使用的 Docker 守护进程的主机地址和其他连接详细信息。有关更多信息,请参阅 Gradle 和 Maven 插件文档。
用于缓存的绑定挂载
现在可以配置 CNB 构建器和 buildpack 使用的构建和启动缓存,以使用绑定挂载而不是命名卷。BitBucket CI 的用户要求提供此功能,因为它们不允许从 CI 管道访问卷。有关更多信息和示例,请参阅 Maven 和 Gradle 文档。
构建工作区配置
现在可以配置 CNB 构建器和 buildpack 使用的临时构建工作区,以使用绑定挂载或自定义命名卷。有关更多信息和示例,请参阅 Maven 和 Gradle 文档。
安全选项配置
现在可以自定义应用于 CNB 构建器容器的安全选项,以支持不允许使用默认 Linux 安全选项 label=disable
的 Docker 环境。有关更多信息,请参阅 Maven 和 Gradle 文档。
对 Spring for GraphQL 的可调用支持
现在Spring for GraphQL 被自动配置为使用 applicationTaskExecutor
。这为控制器方法返回 Callable
提供了开箱即用的支持。
其他 OAuth2 令牌验证器
自动配置的 JwtDecoder
或 ReactiveJwtDecoder
现在将使用任何 OAuth2TokenValidator<Jwt>
bean 进行令牌验证。它们包含在配置为解码器的验证器的 DelegatingOAuth2TokenValidator
中。
对 ActiveMQ 的服务连接支持
已添加对 ActiveMQ 的 ServiceConnection
支持,并针对 Testcontainers 和 Docker Compose 提供了集成。该集成使用 symptoma/activemq
镜像。
对 Neo4j 的 Docker Compose 支持
Spring Boot 的 Docker Compose 集成现在支持 Neo4j。您必须在 compose YAML 中配置 NEO4J_AUTH
环境变量,以禁用身份验证(值为 none
)或为 neo4j
用户设置密码(值为 neo4j/your-password
)。
WebSocketServerSpec 配置
自动配置使用的 WebSocketServerSpec
现在可以使用 spring.rsocket.server.spec
命名空间下的属性进行自定义。
Neo4j AuthTokenManager
如果定义了 AuthTokenManager
bean,它将用于 Neo4j 的身份验证。这种 bean 优先于 spring.neo4j.authentication.*
属性。如果定义了自定义 Neo4jConnectionDetails
(例如用于 Testcontainers 或 Docker Compose 管理的数据库的服务连接),则会忽略 AuthTokenManager
bean。
RabbitMQ
SSL 捆绑包支持
现在可以使用 spring.rabbitmq.ssl.bundle
属性将 RabbitMQ 连接配置为使用来自 SSL 捆绑包的信任材料。这提供了一种替代方法,而不是使用现有的 spring.rabbitmq.ssl
属性提供 Java 密钥库文件作为信任材料。
限制消息正文大小
最新版本的 RabbitMQ Java 客户端默认将传入消息的正文大小限制为 64MB。spring.rabbitmq.max-inbound-message-body-size
配置属性已引入,用于自定义此限制。
RabbitMQ Stream 的虚拟主机支持
已添加对 RabbitMQ Stream 的虚拟主机支持。如果没有显式设置,RabbitMQ Stream 的虚拟主机将自动使用为 RabbitMQ 配置的虚拟主机。要为 RabbitMQ Stream 使用特定的虚拟主机,请设置 spring.rabbitmq.stream.virtual-host
。
Kafka
SSL 捆绑包支持
现在可以使用 spring.kafka.ssl.bundle
属性将 Kafka 连接配置为使用来自 SSL 捆绑包的信任材料。这提供了一种替代方法,而不是使用现有的 spring.kafka.ssl
属性提供 Java 密钥库文件作为信任材料。
JMS 会话
已引入新属性用于配置自动配置的 JmsTemplate
创建的会话:
spring.jms.template.session.acknowledge-mode
spring.jms.template.session.transacted
类似地,还引入了 spring.jms.listener.session.transacted
属性,用于自动配置的 JmsMessageListenerContainer
。
为与这些新属性保持一致,请注意,现有的 spring.jms.listener.acknowledge-mode
属性已被弃用,并引入了### 直译续
spring.jms.listener.session.acknowledge-mode
作为替代。
Oracle UCP 数据源上的连接验证
已删除了 Oracle UCP 数据源上连接验证的默认值。在 3.2.0-RC1 之前,默认情况下启用了连接验证,现在不再是这种情况。如果您需要连接验证,请将配置属性 spring.datasource.oracleucp.validate-connection-on-borrow
设置为 true
。
testAndDevelopmentOnly Gradle 配置
除了 developmentOnly
,Spring Boot 的 Gradle 插件现在还创建了一个 testAndDevelopmentOnly
配置。与 developmentOnly
不同,此新配置中的依赖项将包含在测试编译和运行时类路径中。它主要供那些在开发时使用 Testcontainers 的应用程序使用。
其他
除了上述更改之外,还有许多小的调整和改进,包括:
- 现在可以使用配置属性
spring.jackson.datatype.enum.
和spring.jackson.datatype.jsonnode.
分别启用和禁用 Jackson 的EnumFeature
和JsonNodeFeature
中声明的功能。 - 现在可以通过使用
Provider
为其他构建信息属性设置延迟值。 - 事务管理器自定义现在适用于任何类型的
TransactionManager
,而不仅仅是PlatformTransactionManager
。 - 任何
TransactionExecutionListener
bean 现在都会添加到自动配置的事务管理器中。 - 当嵌入式 WebServer 启动时记录的端口信息已得到改进和统一。
- 新增加的属性
spring.servlet.multipart.strict-servlet-compliance
用于设置是否仅对multipart/form-data
请求使用多部分处理。 - 当欢迎页面的处理程序收到无效的
Accept
头时,已减少日志记录,并会退回到接受所有 MIME 类型。 - 已添加
RestClientBuilderConfigurer
,可用于将 Spring Boot 的默认设置应用于RestClient.Builder
。 restTemplateBuilderConfigurer
bean 不再退出定义了用户 bean。如果您之前有自己的restTemplateBuilderConfigurer
bean,请将其删除。- 已添加一个属性,可用于配置 Jetty 服务器的最大连接数。
- 已添加一个新属性,可用于在使用 PEM SSL 捆绑包时验证密钥。
- 以编程方式创建
PemSslStoreBundle
时,现在可以提供密钥库密码。 - 如果未明确设置
service.name
,现在将使用spring.application.name
作为 OpenTelemetry 的service.name
。 - 已添加一个新属性,可用于配置 OTLP 注册表中导出指标的基本
TimeUnit
。 - 现在有了 OTLP 指标和跟踪的连接详细信息支持。如果使用 Testcontainers 或 Docker Compose 与
otel/opentelemetry-collector-contrib
镜像,将自动创建连接详细信息 bean。 - 已添加对使用 Wavefront 时的 CSP 身份验证的支持。
- 一个新属性
flyway.postgresql.transactional-lock
可用于配置 Flyway 对 PostgreSQL 的事务锁定使用。 - 添加了对 Kafka MessageListenerContainer
changeConsumerThreadName
属性的支持。 - 自动配置
Function<MessageListenerContainer, String>
bean 到 Kafka MessageListenerContainer 的threadNameSupplier
。 - 已引入新的
@ConditionalOnThreading
注解,以帮助自动配置虚拟线程相关的问题。 - 添加了对 RabbitMQ 容器
forceStop
属性的支持。 - 基于
WebClient
的 Zipkin 发送器现在会遵守通过配置属性设置的超时。有关详细信息,请参阅 #36264。 - 当在启用了 AOT 模式但构建中没有进行 AOT 处理的情况下启动应用程序时,错误消息现在更加明确。
- 在使用 GraalVM 时,现在自动提供了
messages.properties
和messages_*.properties
的资源提示。 - 现在提供了 Kotlin 序列化的依赖项管理。
- Awaitility (
org.awaitility:awaitility
) 现在是spring-boot-starter-test
的一部分。 - 在使用
@JdbcTest
和@DataJpaTest
的测试中,自动配置的JdbcClient
bean 现在可用。 - 在自动配置
MockMvc
时,现在使用它们的注册 bean 的分派器类型和初始化参数注册过滤器。 - 现在可以并行初始化 Testcontainers。为此,请将
spring.testcontainers.beans.startup
设置为parallel
。 - 支持
spring.kafka.template.observation-enabled
属性,以支持 Micrometer 观察。
3.2.0废除的
OkHttp 3 的支持已被弃用,有利于 OkHttp 4
spring-boot:run
、spring-boot:start
和spring-boot:test-run
Maven 目标的directories
属性已被弃用,有利于additionalClasspathElements
。- 定义在
LoggingSystemProperties
和LogbackLoggingSystemProperties
中的大多数常量已被弃用,改为使用枚举值。 ClientHttpRequestFactorySettings
和RestTemplateBuilder
中启用请求缓冲的支持已被弃用。虽然 API 以弃用的形式保留,但配置它将不会产生任何效果,这与 Spring Framework 6.1 中的类似更改一致。- 使用
context.initializer.classes
环境属性注册额外的ApplicationContextInitializer
已被弃用,改为以编程方式或在 spring.factories 中注册每个代理。 - 使用
context.listener.classes
环境属性注册额外的ApplicationListener
已被弃用,改为以编程方式或在 spring.factories 中注册每个代理。 - 由扩展程序管理的 Flyway 属性已移动到专用命名空间。因此,
flyway.oracle*
属性已移动到flyway.oracle.*
。同样,spring.flyway.sql-server-kerberos-login-file
已移动到spring.flyway.sqlserver.kerberos-login-file
。 - InfluxDB 的支持已被弃用,有利于新的 InfluxDB Java 客户端及其自己的 Spring Boot 集成。
- 配置属性
management.otlp.metrics.export.resource-attributes
已被弃用,有利于新的management.opentelemetry.resource-attributes
。 TaskExecutorBuilder
已被弃用,有利于ThreadPoolTaskExecutorBuilder
。TaskSchedulerBuilder
已被弃用,有利于ThreadPoolTaskSchedulerBuilder
。- 配置属性
spring.jms.listener.concurrency
的替代品是spring.jms.listener.min-concurrency
。 - 配置属性
spring.jms.listener.acknowledge-mode
的替代品是spring.jms.listener.session.acknowledge-mode
。 PlatformTransactionManagerCustomizer
的替代品是TransactionManagerCustomizer
。TransactionManagerCustomizers(Collection<? extends PlatformTransactionManagerCustomizer<?>>)
的替代品是TransactionManagerCustomizers#of(Collection<? extends TransactionManagerCustomizer<?>>)
。- 不再推荐使用
DelegatingApplicationContextInitializer
和DelegatingApplicationListener
,因为基于属性的初始化不再推荐。 PemSslStoreBundle
中的一些过时的构造函数以及PemSslStoreDetails
中的certificate
访问器已被弃用。TaskExecutorCustomizer
已被弃用,有利于ThreadPoolTaskExecutorCustomizer
TaskSchedulerBuilder
已被弃用,有利于ThreadPoolTaskSchedulerBuilder
TaskSchedulerCustomizer
已被弃用,有利于ThreadPoolTaskSchedulerCustomizer
NettyWebServer
中的一些过时的构造函数已被弃用本文由博客一文多发平台 OpenWrite 发布!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。