Spring Cloud Data Flow 停止开源

TL;DR; 今天,官方宣布今后将不再以开源项目的形式维护 Spring Cloud Data Flow、Spring Cloud Deployer 或 Spring Statemachine。Spring Cloud Data Flow 2.11.x、Spring Cloud Deployer 2.9.x 和 Spring Statemachine 4.0.x 将是最后一批开源项目,今后的版本将仅提供给 Tanzu Spring 客户。这一变更不会影响 Spring 开源产品组合的其他部分,也不会影响现有用户对当前可用开放源码软件版本的支持义务。 Spring Cloud Data Flow 起源于八年前的 Spring XD,用于协调批处理和流工作负载,多年来在客户中取得了巨大成功。然而,为了让 Spring Cloud Data Flow 和相关生态系统项目在未来以可持续的方式发展下去,我们决定只将 Spring Cloud Data Flow 作为商业产品发布。 这一决定并不是轻易做出的,其主要原因是这些项目在我们的社区中得到了广泛采用。我们所看到的 Spring Cloud Data Flow 的绝大多数使用情况都发生在我们的 Tanzu 企业客户中。目前,开源应用只占总体应用的很小一部分,而社区提供的维护贡献同样很小。在过去的两年中,Spring Cloud Data Flow 的维护工作几乎完全由 Tanzu 的研发团队负责,而 Spring 产品组合中的绝大多数产品则由充满活力的社区以多种方式进行维护。Spring Statemachine 和 Spring Cloud Deployer 的采用模式与 Spring Cloud Data Flow 相似,它们的使用主要是由于 Spring Cloud Data Flow 中包含了 Spring Statemachine 和 Spring Cloud Deployer。

Spring WebClient 设置 Header

