1、简介 Java 中的转换(“Cast”)是一个基本概念,它允许将一种数据类型转换为另一种数据类型。它是在程序中有效操作对象和变量的关键过程。在现实世界中,“Cast” 类似于将一种单位的度量值转换为另一种单位的度量值,例如将英寸转换为厘米。
在 Java 的多态(Polymorphism)中,当超类引用子类的对象时,经常会使用到转换。例如,我们需要访问子类的特定方法或属性,就需要依靠转换来实现。这一点非常重要,因为 Java 是一种强类型语言,变量具有特定的数据类型。
本文将带你了解 Java Class.cast() 方法和 Cast(强转)操作符两个选项用法和差别,以及每个选项的最佳实践。
2、定义用例 以一个视频游戏角色的层次结构为例。
创建一个包含了超类 Character(角色)和子类 Warrior(战士)、Commander(指挥官)的示例。
该用例涉及创建 Warrior 和 Commander 的实例。这些实例存储在 Character 对象类型的集合中。之后,它们会被检索并转换回各自的特定类型。这种转换允许调用特定子类的方法。
3、定义 Model 类 首先,定义第一个继承自 Character 的子类,即实现了 obeyCommand() 方法的 Warrior:
public class Warrior extends Character { public void obeyCommand(String command) { logger.info("Warrior {} obeys a command {}", this.getName(), command); } } 然后,创建 Character 的第二个子类,即 Commander。这个子类实现了一个 issueCommand() 方法,可以向战士们发布命令:
public class Commander extends Character { public void issueCommand(String command) { log.
1、简介 本文将带你了解调整 JDBC 连接池大小的最佳策略。
2、什么是 JDBC 连接池,为什么要使用它? JDBC 连接池是一种用于有效管理数据库连接的机制。创建数据库连接需要几个耗时的步骤,如
打开数据库连接 验证用户身份 创建用于通信的 TCP Sokcet 套接字 通过套接字收发数据 关闭连接和 TCP Sokcet 套接字 为每个用户请求重复这些步骤的效率可能会很低,尤其是对于有许多用户的应用。JDBC 连接池通过提前创建一个可重复使用的连接池来解决这个问题。当应用程序启动时,它会在池中创建并维护数据库连接。池连接管理器负责管理这些连接并处理其生命周期。
当客户端请求连接时,连接池管理器会从连接池中提供一个连接,而不是创建一个新的连接。一旦客户端完成操作,连接就会返回池中重复使用,而不是关闭。这种连接的重复使用节省了时间和资源,大大提高了应用程序的性能。
3、为什么 JDBC 连接池的大小对应用来说很重要? 确定 JDBC 连接池的最佳大小对于平衡性能和资源利用率至关重要。较小的连接池可能会加快连接访问速度,但如果没有足够的连接来满足所有请求,则可能导致延迟。相反,较大的连接池可确保有更多连接可用,减少在队列中花费的时间,但可能会降低连接表的访问速度。
“连接表” 通常指的是管理和跟踪数据库连接的内部数据结构。它记录了当前连接的状态(如空闲、使用中等)以及相关的元数据,以便有效地分配和管理连接。这个“表”并不是数据库中的实际表,而是连接池实现中的一个逻辑概念。
下表总结了在确定连接池大小时需要考虑的利弊:
连接池大小 优点 缺点 较小的连接池 更快地访问连接表 可能需要更多连接来满足请求。请求在队列中停留的时间可能会更长 较大的连接池 有更多连接来满足请求。请求在队列中花费的时间减少(或没有) 降低访问连接表的速度 4、确定 JDBC 连接池大小时应考虑的要点 在确定池大小时,需要考虑几个因素。首先,应该评估平均事务响应时间和花费在数据库查询上的时间。负载测试可以帮助确定这些时间,建议在计算连接池大小时再增加 25% 的容量,以应对意外负载。其次,连接池应能根据实际需要进行增减。我们可以使用日志或 JMX 监视来监控系统,从而动态调整池的大小。
此外,还应考虑每次页面加载执行多少次查询以及每次查询的持续时间。为了获得最佳性能,我们可以从少量连接开始,然后逐渐增加。每个节点 8 到 16 个连接的池通常是最佳的。我们还可以根据监控统计数据调整空闲超时(Idle Timeout)和池大小调整数量(Pool Resize Quantity)值。
5、JDBC 连接池的基本控制设置 这些基本设置可控制池的大小:
连接池属性 说明 初始和最少连接数 池创建时的大小及其允许的最小连接数量 池最大连接数 连接池可维护的最大连接数量 池大小调整数量 空闲超时时要移除的连接数。闲置时间超过超时的连接将被移除,一旦连接池达到初始和最小连接池大小,就会停止移除。 最大空闲连接数 池中允许的最大闲置连接数。如果闲置连接数超过此限制,多余的连接将被关闭,从而释放资源 最小空闲连接数 在连接池中保留的空闲连接的最小数量 最大等待时间 应用等待连接可用的最长时间 验证查询 用于验证连接的 SQL 查询,然后再将其交给应用 6、调整 JDBC 连接池大小的最佳实践 以下是调整 JDBC 连接池以确保与数据库实例之间健康连接的一些最佳实践。
1、简介 本文将带你了解如何在 Spring Boot 应用中使用 ProblemDetail 响应错误信息,无论我们处理的是 REST API 还是 Reactive Stream(响应式流),它都提供了一种向客户端传达错误的标准化方式。
2、为什么要关注 ProblemDetail? 使用 ProblemDetail 来标准化错误响应对任何 API 都至关重要。
它可以帮助客户理解和处理错误,提高 API 的可用性和可调试性。这将带来更好的开发体验和更强大的应用。
采用它还有助于提供更翔实的错误信息,这对维护我们的服务和排除故障至关重要。
3、传统的错误处理方式 在 ProblemDetail 之前,我们经常在 Spring Boot 中实现自定义 ExceptionHandler 和 ResponseEntity 来处理错误。我们会创建自定义的错误响应结构。这导致了不同 API 之间的不一致性。
这种方式不仅需要大量的模板代码。而且,缺乏表示错误的标准化方式,因此客户端很难统一解析和理解错误信息。
4、ProblemDetail 规范 ProblemDetail 规范是 RFC 7807 标准的一部分。它为错误响应定义了一致的结构,包括诸如类型(type)、标题(title)、状态(status)、详情(detail)和实例(instance)等字段。这种标准化提供了一个通用的错误信息格式,有助于 API 开发人员和使用者。
实现 ProblemDetail 可确保我们的错误响应具有可预测性并易于理解。这反过来提高了我们的 API 和其客户端之间的整体沟通效果。
5、在 Spring Boot 中实现 ProblemDetail 在 Spring Boot 中有多种方法可以实现 ProblemDetail。
5.1、通过配置属性启用 ProblemDetail 我们可以添加一个配置属性来启用它。对于 RESTful 服务,在 application.properties 中添加以下属性:
spring.mvc.problemdetails.enabled=true 此属性可使 ProblemDetail 自动用于基于 MVC(servlet 栈)的应用中的错误处理。
1、概览 Java 21 在 java.lang.Character 类中引入了一组新方法,为 Emoji 表情符号提供更好的支持。通过这些方法,我们可以轻松检查某个字符是否是 Emoji 表情符号,并检查 Emoji 表情符号的属性和特征。
本文将带你了解这些新添加的方法,以及与 Java 21 中 Emoji 表情符号处理相关的关键概念。
2、Character API 的更新 Java 21 在 java.lang.Character 类中引入了六个与 Emoji 表情符号处理相关的新方法。所有新方法都是静态的,以代表字符 Unicode 码点的 int 作为参数,并返回 boolean 值。
Unicode 码点是分配给 Unicode 标准中每个字符的唯一数值。它代表不同平台和语言中的特定字符。例如,码点 U+0041 代表字母 A,十六进制形式为 0x0041。
现在,让我们来仔细看看这些与 Emoji 表情符号相关的新方法。
2.1、isEmoji() isEmoji(int codePoint) 方法是新 emoji 方法中最基本的方法。它接收代表字符 Unicode 码点的 int 值,并返回一个 boolean 值,表示该字符是否为 Emoji。
用法如下;
String messageWithEmoji = "Hello Java 21! 😄"; String messageWithoutEmoji = "Hello Java!
1、概览 本文将带你了解 Spring Boot @MockBeans 注解的用法。
2、示例项目 以一个简单的票据验证器(Ticket Validator)示例为例:
public class TicketValidator { private CustomerRepository customerRepository; private TicketRepository ticketRepository; public boolean validate(Long customerId, String code) { customerRepository.findById(customerId) .orElseThrow(() -> new RuntimeException("Customer not found")); ticketRepository.findByCode(code) .orElseThrow(() -> new RuntimeException("Ticket with given code not found")); return true; } } 如上,我们定义了 validate() 方法,用于检查数据库中是否存在给定数据。它依赖 CustomerRepository 和 TicketRepository。
现在,来看看如何使用 Spring 的 @MockBean 和 @MockBeans 注解创建测试和模拟依赖。
3、@MockBean 注解 Spring 框架提供了 @MockBean 注解,用于模拟依赖以进行测试。该注解允许我们定义特定 Bean 的模拟版本。新创建的模拟 Bean 将被添加到 Spring ApplicationContext 中。因此,如果已经存在相同类型的 Bean,它将被替换为模拟版本。
Spring Boot 中的 application.yaml / application.properties 配置文件用于定义应用运行时需要的配置属性。
Spring Boot 提供了强大的配置属性绑定功能,可以把配置文件中的属性绑定到 Java Bean,并且会根据 Java Bean 的字段类型对配置属性进行必要的转换。
绑定属性到 Bean 通过一个简单的示例来看看如何把配置文件中的配置属性绑定到 Bean,并且自动转换其类型。
本文使用的 Spring Boot 版本是 3.3.1。
创建 Spring Boot 项目 创建任意 Spring Boot 应用。
定义配置属性 在 src/main/resources 目录下创建 application.yaml 配置文件,并在其中定义如下自定义的配置属性:
app: # 数值 port: 8080 # 字符串 title: "Spring Boot 属性绑定测试" # Duration duration: 15s # DataSize data-size: 10MB # 集合 file-types: ["png", "jpeg"] 如上,在配置文件中定义了几个不同类型的配置属性。在本例中,这些配置属性的名称没有任何意义,随意取的。
定义配置 Bean 在 cn.springdoc.demo.prop 包下定义与配置文件中属性相对应的 Bean。
package cn.
更快的信息处理速度不仅能提供信息,还能改变我们的认知和创新方式。
Spring AI 是一个强大的框架,用于将 AI 能力集成到 Spring 应用中,现在已支持 Groq - 一个运行速度极快的 AI 推理引擎,并支持工具/函数调用。
利用 Groq 的 OpenAI 兼容 API,Spring AI 通过调整其现有的 OpenAI Chat 客户端实现了无缝集成。这种方法使开发人员能够通过熟悉的 Spring AI API 利用 Groq 的高性能模型。
本文将带你了解如何配置和使用 Spring AI OpenAI 聊天客户端与 Groq 进行连接。详细信息请查阅 Spring AI Groq 文档 和相关 测试。
Groq API Key 要与 Groq 交互,你需要从 https://console.groq.com/keys 获取 Groq API Key。
依赖 将 Spring AI OpenAI Starter 添加到项目中。
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai-spring-boot-starter</artifactId> </dependency> 对于 Gradle,在 build.gradle 中添加以下内容:
1、简介 本文将带你了解使用 Hibernate 时出现 “could not determine recommended JdbcType for class” 异常的原因,以及解决办法。
2、常见原因 出现该异常,通常是因为 JPA(Java Persistence API)抛出了异常。
这种情况发生在 JPA 无法确定类的推荐 JDBC 类型时。
通常,这会 Hibernate 应用启动期间发生,当 Hibernate 尝试创建数据库 Schema 或验证映射时。
3、复合数据类型 JPA 中出现 “could not determine recommended JdbcType for class” 错误的一个常见原因是,我们在实体类中使用了复合数据类型或其他非原始类型。一个典型的例子就是使用 java.util.Map 来存储动态键值对。
来看看下面这个实体类:
@Entity public class Student { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; // 使用了 Map private Map<String, String> studentDetails; // Getter/Setter 省略 } 在上例中,studentDetails 字段是 Map<String, String>。JPA 可能会抛出错误,因为它无法自动为这种复杂的数据类型确定推荐的 JDBC 类型。
今天遇到了一个面试题:Spring 中 Bean 的实例化有哪些方式?
大家知道,Spring 中 Bean 的配置方式有很多种,但是正常来说,无论你是 XML 文件配置,还是用类似 @Service 注解这种配置,本质上最终都是通过反射去完成 Bean 的初始化的;@Bean 注解则稍微特殊一点,往往我们在 @Bean 注解中是自己 new 出来目标 Bean,但是 @Bean 注解所标记的方法也是通过反射调用的。
似乎 Bean 的实例化离不开反射。
那么除了上面这些方案,还有没有其他方案呢?本文和大家探讨一下这个问题。
以下内容基于 Spring6.0.4。
总所周知,当使用 Spring 容器的时候,如果遇到一些特殊的 Bean,一般来说可以通过如下三种方式进行配置:
静态工厂方法 实例工厂方法 FactoryBean 不过从 Spring5 开始,在 AbstractBeandefinition 类中多了一个属性,对于特殊的 Bean 我们有了更多的选择:
/** * Specify a callback for creating an instance of the bean, * as an alternative to a declaratively specified factory method. * <p>If such a callback is set, it will override any other constructor * or factory method metadata.
1、概览 Lombok 是一个流行的 Java 库,它通过减少模板代码来简化代码编写。其强大功能之一是 @ExtensionMethod 注解,可以增强代码的可读性和简洁性。
本文将带你了解 Lombok 中的 @ExtensionMethod 注解有什么用,以及如何有效地使用它。
2、@ExtensionMethod 是什么? @ExtensionMethod 注解允许为现有类添加静态方法扩展。这意味着可以在原始类中调用在其他类中定义的方法。这有利于在不修改源代码的情况下增强第三方库或现有类的功能。
3、@ExtensionMethod 的原理 要使用 @ExtensionMethod,需要用 @ExtensionMethod 来注解一个类,并指定包含想要扩展的静态方法的类。然后,Lombok 会生成必要的代码,使这些方法可用,就好像它们是注解类的方法一样。
假设我们有一个工具类 StringUtils,其中的 reverse() 方法可以反转字符串。我们想把这个方法当作 String 类的一个方法来使用。Lombok 的 @ExtensionMethod 可以帮助我们实现这一目的。
首先,需要在项目中添加 Lombok 依赖。如果使用 Maven,可以在 pom.xml 中添加以下内容:
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.24</version> <scope>provided</scope> </dependency> Lombok 的最新版本可以在 Maven 中央仓库 找到。
3.1、String 示例 先创建 StringUtils 工具类,实现 reverse 方法:
public static String reverse(String str) { return new StringBuilder(str).reverse().toString(); } 接下来,创建一个使用 @ExtensionMethod 注解的测试类:
@ExtensionMethod(StringUtils.class) public class StringUtilsUnitTest { @Test public void givenString_whenUsingExtensionMethod_thenReverseString() { String original = "Lombok Extension Method"; String reversed = original.