1、简介 本文将带你了解如何解决 JDBC 异常:“Cannot issue data manipulation statements with executeQuery()”。
在使用 JDBC 与数据库交互时,这个异常并不常见,但这个问题很容易解决。
2、理解异常 2.1、导致这个异常的原因 当我们尝试使用 executeQuery() 方法执行 INSERT、UPDATE 或 DELETE 语句时,就会出现错误 “Cannot issue data manipulation statements with executeQuery()” 异常。
Statement 或 PreparedStatement 对象中的 executeQuery() 方法专门用于处理 SELECT 查询。如果检查一下该方法的签名,就会发现它返回的是 ResultSet 实例,其中包含从数据库中获取的记录。
使用 Connector/J 连接 MySQL 时会出现这种异常,但其他数据库也执行相同的规则。在这种情况下,它们会以不同的错误信息抛出类似的错误。
需要注意的是,在较新版本的 MySQL Connector/J 中,该错误信息已略有更新。现在是这样:
java.sql.SQLException: Statement.executeQuery() cannot issue statements that do not produce result sets. 2.2、导致该异常的场景 来看一个代码示例,以便更好地理解是什么触发了异常。如前所述,我们使用 MySQL 数据库。
首先,为示例创建一个简单的数据表:
CREATE TABLE IF NOT EXISTS users ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50), email VARCHAR(50) ) 现在我们可以尝试执行一个非 SELECT 语句的查询。
1、概览 WAR 文件是 Web 应用程序归档文件(Web Application Archive)或 Web 应用程序资源文件(Web Application Resource)的简称,用于存储 Java Web 应用程序的资源。WAR 将所有 Web 组件打包成一个单元。它包含 JAR 文件、JavaServer Page(JSP)、Java Servlet、Java 类文件、XML 文件、HTML 文件以及 Web 应用程序所需的其他资源。
本文将带你了解如何使用 CLI 调用在 WAR 文件中的类。
2、WAR 文件的结构 WAR 文件使用 .war 扩展名并打包 Web 应用程序,我们可以将其部署到任何 Servlet/JSP 容器上。
下面是一个典型的 WAR 文件结构布局示例:
META-INF/ MANIFEST.MF WEB-INF/ web.xml jsp/ helloWorld.jsp classes/ com/baeldung/*.class application.properties static/ templates/ lib/ // third party *.jar files as libs index.html 内部有一个 META-INF 目录,在 MANIFEST.MF 中保存了有关 Web 存档的有用信息。META-INF 目录是私有的,外部无法访问。
1、概览 在 Java 中,数组是语言的基本组成部分,它提供了一种结构化的方式来存储相同类型的多个值。然而,在使用数组和类型转换时,我们有时会遇到意想不到的运行时异常。
当我们试图将 Object[] 数组转换为特定数组类型(如 Integer[])时,就会出现这样的问题。这会导致 ClassCastException 异常,这可能会让很多人感到困惑。
本文将带你了解出现这种异常的原因,从而了解 Java 数组的基本机制,并学习如何在代码中避免此类错误。
2、问题介绍 像往常一样,先通过一个例子来了解这个问题:
Integer[] convertObjectArray() { Object[] objArray = new Object[3]; objArray[0] = 1; objArray[1] = 2; objArray[2] = 3; return (Integer[]) objArray; } 在上述方法中,我们在一个 Object[] 数组中插入了三个 int 值。由于 Object[] 数组只包含 Integer,我们尝试将其转换为 Integer[] 数组。
在测试中调用该方法,看看会发生什么:
Exception ex = assertThrows(ClassCastException.class, () -> convertObjectArray()); LOG.error("The exception stacktrace:", ex); 可以看到,调用该方法会抛出 ClassCastException。在输出中,还可以看到异常的详细信息:
java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [Ljava.lang.Integer; ... at .
1、概览 在 Spring 中,可以通过内置工具和注解简化数据验证,使我们能够轻松实现强大的验证逻辑。
本文将带你了解如何在 Spring 中验证 List 类型的参数值。
2、在 Spring 中配置 Validation 要启用验证,需要在 pom.xml 中添加以下 依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> 该依赖会自动将 Hibernate Validator 整合到我们的 Spring 应用程序中。
3、验证 List 中的每个元素 假设我们需要验证员工角色列表。每个角色都应以 ROLE_ 开头。
首先在 Employee DTO 类中添加一个 roles 变量:
@NotEmpty(message = "Roles list cannot be empty") @Valid private List<@Pattern(regexp = "ROLE_[A-Z]+", message = "Each role must start with 'ROLE_' and contain uppercase letters only") String> roles; @NotEmpty 注解确保列表不是空的,而 @Pattern 注解则验证每个角色都符合指定的格式(正则)。
1、概览 HTTP 服务器通常用于为发起请求的客户端提供资源。Java 中有一系列生产级 Web 服务器。
本文将带你了解如何使用 ServerSocket 类实现一个简单的 Web 服务器,从而了解 HTTP 服务器是如何工作的。注意,此服务器仅用于教学目的,不适合用于生产。
2、ServerSocket 基础 首先,服务器会监听客户端应用程序的连接。客户端应用程序可以是浏览器、其他程序、API 工具等。连接成功后,服务器会响应客户端连接,向客户端提供资源。
ServerSocket 类提供了在指定端口上创建服务器的方法。它使用 accept() 方法监听指定端口上的传入连接。
accept() 方法会阻塞,直到建立连接,并返回一个 Socket 实例。Socket 实例为服务器和客户端之间的通信提供了对输入和输出流的访问。
3、创建 ServerSocket 实例 首先,创建一个监听指定端口的 ServerSocket 对象:
int port = 8080; ServerSocket serverSocket = new ServerSocket(port); 接着,使用 accept() 方法接受一个传入连接:
while (true) { Socket clientSocket = serverSocket.accept(); // ... } 如上,使用 while 循环等待连接。然后,调用 ServerSocket 对象上的 accept() 方法来监听和接受连接。
连接建立后,该方法会返回一个 Socket 对象,允许服务器和客户端通过已建立的网络进行通信。
4、处理输入和输出 通常,服务器接收来自客户端的输入并发送适当的响应。我们可以使用 Socket 类的 getInputStream() 和 getOutputStream() 方法,通过提供流来读取和写入数据到客户端,从而进行通信。
1、简介 在开发 Java 项目时,我们可能会遇到这样的情况:需要在 Java 程序中启动一个单独的进程运行外部 JAR(可执行 JAR)并查看输出,或者可能想要执行外部 JAR 中带有 main 方法的类文件。
2、运行可执行 JAR 可执行 JAR 是一种 JAR 文件类型,它包含一个设置了 Main-Class 属性的清单(manifest)文件。该属性指向应首先运行(使用 main 方法)的类文件。
我们可以使用 java -jar <example.jar> 命令从命令行运行该 JAR。也可以在 Java 程序中使用 ProcessBuilder 来实现类似的结果。
下面的代码演示了如何以编程式将可执行 JAR 作为单独进程运行,并在控制台中查看输出结果:
@Test public void givenRunnableJar_whenExecuted_thenShouldRunSuccessfully() { Process process = null; try { String jarFile = new File(Objects.requireNonNull(getClass().getClassLoader() .getResource(RUNNABLE_JAR_PATH)) .toURI()).getAbsolutePath(); ProcessBuilder processBuilder = new ProcessBuilder("java", "-jar", jarFile); processBuilder.redirectErrorStream(true); process = processBuilder.start(); try (InputStream inputStream = process.getInputStream()) { byte[] output = inputStream.
🐞 Bug 修复 logging.structured.json.customizer 的属性元数据类型不正确 #43916 仅指定 logging.structured.gelf.host 时,GraylogExtendedLogFormatProperties 会抛出 NullPointerException 异常 #43863 结构化日志属性在 Native Image 中不起作用 #43862 当 ALLOW_EMPTY_PASSWORD=yes 时,ClickHouse 的 Docker Compose 支持不允许使用空密码 #43790 在 2.23 或更早版本中,docker compose ps 现在会因为未知的 --orphans flag 而失败 #43717 构建信息时间戳被截断为秒 #43617 用于 SSL 重载的 FileWatcher 不支持 Symlink #43604 BindableRuntimeHintsRegistrar 应处理 TypeNotPresentException #43600 使用 Log4J2 StatusLogger 时,CapturedOutput 为空 #43578 Spring Boot 3.4 与 Gson 2.1 不兼容 #43442 使用 JUnit 测试依赖 spring-boot-actuator-autoconfigure 但不依赖 org.junit.platform:junit-platform-launcher 的 Gradle 7.
1、简介 众所周知,Java 和 Go 是两种著名的编程语言,各自在不同的领域表现出色。Java 以其可移植性和广泛的生态系统而闻名,而 Go 则以其简洁性、性能和高效的并发处理而著称。在某些情况下,将两种语言的优势结合起来,可以开发出更强大、更高效的应用程序。
本文将带你了解如何利用 Java Native Access(JNA)库来弥合两种语言之间的差距,从而在不编写任何 C 代码的情况下从 Java 中调用 Go 函数。
2、用 JNA 架起 Java 和 Go 之间的桥梁 传统上,从 Java 调用本地代码需要用 C 语言编写 Java 本地接口(JNI)代码,这会增加复杂性和开销。然而,随着 Java Native Access(JNA)库的出现,可以直接从 Java 调用本地共享库,而无需深入研究 C 代码。这种方法简化了集成过程,允许开发人员在 Java 应用程序中无缝利用 Go 的功能。
要理解这种集成是如何工作的,首先,要了解 Java Native Access(JNA)库在连接 Java 和 Go 方面的作用。具体来说,JNA 提供了一种从 Java 代码调用本地共享库函数的直接方法。通过将 Go 代码编译到共享库中并导出必要的函数,Java 可以与 Go 函数进行交互,就像它们是自己生态系统的一部分一样。
本质上,这一过程包括编写 Go 函数,将其编译成共享库,然后使用 JNA 创建映射到这些函数的相应 Java 接口。
2、项目设置 首先,设置项目环境。这包括配置集成所需的构建工具和依赖项。在本例中,我们需要以下组件:
Java Development Kit(JDK):用于编译和运行 Java 代码。 Go 语言环境:用于编写和编译 Go 代码。 Java Native Access(JNA)库:作为 Maven 项目的一个依赖项包含在内。 构建工具:Maven 适用于 Java,Go 编译器适用于 Go 代码。 添加 JNA 库到 maven 依赖:
1、简介 在开发 Java 项目时,我们经常依赖外部库来开发应用。
本文将带你了解把这些第三方库作为 JAR 添加到 classpath 下的不同方法。
2、在命令行中使用 -cp 或 -classpath 选项 如果我们从命令行启动程序,那么可以在命令中指定 JAR 依赖:
java -cp /path/to/jar/file.jar com.example.MyClass 如上,/path/to/jar/file.jar 是 JAR 文件的路径,com.example.MyClass 是要执行的类。
还可以添加多个 jar:
java -cp "lib/jar1.jar:lib/jar2.jar" com.example.MyClass 3、在命令行中使用 CLASSPATH 在某些情况下,在同一台机器上运行的多个 Java 程序可能需要用同一个 JAR。
在这种情况下,我们可以在 macOS/Linux 中设置 CLASSPATH 环境变量,而不是在每条命令中指定 classpath:
export CLASSPATH=/path/to/jar/file.jar Windows 系统的设置方法如下:
set CLASSPATH=C:\path\to\jar\file.jar 设置 CLASSPATH 后,我们就可以直接运行 Java 程序,而无需指定 -classpath 选项。
注意,如果我们以这种方式设置 CLASSPATH,它只对该终端会话有效。一旦终端关闭,设置就会丢失。所以,我们可以将 classpath 添加到环境变量,使其永久有效。
4、在 MANIFEST.MF 文件中指定 Classpath 当我们创建一个独立可执行的应用时,最佳实践是将所有依赖的 JAR 都打包到一个 JAR 中。
1、概览 Java JWT(JSON Web Token)库是一个用于创建、解析和验证 JWT Token 的工具。这些 Token 可确保 API 和 Web 应用的安全,是身份验证和授权的通用解决方案。
本文将带你了解如何使用更先进的 parserBuilder.setSigningKey() 方法替换该库中已废弃的 parser().setSigningKey() 方法,以及使用 JWT Parser Builder 解析和验证 JWT 的优势。
2、签名密钥是什么? 签名密钥是 JWT Token 的关键要素。JWT Token 由三部分组成:Header、Payload 和签名。签名是通过使用秘钥或公钥/私钥对对 Header 和 Payload 进行签名来创建的。当 Token 发送到服务器时,签名密钥将用于验证签名,确保 Token 未被篡改。
在 Java JWT 库中,签名密钥是在 Token 验证过程中提供给解析器的。这可以确保 Token 的完整性,并使服务器能够信任其内容。
3、Jwts 类是什么? Jwts 类是 Java JWT 库中的一个核心工具类。它是处理 JWT 的入口点。该类为我们提供了创建、解析和验证 JWT 的各种方法。例如,当我们要解析 JWT 时,首先要调用 Jwts.parserBuilder() 方法,该方法为我们提供了一个构建器,用于构建带有必要配置选项(如设置签名密钥)的解析器。
3.1、已废弃方法概述 有了上述理论后,来看看我们要替换的已废弃的 parser().setSigningKey() 方法:
JwtParser parser = Jwts.