1、简介 WebClient 是 Spring WebFlux 中的一个 HTTP 客户端工具类,可以实现同步和异步 HTTP 请求。 本文将带你了解在 Spring WebClient 中设置 Header 的几种方式。 2、WebClient 如何处理 Header? 一般来说,HTTP 请求中的 Header 起到元数据的作用。它们包含认证详细信息、内容类型、版本等信息。 在 WebClient 中,HttpHeaders 类负责管理 Header。这是一个 Spring 框架类,专门用于表示请求和响应头。该类实现了 MultiValueMap<String, String>,允许一个 Header Key 有多个 Value。 这为需要多个值的 Header(如 Accept)提供了灵活性。 3、在 WebClient 中设置 Header 有几种方法可以为请求添加 Header。根据使用情况,我们可以为单个请求设置 Header,为整个 WebClient 实例定义全局 Header,或动态修改 Header。 3.1、为单个请求设置 Header 如果 Header 是针对单个请求的,并且因端点而异,那么直接的方法就是在请求中直接设置它们。 一个简单的示例如下。例化 WebClient,在请求中添加了两个 Header,并断言这些 Header 已通过请求发送。使用 okhttp3 库中的 MockWebServer 来模拟服务器响应并验证 WebClient 的行为: @Test public void givenRequestWithHeaders_whenSendingRequest_thenAssertHeadersAreSent() throws Exception { mockWebServer.

在 Spring Boot 中通过 Profile 启用或禁用嵌入式 Tomcat

1、概览 默认情况下,Spring Boot 提供嵌入式 Tomcat 服务器,但在某些情况下,我们可能希望根据应用的需求来禁用/启用它。 对于不需要 Web 服务的 Spring Boot 应用,禁用 Tomcat 可以节省资源。 2、理解 Spring Boot 中的嵌入式 Tomcat Spring Boot 在应用的可执行 JAR 文件中捆绑了嵌入式 Tomcat 服务器,从而简化了应用的部署。这种方法消除了安装和配置外部 Tomcat 实例的需要,使开发和部署更加高效。 Spring Boot 使用 Spring Boot Starter 来包含嵌入式 Tomcat 的必要依赖。默认情况下, spring-boot-starter-web Starter 会在 Tomcat 出现在 classpath 中时自动配置和初始化 Tomcat。 2.1、嵌入式 Tomcat 的优势 Spring Boot 的嵌入式 Tomcat 服务器具有多种优势: 简化部署:无需安装外部 Tomcat 服务器。 独立的应用:应用程序可打包为 JAR 文件,在任何地方运行。 自动配置:Spring Boot 根据依赖自动配置 Tomcat。 灵活:可轻松替换为 Jetty 或 Undertow 等其他嵌入式服务器。 2.2、为什么要禁用 Tomcat 服务器? 虽然嵌入式 Tomcat 很有用,但在某些情况下,禁用它对我们也有好处:

解决 DateTimeParseException: “Unable to obtain LocalDateTime from TemporalAccessor” 异常

1、概览 在 Java 中使用 java.time 包处理日期和时间非常高效,但有时我们可能会遇到 DateTimeParseException 异常,提示 “Unable to obtain LocalDateTime from TemporalAccessor(无法从 TemporalAccessor 获取 LocalDateTime)”。出现这种问题的原因通常是预期的日期时间格式与实际输入不兼容。 本文将带你了解出现该异常的原因以及解决办法。 2、理解异常 当 Java 的日期时间解析器无法从 TemporalAccessor(如 LocalDate、ZonedDateTime 或 OffsetDateTime)中提取有效的 LocalDateTime 对象时,就会出现 “Unable to obtain LocalDateTime from TemporalAccessor” 异常。根本原因通常是输入字符串格式不当或不完整。 LocalDateTime 需要 日期 和 时间 两个部分。如果输入字符串缺少所需的部分或不符合预期的格式,解析过程就会失败,从而产生此异常。很多人认为 Java 可以自动推断缺少的时间值,但事实并非如此。 示例如下,解析一个日期字符串为 LocalDateTime 的错误例子: public static void main(String[] args) { String dateTimeStr = "20250327"; // 只有日期,没时间 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd"); LocalDateTime localDateTime = LocalDateTime.parse(dateTimeStr, formatter); } 执行该代码时,会出现以下异常: java.time.format.DateTimeParseException: Text '20250327' could not be parsed: Unable to obtain LocalDateTime from TemporalAccessor: {},ISO resolved to 2025-03-27 of type java.

Maven 预定义属性详解

1、简介 本文将带你了解 Maven 中的预定义属性。 2、Maven 预定义属性 Maven 有一些方便的内置属性,可以于简化配置。 如果需要,甚至可以直接在 pom.xml 文件中自定义它们。 这些属性也可以在任何由 Maven 资源插件的过滤功能处理的资源文件中使用,例如 application.properties 文件。在使用这些属性时,只需要将它们包装在 ${} 中。 2.1、使用示例 示例如下,使用输出目录位置属性: <?xml version="1.0" encoding="UTF-8"?> <project> <modelVersion>4.0.0</modelVersion> <groupId>example.override.properties</groupId> <artifactId>parameter-maven-plugin</artifactId> <version>1.0-SNAPSHOT</version> <packaging>maven-plugin</packaging> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-plugin-plugin</artifactId> <version>3.2</version> <configuration> <outputDirectory>${project.build.directory}</outputDirectory> </configuration> </plugin> </plugins> </build> </project> 上面的示例展示了如何获取 ${project.build.directory} 的默认值,即 src/main/resources。 2.2、属性覆盖示例 自定义构建路径的属性: <?xml version="1.0" encoding="UTF-8"?> <project> <modelVersion>4.0.0</modelVersion> <groupId>example.override.properties</groupId> <artifactId>parameter-maven-plugin</artifactId> <version>1.0-SNAPSHOT</version> <packaging>maven-plugin</packaging> <build> <directory>src/main/resources/custom</directory> </build> </project> 如上,通过在 <project> -> <build> -> <directory> 中指定自定义值,将 ${project.build.directory} 属性的默认值覆盖为 src/main/resources/custom。

Spring AI 1.0.0-SNAPSHOT:重要变更和更新说明

Spring AI 1.0.0-SNAPSHOT 在构件 ID、依赖管理和自动配置方面引入了几项重要变更。 本文将带你了解这些变更并提供项目更新指南。 最显著的变更是 Spring AI Starter 构件的命名模式: 模型 starter:spring-ai-{model}-spring-boot-starter → spring-ai-starter-model-{model} 向量存储 starter:spring-ai-{store}-store-spring-boot-starter → spring-ai-starter-vector-store-{store} MCP starter:spring-ai-mcp-{type}-spring-boot-starter → spring-ai-starter-mcp-{type} 此外,你需要添加快照仓库并更新 Dependency Management (依赖管理)配置。 有两种方式可以将项目更新到 Spring AI 1.0.0-SNAPSHOT:使用 AI 工具自动更新 或 手动更新。自动方式利用 Claude Code 快速转换你的项目,而手动方式为那些喜欢直接进行更改的人提供了逐步说明。 使用 Claude Code 自动更新 对于偏好自动化方式的用户,你可以使用 Claude Code CLI 工具,通过提供的提示自动将项目升级到 1.0.0-SNAPSHOT。这种方法可以在升级多个项目或复杂代码库时节省时间并减少错误。更多详情,请参阅升级说明中的 使用 AI 自动升级 部分。 这里仅以屏幕截图的形式展示 Claude Code CLI 工具将执行的步骤。 更新 BOM 版本。 添加仓库。 更新 starter。 全部完成! 手动更新 添加快照仓库 要使用 1.0.0-SNAPSHOT 版本,你需要在构建文件(pom.xml)中添加相应的快照仓库。其中,Central Sonatype Snapshots 仓库(https://central.

动态忽略 Jackson 中的字段

1、简介 本文将带你了解如何在 Jackson 中通过 @JsonFilter、@JsonView 和 Jackson Mixin(混合) 实现动态忽略字段。 2、项目设置 添加 Jackson 库: <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.17.2</version> </dependency> 最新版本可在 此处 找到。 3、使用 @JsonFilter 第一种方法是通过 @JsonFilter 注解指定在序列化过程中使用的过滤器。 使用 @JsonFilter 对类进行注解: @JsonFilter("publicFilter") // 指定 Filter 名称 public class UserWithFilter { private Long id; private String name; //Getter/Setter 忽略 } 然后,动态配置 ObjectMapper,并注册 PropertyFilter 来序列化除 id 之外的所有字段: SimpleFilterProvider filterProvider = new SimpleFilterProvider(); // 注册 Filter,指定名字 filterProvider.addFilter("publicFilter", SimpleBeanPropertyFilter.serializeAllExcept("id")); ObjectMapper objectMapper = new ObjectMapper().setFilterProvider(filterProvider); 然后,使用 objectMapper 序列化 UserWithFilter 对象:

Spring Boot 无缝接入 DeepSeek 和通义千问

本文将带你了解如何在 Spring Boot 中使用 spring-ai 无缝接入 DeepSeek 和通义千问来构建自己的 AI 应用。 Spring & JDK 版本: springboot 3.4.3 jdk17 1、maven依赖 <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai-spring-boot-starter</artifactId> </dependency> 2、application.yaml 配置 # DeepSeek 配置,完全兼容openai配置 # spring: # ai: # openai: # base-url: https://api.deepseek.com # DeepSeek的OpenAI式端点 # api-key: sk-xxxxxxxxx # chat.options: # model: deepseek-chat # 指定DeepSeek的模型名称 # 通义千问配置 spring: ai: openai: base-url: https://dashscope.aliyuncs.com/compatible-mode # 通义千问 api-key: sk-xxxxxxxxxxx chat.options: model: qwen-plus 3、Controller package org.example.springboot3ds.controller; import jakarta.annotation.PostConstruct; import jakarta.annotation.Resource; import org.

使用 JSpecify 和 NullAway 实现 Spring 应用 Null Safety

Null Safety 旨在防止空指针(NullPointerException)异常。 最初在 Spring 中引入 Null Safety 支持要追溯到 2017 年发布的 Spring Framework 5.0。2025 年,我们会继续完善这一功能,为 Java 或 Kotlin 的 Spring 开发人员带来更多附加值。 我们要解决什么问题? 举一个具体的例子,假设我们正在使用一个提供 TokenExtractor 接口的库,其定义如下: interface TokenExtractor { /** * Extract a token from a {@link String}. * @param input the input to process * @return the extracted token */ String extractToken(String input); } 如果由于某种原因实现返回 null 值,在 token.length() 中访问 null 引用(如下所示)会导致 NullPointerException 异常,通常会在运行时产生状态码为 500 Internal Server Error 的 HTTP 响应。

Spring Boot 启用 HTTP2

1、概览 HTTP/2 是广泛使用的 HTTP/1.1 协议的后续协议,它通过采用多路复用和 Header 压缩等新功能提高了网络性能。 本文将带你了解如何配置 Spring Boot 应用,以在嵌入式 Tomcat 服务器上启用 HTTP/2。 2、HTTP/2 超文本传输协议(HTTP)是一种在互联网上获取资源的应用协议。HTTP/1.1 于 1997 年 1 月发布,二十多年来为大多数网络提供服务。该版本发现了在某些情况下导致性能缓慢的问题。 HTTP/2 克服了 HTTP/1.1 中的性能问题,具有以下特点: 多路复用 - HTTP/1.1 使用多个连接发送多个请求;多路复用允许通过单个连接发送请求,从而减少资源消耗和延迟 Header 压缩 - 如果不进行压缩,由于 TCP 启动速度较慢,通常需要多次往返才能发送 Header;压缩 Header 后,Header 的发送往返次数会减少,大部分时间都能在一次往返内完成 二进制 - 与使用文本编码数据的 HTTP/1.1 相比,HTTP/2 以二进制格式发送数据,以减少解析开销并缩小报文大小。 3、先决条件 HTTP/2 可以通过明文或 TLS 运行。大多数 Web 浏览器不支持明文 HTTP/2,因此建议通过 TLS 运行。 首先要在嵌入式 Web 服务器上启用 SSL。 在控制台中运行以下 keytool 命令来生成一个 keystore,用于存储 SSL/TLS 使用的密钥和证书,并将其放入嵌入式 Tomcat 中。 $ keytool -genkeypair -alias http2-alias -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore keystore.