Spring AI 1.0 正式 GA

Spring AI 1.0 正式发布。 快速开始 构件已经发布到 maven central,可以通过提供的 bom 导入依赖项。 <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-bom</artifactId> <version>1.0.0</version>0 <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> 请查看 升级说明,了解最新的更改和升级方法。注意:你可以使用 OpenRewrite Recipe 自动升级到 1.0.0-GA。这可帮助应用此版本的许多必要代码更改。可在 Arconia Spring AI Migrations 查找使用说明。 你可以在 Intialzr 网站上开始创建 1.0 GA 应用,并阅读参考文档中的 “入门” 部分。 博客 这有一些博客精选,这些博客展示了如何以各种方式使用 Spring AI: 微软 Azure 博客 和 视频。特别感谢 Asir Selvasingh,他在 2023 年拉斯维加斯 Spring One 大会上帮助我们 发布了 Spring AI AWS - 博客 - Spring AI 1.0 为广大开发人员带来人工智能技术 Google - 博客 - Google Cloud 和 Spring AI 1.

在同类中直接调用 Spring Aop 代理方法

1、概览 在使用 Spring AOP 时有许多错综复杂的问题。其中一个常见问题是如何处理同一类中的方法调用,因为这种直接调用会使 AOP 功能失效。 本文将带你了解 Spring AOP 的工作原理以及如何解决同类中 AOP 方法直接调用导致的 AOP 功能失效的问题。 2、代理 和 Spring AOP 代理对象可以看作是一个 “包装”,它可以在调用目标对象时添加功能。 在 Spring 中,当一个 Bean 需要额外功能时,就会创建一个代理,并将代理注入到其他 Bean 中。例如,如果某个方法具有事务(Transactional)注解或任何缓存注解,那么该代理就会被用来在调用目标对象时添加所需的功能。 3、AOP:内部方法调用和外部方法调用 如上所述,Spring 创建的代理添加了所需的 AOP 功能。 来看一个缓存示例,看看在内部和在外部调用方法有何不同: @Component @CacheConfig(cacheNames = "addOne") public class AddComponent { private int counter = 0; @Cacheable public int addOne(int n) { counter++; return n + 1; } @CacheEvict public void resetCache() { counter = 0; } } 当 Spring 创建 AddComponent Bean 时,也会创建一个代理对象,以添加用于缓存的 AOP 功能。当另一个对象需要 AddComponent Bean 时,Spring 会提供代理对象用于注入。

Maven 输出版本号到文本文件

1、概览 在基于 Maven 的 Java 项目中,经常需要将项目版本号输出到文本文件中。用于版本跟踪、日志记录以及确保不同构建和部署之间的一致性。 Maven 会在 pom.xml 文件中的 <version> 标签下维护项目版本。利用 Maven 的资源过滤(Resource Filtering)功能和附加插件,我们可以在构建过程中自动提取并存储该版本号。 本文将带你了解 Mave 实现版本号输出的两种方法:第一种是使用 Maven Resources Plugin,第二种是使用 Maven Antrun Plugin。 2、使用 Maven Resources Plugin Maven 资源插件通常用于文件过滤,允许用 pom.xml 中定义的值替换资源文件中的占位符。 该插件可以在构建过程中直接在资源文件中动态插入项目属性(version、artifactId、groupId)。 2.1、启用资源过滤 首先配置 pom.xml 文件中的 <resources> 部分,以启用项目中资源文件的过滤功能。 <build> <resources> <resource> <directory>src/main/resources</directory> <!-- 启用资源过滤 --> <filtering>true</filtering> </resource> </resources> </build> <filtering>true</filtering> 此配置会告诉 Maven 处理 src/main/resources 目录中的所有文件,并应用过滤功能,用 Maven 项目属性(如 ${project.version})中的相应值替换任何占位符。 2.2、创建版本文件 接下来,在 src/main/resources 目录中创建一个资源文件(例如 version.txt)。该文件可包含 ${project.version} 等占位符,它们将在构建过程中被动态替换为 pom.xml 中定义的实际版本号。 如下,创建一个 version.txt 文件,内容如下:

Java Class-File API 指南

1、简介 Java Class-File(类文件) API 是在 JEP-484 中引入的,是 Java 24 的一部分。它旨在创建一个接口,允许在不依赖于 ASM 库的传统 JDK 内部复制实现的情况下进行类文件处理。 本文将带你了解如何从头开始构建类文件,以及如何使用类文件 API 将一个类文件转换为另一个类文件。 2、 Class-File 核心的 API Class-File 有三个核心元素: 元素 - 代表代码的一部分,如变量、指令、方法或类。此外,一个元素可能包含其他元素。例如,一个类元素可能包含方法元素,而方法元素又包括变量或指令元素。 构建器 -(如方法构建器和代码构建器)用于创建每种类型的元素。 转换函数 - 可用于使用构建器将元素转换为其他元素。 3、生成类文件 使用 MethodBuilder 和 CodeBuilder 类生成类文件。 3.1、示例方法 先来看一个简单的代码段,它根据员工的角色和基本工资计算员工的工资: public double calculateAnnualBonus(double baseSalary, String role) { if (role.equals("sales")) { return baseSalary * 0.35; } if (role.equals("engineer")) { return baseSalary * 0.25; } return baseSalary * 0.15; } 3.2、使用 MethodBuilder 和 CodeBuilder 我们可以使用 MethodBuilder 和 CodeBuilder 类来生成与 calculateAnnualBonus() 功能相同的方法

