Java

Java 使用 RSA 进行加密、解密、签名和验签

RSA(Rivest-Shamir-Adleman)算法是一种非对称加密算法,广泛用于数据加密和数字签名领域。它是由 Ron Rivest、Adi Shamir 和 Leonard Adleman 于 1977 年共同提出的。 RSA 算法常用于如下场景: 公钥加密,私钥解密 私钥加密,公钥解密(不推荐) 私钥签名,公钥验签 生成密钥对 通过 Java java.security 包下的工具类可以生成 RSA 公钥和私钥。 package cn.springdoc.demo.test; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.util.Base64; /** * @author springdoc.cn * 生成 RSA 密钥对 */ public class Main { public static void main(String[] args) throws Exception { // 初始化 Key 生成器,指定算法类型为 RSA KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); // 密钥长度为 2048 位 keyPairGenerator.initialize(2048); // 生成密钥对 KeyPair keyPair = keyPairGenerator.

如何 Mock(模拟)HttpServletRequest

1、概览 本文将带你了解几种模拟 HttpServletRequest 对象的方法。 首先,从 Spring Test 中的 MockHttpServletRequest 开始,这是一个功能齐全的模拟类型。然后,了解如何使用 Mockito 和 JMockit 这两个流行的模拟库进行测试。最后,了解如何使用匿名子类进行测试。 2、测试 HttpServletRequest 当我们要模拟客户端 request 信息(如 HttpServletRequest)来测试 Servlet 可能会有点麻烦,该接口定义了各种方法,需要进行实现。 要测试的目标 UserServlet 类,如下: public class UserServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { String firstName = request.getParameter("firstName"); String lastName = request.getParameter("lastName"); response.getWriter().append("Full Name: " + firstName + " " + lastName); } } 要对 doGet() 方法进行单元测试,需要模拟 request 和 response 参数,以模拟实际的运行时行为。 3、使用 Spring 的 MockHttpServletRequest Spring-Test 提供了一个功能齐全的类 MockHttpServletRequest,它实现了 HttpServletRequest 接口。

使用 @NotNull 注解进行非空校验

1、概览 空指针异常 NullPointerException 是一个常见问题,避免这种问题的方法之一是在方法参数上添加 @NotNull 等校验注解。 给方法参数添加了 @NotNull 注解后,还需要其他的一些设置才能自动对参数进行非空校验。 2、给方法参数添加 @NotNull 注解 创建一个类,其中包含一个返回 String 长度的方法。 在 String 参数上添加 @NotNull 注解: public class NotNullMethodParameter { public int validateNotNull(@NotNull String data) { return data.length(); } } 注意,有多个包下都有 @NotNull 注解,我们使用的应该是 jakarta.validation.constraints 包。 创建 NotNullMethodParameter 实例,然后使用 null 参数调用方法。 NotNullMethodParameter notNullMethodParameter = new NotNullMethodParameter(); notNullMethodParameter.doesNotValidate(null); 尽管在参数上使用了 @NotNull,但还是出现了空指针异常:NullPointerException。 注解未生效,因为没有 Validator 来执行它。 3、添加 Validator 添加 Hibernate Validator(jakarta.validation 的实现)来识别 @NotNull。 <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>8.0.0.Final</version> </dependency> 使用默认的 ValidatorFactory 创建 validator。

使用 OpenAPI 生成带有 Lombok 注解的 Model

1、概览 Lombok 是一个 Java 库,有助于减少 getter、setter 等模板代码。OpenAPI 提供了一个属性,用于自动生成带有 Lombok 注解的 Model。 在本教程中,我们将探讨如何使用 OpenAPI 代码生成器生成带有 Lombok 注解的 Model。 2、项目设置 首先,让我们创建一个 Spring Boot 项目,并添加 Spring Boot Starter Web 和 Lombok 依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>3.1.2</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.28</version> <scope>provided</scope> </dependency> 此外,我们还需要 Swagger 注解、Gson 和 Java Annotation API 依赖,以防止在生成的代码中出现与包相关的错误: <dependency> <groupId>javax.annotation</groupId> <artifactId>javax.annotation-api</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.10.1</version> </dependency> <dependency> <groupId>io.swagger</groupId> <artifactId>swagger-annotations</artifactId> <version>1.6.2</version> </dependency> 在下一节中,我们将为一个名为 Book 的 model 创建一个 API 规范,然后使用 OpenAPI 代码生成器生成带有 Lombok 注解的代码。

Java IllegalStateException: “getInputStream() has already been called for this request”

1、介绍 有时,当我们在 Java Web 应用程序中调用 ServletRequest 接口的 getReader() / getInputStream()方法时,可能会出现IllegalStateException 异常,异常信息为:“getInputStream() has already been called for this request”。 在本教程中,我们将了解出现这种异常的原因和解决方法。 2、问题与原因 Java Servlet 规范,用于用 Java 构建 Web 应用程序。它定义了 ServletRequest / HttpServletRequest 接口,以及 getReader() 和 getInputStream() 方法,用于从 HTTP 请求中读取数据。 getReader() 方法以字符数据形式返回请求体,而 getInputStream() 方法则以二进制数据形式返回请求体。 getReader() 和 getInputStream() 的 Servlet API 文档强调,它们不能同时使用: public java.io.BufferedReader getReader() Either this method or getInputStream may be called to read the body, not both. ... Throws: java.lang.IllegalStateException - if getInputStream() method has been called on this request public ServletInputStream getInputStream() Either this method or getReader may be called to read the body, not both.