教程

Spring Retry 教程

1、概览 Spring Retry 提供了自动重新调用失败操作的能力。这在错误可能是短暂的(例如瞬时的网络故障)情况下非常有帮助。 本文将带你了解使用 Spring Retry 的各种方法:注解、RetryTemplate 和回调。 2、Maven 依赖 首先,在 pom.xml 文件中添加 spring-retry 以及 Spring AOP 依赖: <dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> <version>2.0.3</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>6.0.11</version> </dependency> 你可以在 Maven Central 获取 spring-retry 和 spring-aspects 依赖的最新版本。 3、启用 Spring Retry 要在应用中启用 Spring Retry,需要在 @Configuration 类中添加 @EnableRetry 注解: @Configuration @EnableRetry public class AppConfig { ... } 4、使用 Spring Retry 4.1、@Retryable 注解 使用 @Retryable 注解为方法添加重试功能: @Service public interface MyService { @Retryable void retryService(String sql); } 由于没有指定任何异常,因此将尝试重试所有异常。此外,一旦达到最大尝试次数,但仍有异常,就会抛出 ExhaustedRetryException。

Spring 中的控制反转(IoC)和依赖注入(DI)

1、概览 本文将带你了解 IoC(控制反转)和 DI(依赖注入)的概念,以及如何在 Spring 中实现这些概念。 2、控制反转(IoC)是什么? 控制反转(Inversion of Control)是软件工程中的一项原则,它将对象或程序部分的控制权转移到容器或框架中。在面向对象的编程中经常使用。 也有人叫 “反转控制”。 在传统编程中,我们使用自定义代码来调用库,而 IoC 则使框架能够控制程序的流程,并调用我们的自定义代码。框架使用了带有内置附加行为的抽象类来实现这一点。如果我们想添加自己的行为,就需要继承框架的类或插入自己的类。 这种架构的优势在于: 将任务的执行与任务的实现分离开来 更容易在不同的实现之间切换 程序的模块化程度更高 通过隔离组件或模拟其依赖,并允许组件通过 “约定” 进行通信,从而更轻松地测试程序 我们可以通过各种机制实现控制反转,例如:策略模式、服务定位模式、工厂模式和依赖注入(DI)。 3、依赖注入(DI)是什么? 依赖注入是可以用来实现 IoC 的一种模式,其中被反转的控制是 设置对象的依赖。 将对象与其他对象 “装配” 起来,或将对象 “注入” 到其他对象中是由组装器(Assembler)而不是对象本身来完成的。 下面是我们在传统编程中创建依赖对象的方法: public class Store { private Item item; public Store() { item = new ItemImpl1(); // 实例化所需的依赖 } } 重写示例,通过使用 DI,而无需指定 Item 的实现: public class Store { private Item item; public Store(Item item) { this.item = item; } } 在接下来的章节中,将带你了解如何通过元数据(Metadata)来实现 Item。

Java 加载 PEM 格式的 RSA 证书和私钥

在 上一篇文章 中,我们介绍了如何使用 Java 生成 RSA 密钥对,以及如何使用 RSA 进行加密、解密和签名验签。 在实际情况中,RSA 加密、解密所使用的密钥对往往是已经生成好的,通常以 PEM(Privacy Enhanced Mail)格式存储。 PEM 是一种常见的文件格式,用于存储和传输加密的 证书、私钥 和其他安全相关的数据。 证书(Certificate):用于存储公钥证书,通常以 .pem 或 .crt 为扩展名。 私钥(Private Key):用于存储私钥,通常以 .pem 或 .key 为扩展名。 PEM 格式的文件通常以.pem为扩展名,它使用标头和尾部标记来界定不同类型的数据,并使用 Base64 编码将二进制数据转换为 ASCII 文本。 本文将带你了解如何在 Java 中使用 Spring 的 PemContent 工具类加载 PEM 格式的 RSA 证书和私钥为 PublicKey 和 PrivateKey 对象。 使用 OpenSSL 生成 RSA 私钥和证书 我们使用 OpenSSL 来生成示例所用的 RSA 私钥和证书。首先需要确保你在本机安装了 OpenSSL,并且正确地配置到了 PATH 环境变量。 OpenSSL 是一个开源的密码学工具库,被广泛应用于网络安全领域,用于创建和管理 SSL/TLS 连接、生成自签名证书、签发数字证书、进行加密通信等。 生成 2048 位的 RSA 私钥:

Spring Cloud Netflix 教程 - Eureka

1、概览 本文将带你了解如何通过 Spring Cloud Netflix Eureka 来实现客户端服务发现。 客户端服务发现允许服务相互查找和通信,而无需硬编码主机名和端口。在这种架构中,唯一的 “固定点” 是服务注册中心(service registry,),每个服务都必须在注册中心中注册。 一个缺点是所有客户端必须实现特定的逻辑与这个注册中心进行交互。这就需要在实际请求之前进行一次额外的网络请求。 有了 Netflix Eureka,每个客户端都可以同时充当服务器,将自己的状态复制给已连接的对等服务。换句话说,客户端在服务注册中心中检索所有已连接对等服务的列表,并通过负载均衡算法向其他服务发出所有进一步请求。 要获知客户端的存在,它们必须向注册中心发送心跳信号。 为了实现本文的目标,需要实现三个微服务: 注册中心(Eureka Server) REST 服务,在注册中心中注册(Eureka Client) Web 应用,作为客户端(Spring Cloud Netflix Feign Client)来消费 REST 服务(从注册中心获取到服务) 2、Eureka 服务器 使用 Eureka Server 实现一个注册中心,很简单: 在依赖中添加 spring-cloud-starter-netflix-eureka-server 用 @EnableEurekaServer 对 @SpringBootApplication 进行注解,从而启用 Eureka 服务器 配置一些配置属性 一步步来: 首先,创建一个新的 Spring Boot 项目,并添加相应的依赖。 通过 spring-cloud-starter-parent Bom 管理组件的依赖版本。 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-parent</artifactId> <version>2021.0.3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> 你可以在 Spring 的官方文档中查看 最新的 Spring Cloud 版本。

使用 Spring Security 防止 CSRF 攻击

1、概览 本文将带你了解什么是跨站请求伪造(CSRF)攻击?以及如何使用 Spring Security 来防范这些攻击。 2、两种简单的 CSRF 攻击行为 CSRF 攻击有多种形式。 2.1、GET 示例 假如下面这个 GET 请求,用于一个已登录的用户向指定的银行账户 1234 转账: GET http://bank.com/transfer?accountNo=1234&amount=100 如果攻击者想把钱从受害者的账户转到自己的账户(5678),他需要让受害者触发请求: GET http://bank.com/transfer?accountNo=5678&amount=1000 有多种方法可以实现这一点: 链接 - 攻击者可以说服/诱导受害者点击该链接,例如执行转账: <a href="http://bank.com/transfer?accountNo=5678&amount=1000"> 点击展示美女图片 </a> 图片 - 攻击者可能会使用 <img/> 标签,将目标 URL 作为图片来源。换句话说,甚至不需要点击。请求将在页面加载时自动执行: <img src="http://bank.com/transfer?accountNo=5678&amount=1000"/> 所以,涉及到敏感的业务,千万不能用 GET 请求。 2.2、POST 示例 假设转账 API 是一个 POST 请求。 POST http://bank.com/transfer accountNo=1234&amount=100 在这种情况下,<a> 和 <img/> 标签都不起作用。 攻击者需要使用 <form>: <form action="http://bank.com/transfer" method="POST"> <input type="hidden" name="accountNo" value="5678"/> <input type="hidden" name="amount" value="1000"/> <input type="submit" value="Show Kittens Pictures"/> </form> 然后,使用 JavaScript 自动提交表单:

Spring 整合 Thymeleaf 模板引擎

1、概览 Thymeleaf 是一个 Java 模板引擎,用于处理和创建 HTML、XML、JavaScript、CSS 和文本。 本文将带你了解如何在 Spring 和 Spring Boot 应用中整合、使用 Thymeleaf。 该库具有极高的可扩展性,其天然的模板功能可以确保在没有后端的情况下制作模板原型。与其他流行的模板引擎(如 JSP)相比,这使得开发速度非常快。 2、Spring 整合 Thymeleaf 首先,来看看与 Spring 整合所需的配置。这需要使用 thymeleaf-spring 库。 在 Maven POM 文件中添加以下依赖: <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf</artifactId> <version>3.1.2.RELEASE</version> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring5</artifactId> <version>3.1.2.RELEASE</version> </dependency> 注意,对于 Spring 4,必须使用 thymeleaf-spring4,而不是 thymeleaf-spring5。 通过 SpringTemplateEngine 类执行所有配置步骤。 可以在 Java 配置中将该类配置为 bean: @Bean @Description("Thymeleaf Template Resolver") public ServletContextTemplateResolver templateResolver() { ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(); templateResolver.setPrefix("/WEB-INF/views/"); templateResolver.setSuffix(".html"); templateResolver.setTemplateMode("HTML5"); return templateResolver; } @Bean @Description("Thymeleaf Template Engine") public SpringTemplateEngine templateEngine() { SpringTemplateEngine templateEngine = new SpringTemplateEngine(); templateEngine.

Spring Security LDAP 简介

1、概览 本文将带你了解如何设置 Spring Security LDAP。 LDAP、即 Lightweight Directory Access Protocol(轻量级目录访问协议)的缩写,是一种开放的、厂商中立的协议,用于通过 Web 访问目录服务。 2、Maven 依赖 所需 Maven 依赖如下: <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-ldap</artifactId> </dependency> <dependency> <groupId>org.apache.directory.server</groupId> <artifactId>apacheds-server-jndi</artifactId> <version>1.5.5</version> </dependency> 注:使用 ApacheDS 作为 LDAP 服务器,这是一个可扩展、可嵌入的目录服务器。 3、Java 配置 Spring Security Java 配置: public class SecurityConfig { @Bean ApacheDSContainer ldapContainer() throws Exception { return new ApacheDSContainer("dc=baeldung,dc=com", "classpath:users.ldif"); } @Bean LdapAuthoritiesPopulator authorities(BaseLdapPathContextSource contextSource) { String groupSearchBase = "ou=groups"; DefaultLdapAuthoritiesPopulator authorities = new DefaultLdapAuthoritiesPopulator (contextSource, groupSearchBase); authorities.setGroupSearchFilter("(member={0})"); return authorities; } @Bean AuthenticationManager authenticationManager(BaseLdapPathContextSource contextSource, LdapAuthoritiesPopulator authorities) { LdapBindAuthenticationManagerFactory factory = new LdapBindAuthenticationManagerFactory (contextSource); factory.

RestTemplate 教程

1、概览 本文将带你了解如何使用 Spring REST 客户端 RestTemplate 发起各种类型的 HTTP 请求。 2、废弃警告 从 Spring Framework 5 开始,除了 WebFlux,Spring 还引入了一个名为 WebClient 的新 HTTP 客户端。 WebClient 是一种替代 RestTemplate 的现代 HTTP 客户端。它不仅提供传统的同步 API,还支持高效的非阻塞和异步方法。 如果要开发新的应用或迁移旧的应用,最好还是使用 WebClient。在未来版本中,RestTemplate 将被弃用。 3、使用 GET 检索资源 3.1、获取纯 JSON 格式 使用 getForEntity() API 发起 GET 请求: RestTemplate restTemplate = new RestTemplate(); String fooResourceUrl = "http://localhost:8080/spring-rest/foos"; ResponseEntity<String> response = restTemplate.getForEntity(fooResourceUrl + "/1", String.class); Assertions.assertEquals(response.getStatusCode(), HttpStatus.OK); 可以访问完整的 HTTP 响应,因此可以检查 HTTP 状态码是否成功,或者处理响应体: ObjectMapper mapper = new ObjectMapper(); JsonNode root = mapper.

Spring Boot 对 CRaC(Coordinated Restore at Checkpoint)的支持

上周 发布 的 Spring 6.1 和 SpringBoot 3.2 都全面支持 CRaC(Coordinated Restore at Checkpoint)。 CRaC(Coordinated Restore at Checkpoint),翻译过来应该是 “检查点协调恢复”,如果你想了解有关 CRaC 的更多信息,请参阅 这里。 CRaC 是一个 OpenJDK 项目,可以对运行中的 JVM(Java 虚拟机)进行 “快照”,并将其状态(包括应用)存储到磁盘中。然后,在另一个时间点,可以将 JVM 从保存的检查点恢复到内存中。借助这个功能,你可以启动应用、预热并创建检查点(Checkpoint)。从保存的检查点恢复到内存主要依靠磁盘 I/O,这意味着恢复速度非常快(在毫秒级范围内)。 本文使用 SpringBoot Petclinic 项目来测试 SpringBoot 3.2 对 CRaC 的支持。 前提条件 要在 SpringBoot 3.2 中使用 CRaC,需要具备以下三个条件 支持 CRaC 的 JVM org.crac 的依赖 存放检查点的文件夹 使用的 JDK(Java 开发包)是 Azul Zulu 21.0.1 + CRaC,可从 此处 获取。该 JDK 适用于 x64 和 aarch64 CPU 架构,以及 JDK 17 和 JDK 21。

在 Spring Boot 中修改请求

1、概览 本文将带你了解如何在 HTTP 请求到达 Spring Boot 应用的 Controller 之前对其进行修改。Web 应用和 RESTful Web 服务经常使用这种方式来解决常见问题,例如在传入的 HTTP 请求到达实际 Controller 之前对其进行转换或过滤。这促进了松散耦合,大大减少了开发工作量。 2、使用 Filter 通常,应用需要执行一些通用的操作,如身份认证、日志记录、转义 HTML 字符等。Filter 是解决在任何 Servlet 容器中运行的应用的这些通用问题的最佳选择。 Filter 工作方式如下: 在 Spring Boot 应用中,以固定顺序注册 Filter,以实现以下目的: 修改请求 记录请求日志 检查请求是否经过认证或是否存在恶意脚本 决定拒绝或将请求转发给下一个 Filter 或 Controller 假设我们要转义 HTTP 请求体中的所有 HTML 字符,以防止 XSS 攻击。 首先定义 Filter: @Component @Order(1) public class EscapeHtmlFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { filterChain.doFilter(new HtmlEscapeRequestWrapper((HttpServletRequest) servletRequest), servletResponse); } } @Order 注解中的 value 值 1 表示所有 HTTP 请求首先通过 EscapeHtmlFilter Filter。还可以在 Spring Boot 配置类中定义 FilterRegistrationBean Bean 来注册 Filter,这可以为 Filter 定义 URL 模式。