在 Protobuf 中使用 Map

1、简介 ProtoBuf 为结构化数据的序列化提供了一种快速高效的方式,它是 JSON 的紧凑型高性能替代品。 与基于文本并需要解析的 JSON 不同,protobuf 可生成适用于多种语言的优化代码。这使得在不同系统间发送结构化数据变得更加容易。 使用 protobuf,只需在 .proto 文件中定义一次数据结构。然后,就可以使用生成的代码来处理跨流和跨平台的数据传输。在处理类型化、结构化数据时,它是理想的选择,尤其是当 Payload 比较大的时候。 Protobuf 支持字符串、整数、布尔值和浮点数等常见类型。它们还能很好地与 List 和 Map 配合使用,使复杂的数据易于管理。 本文将带你了解如何在 protobuf 中使用 Map。 2、了解 Protobuf 中的 Map 2.1、Map 是什么? Map 是一种键值数据结构,类似于字典。 每个键都映射到一个特定的值,从而使查找快速高效。类似于 DNS 系统:每个域名都指向一个 IP 地址。 2.2、定义 Map 的语法 Protobuf 3 对 Map 提供了开箱即用的支持。 示例如下: message Dictionary { map<string, string> pairs = 1; } 使用 map<key_type, value_type> 定义字段。Key 必须是 scalar 类型,如 string、int32 或 bool。值可以是任何有效的 protobuf 类型 - scalar、enum 或其他消息。

Spring JDBC 的全面教程

1、概览 本文将带你全面了解 Spring JDBC 模块。 Spring JDBC 中的所有类都分为四个独立的包: core — JDBC 的核心功能。该软件包下的一些重要类包括 JdbcTemplate、SimpleJdbcInsert、SimpleJdbcCall 和 NamedParameterJdbcTemplate。 datasource — 用于访问数据源的工具类。它还有各种数据源实现,用于在 Jakarta EE 容器外测试 JDBC 代码。 object — 以面向对象的方式访问数据库。它允许运行查询并将结果作为业务对象返回。它还能在业务对象的列和属性之间映射查询结果。 support — core 包和 object 包下的类的支持类,例如提供 SQLException 翻译功能。 2、Maven 依赖 在 pom.xml 中添加 spring-boot-starter-jdbc 和 mysql-connector-j: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> <version>3.3.5</version> </dependency> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <version>9.1.0</version> </dependency> 然后,在 pom.xml 中添加 h2 依赖: <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>2.3.232</version> <scope>test</scope> </dependency> H2 数据库是一个嵌入式数据库,可用于快速原型开发。 3、配置 在 Spring 中配置数据源有两种主要方法:使用 properties 文件或使用基于 Java 的配置。

使用 Spring Validator 验证 Map

1、简介 Spring 的 Validation 框架主要设计用于 JavaBean,其中每个字段都可以通过注解来定义验证约束。 本文将带你了解如何使用 Spring 的 Validator 接口验证 Map<String,String>。 2、理解问题 - Hibernate Validator 和 Map 在实现自定义验证器之前,我们会自然地尝试直接在 Map 结构上使用标准约束注解,通过 Hibernate Validator 和 Spring 内置的 @Valid 和 @Validated 等验证机制来进行校验。不幸的是,这种方法并不像我们想象的那样有效。 来看一个示例: Map<@Length(min = 10) String, @NotBlank String> givenMap = new HashMap<>(); givenMap.put("tooShort", ""); Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); Set<ConstraintViolation<Map<String, String>>> violations = validator.validate(givenMap); Assertions.assertThat(violations).isNotEmpty(); // 测试失败 尽管在 Map 泛型上添加了约束注解,但校验结果 violations 仍是空的,即未检测到违反约束的情况。 2.1、为什么会校验失败? Hibernate Validator 或一般的 Bean Validation 是根据 JavaBean 惯例运行的,这意味着它会验证通过 getter 访问的对象属性。由于 Map 不会将键和值作为属性公开,因此 像 @Length 或 @NotBlank 这样的约束注解并不直接适用,在验证过程中会被忽略。

解决 Spring Boot 异常:“Cannot Load Driver Class: com.mysql.jdbc.driver”

1、简介 在 Spring Boot 中整合 MySQL 时,我们通常依赖 Spring Boot 的自动配置和 JDBC 支持来连接数据库。不过,遇到配置问题的情况并不少见,尤其是在使用 过时的依赖 时。其中一个异常就是: Cannot load driver class: com.mysql.jdbc.Driver 本文将带你了解出现 “Cannot load driver class: com.mysql.jdbc.Driver” 异常的原因以及解决办法。 2、理解原因 这个问题的根源在于使用了过时的 MySQL 驱动程序类。在早期版本的 MySQL JDBC 驱动程序 (Connector/J) 中,通常使用以下驱动程序类: spring.datasource.driver-class-name=com.mysql.jdbc.Driver 不过,从 MySQL Connector/J 8.0 开始,该类已被弃用并删除。更新后的驱动程序类是 com.mysql.cj.jdbc.Driver 如果在新版本的 MySQL 驱动程序中继续使用旧的类名,应用将无法启动,并出现 ClassNotFoundException 异常。 3、处理问题 要解决这个问题,需要更新 Spring Boot 配置和项目中使用的依赖。 3.1、使用正确的依赖 第一步是在 application.properties 或 application.yml 文件中新的驱动程序类替换旧的驱动程序类。 spring.datasource.url=jdbc:mysql://localhost:3306/mydb spring.datasource.username=root spring.datasource.password=secret # 新的驱动类 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 或者 application.yml 文件: spring: datasource: url: jdbc:mysql://localhost:3306/mydb username: root password: secret driver-class-name: com.

使用 Java Compiler API 编译 Java 代码

1、简介 在 Java 开发中,编译是防止语法错误、类型不匹配和其他可能导致项目失败的问题的第一道防线。传统的工作流程依赖于手动编译,而现代应用程序则需要动态编译检查。例如: 实时验证学生提交的代码的教育平台 在部署前对生成的代码片段进行编译的 CI/CD 流水线 动态编译用户自定义逻辑的低代码工具 热代码重载系统可即时重载开发人员所做的更改 创建 Java 插件 Java Compiler API 允许在 Java 应用程序中以编程式编译代码,从而实现上述应用场景。像 LeetCode 或 Codecademy 等平台可即时验证用户提交的代码。当用户点击 “运行” 时,后台会使用编译器 API 等工具编译代码段、检查错误并在沙盒环境中执行。程序化编译为这一即时反馈循环提供了动力。 本文将带你了解 Java Compiler 这一强大的工具。 2、Java Compiler API 概览 Java Compiler API 位于 javax.tools 包内,提供对 Java 编译器的编程式访问。该 API 对于需要在运行时验证或执行代码的动态编译任务至关重要。 Compiler API 的主要组件包括: JavaCompiler:启动编译任务的主编译器实例 JavaFileObject:代表 Java 源文件或类文件,可以是内存文件,也可以是基于文件的文件 StandardJavaFileManager:编译过程中管理输入和输出文件 DiagnosticCollector:捕获错误和警告等编译诊断信息 这些组件协同工作,可在 Java 应用程序中实现灵活高效的动态编译。 3、实现编译 JDK 环境默认提供 Compiler API,无需任何外部依赖。 现在,来看看如何编译内存中的 Java 代码。 3.1、在内存中创建源码 首先在内存中创建一个 Java 源码类: // 继承自 SimpleJavaFileObject public class InMemoryJavaFile extends SimpleJavaFileObject { private final String code; protected InMemoryJavaFile(String name, String code) { super(URI.

使用 Spring AI 从图片中提取结构化数据

1、概览 本文将带你了解如何使用 Spring AI 通过 OpenAI 聊天模型从图像中提取结构化数据。 OpenAI 聊天模型可以分析上传的图像并返回相关信息。它还能返回结构化的输出结果,这些输出结果可以很容易地通过管道输送到其他应用程序,以进行进一步操作。 举例说明,我们要创建一个 Web 服务,接收客户端上传的图像并将其发送给 OpenAI,以计算图像中彩色汽车的数量。Web 服务会以 JSON 格式返回颜色数量。 2、Spring Boot 配置 在 Maven pom.xml 中添加以下 Spring Boot Start Web 和 Spring AI Model OpenAI 依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>3.4.1</version> </dependency> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai-spring-boot-starter</artifactId> <version>1.0.0-M6</version> </dependency> 在 Spring Boot application.yml 文件中,必须要提供用于验证 OpenAI API 的 API 密钥(spring.ai.openai.api-key)和能够执行图像分析的聊天模型(spring.ai.openai.chat.options.model)的配置。 有多种支持图像分析的 模型,如 gpt-4o-mini、gpt-4o 和 gpt-4.5-preview。像 gpt-4o 这样的大模型知识面较广,但成本较高,而像 gpt-4o-mini 这样的小型模型成本较低,延迟也较小。我们可以根据自己的需求来选择型号。 本文选择使用 gpt-4o 模型: spring: ai: openai: api-key: "<YOUR-API-KEY>" chat: options: model: "gpt-4o" 配置完毕后,Spring Boot 就会自动加载 OpenAiAutoConfiguration 以注册 ChatClient 等 Bean。