Spring Boot 3.2 前几天 发布 了,让我们用 Java 21、GraalVM 和 Virtual Threads(虚拟线程)来快速体验一下。
Spring Boot 3.2 支持:
Java 21 虚拟线程 原生镜像(自 2022 年 11 月 Spring Boot 3.0 发布以来,Spring Boot 已在生产中支持 GraalVM 原生镜像) Java 21 2023 年 9 月 19 日 Java 21 发布。
正如宣布的那样,Java 21 在性能、稳定性和安全性方面进行了数千项改进,包括平台增强功能,这有助于开发人员提高生产力,推动整个组织的创新和发展。
Project Loom 其中一个比较重要的更新是虚拟线程(Virtual Thread),这是 Project Loom 提供的功能。具体细节这里就不多说了,你可以参考官方的 JEP:https://openjdk.org/jeps/444。
GraalVM 和 Native image GraalVM 是一款高性能 JDK,可使用另一种即时(JIT)编译器提高 Java 和基于 JVM 的应用程序的性能。
原生镜像(Native image)是一种将 Java 代码提前编译成独立可执行文件(称为原生镜像)的技术。该可执行文件包括应用程序类、其依赖项中的类、运行时库类以及 JDK 中静态链接的本地代码。
前几天 Spring Boot 3.2 正式 发布 了,本次发布带来了一个新的 HTTP 客户端:RestClient,它提供了 Fluent 风格的 API,比起 RestTemplate 来说更加优雅。
关于 RestClient 的更多信息,你可以参考如下文章:
Spring RestClient 教程 Spring 6.1的新特性:RestClient 本文将会带你了解如何使用 RestClient 同时上传文件、JSON 和表单数据。
关于如何使用 RestTemplate 进行文件上传,你可以参考 “RestTemplate 上传文件” 和 “在 Spring Boot 应用中同时上传文件、JSON和表单数据”。
本文使用的 Spring Boot 版本为 3.2.0。
创建 Controller 首先在 Spring Boot 应用中,创建一个处理 multipart/form-data 文件上传请求的 Controller。
package cn.springdoc.demo.web.controller; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.
1、简介 OAuth 是一种描述授权过程的开放标准。它可用于授权用户访问 API。例如,REST API 可以限制只有具有适当角色的注册用户才能访问。
OAuth 授权服务器负责认证用户身份,并签发包含用户数据和适当访问策略的访问令牌(Access Token)。
本将带你了解如何使用 Spring Security OAuth 授权服务器 实现一个简单的 OAuth 应用。
我们要创建一个 CS 应用,通过 REST API 获取资源服务器上的文章列表。客户端服务和服务器服务都需要 OAuth 身份认证。
2、授权服务器实现 先来看看 OAuth 授权服务器的配置。它作为文章资源和客户端服务器的身份认证源。
2.1、依赖 首先,在 pom.xml 中添加如下依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.5.4</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> <version>2.5.4</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-oauth2-authorization-server</artifactId> <version>0.2.0</version> </dependency> 2.2、配置 在 application.yml 文件中,设置 server.port 属性来配置认证服务器的运行端口:
server: port: 9000 然后,就可以开始配置 Spring Bean 了。首先,需要一个 @Configuration 类,在该类中创建一些 OAuth 特有的 Bean。
第一个是客户端服务的 Repository。在本例中,使用 RegisteredClient Builder 类创建一个客户端:
1、概览 本文将带你了解如何获取 Spring Boot 应用中的所有 REST 端点。
2、映射端点 在 Spring Boot 应用中,通过在 Controller 类中使用 @RequestMapping 注解来暴露 REST API 端点。要获取这些端点,有三种选择:事件监听器、Spring Boot Actuator 或 SpringDoc。
3、事件监听器 在 Controller 中使用 @RestController 和 @RequestMapping 创建 REST API 服务。这些类在 Spring Application Context 中注册为 Spring Bean。因此,当 Application Context 在启动时准备就绪,就可以使用事件监听器获取端点。定义监听器有两种方法。可以实现 ApplicationListener 接口,或者使用 @EventListener 注解。
3.1、ApplicationListener 接口 在实现 ApplicationListener 时,必须定义 onApplicationEvent() 方法:
@Override public void onApplicationEvent(ContextRefreshedEvent event) { ApplicationContext applicationContext = event.getApplicationContext(); RequestMappingHandlerMapping requestMappingHandlerMapping = applicationContext .getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class); Map<RequestMappingInfo, HandlerMethod> map = requestMappingHandlerMapping .
1、概览 本文将带你了解出现 “not eligible for auto-proxying” 警告的原因以及如何修复它。
2、“not eligible for auto proxying” 的原因 2.1、配置示例 首先,创建一个自定义 RandomInt 注解,使用它来注解应该插入指定范围内的随机整数的字段。
@Retention(RetentionPolicy.RUNTIME) public @interface RandomInt { int min(); int max(); } 其次,创建一个简单的 Spring 组件 DataCache 类。将一个可能被使用的随机 Group 分配给缓存,例如用于支持分片。为了实现这一点,使用自定义的注解来注解该字段:
@Component public class DataCache { @RandomInt(min = 2, max = 10) private int group; private String name; } 现在,来看看 RandomIntGenerator 类。它是一个 Spring 组件,用于在 RandomInt 注解注解的字段中插入随机 int 值:
@Component public class RandomIntGenerator { private Random random = new Random(); private DataCache dataCache; public RandomIntGenerator(DataCache dataCache) { this.
1、概览 本文将带你了解如何通过 properties 文件控制 Spring Boot Actuator 端点的状态,以及如何保证端点的安全。
2、设置 为了使用 Actuator,需要在 Maven 配置中包含 spring-boot-starter-actuator:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> <version>3.1.2</version> </dependency> 此外,从 Spring Boot 2.0 开始,如果想通过 HTTP 暴露端点,就需要包含 Web Starter:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>3.1.2</version> </dependency> 3、启用和暴露端点 默认情况下,除 /shutdown 之外的所有端点都已启用,只有 /health 和 /info 被暴露。即使为应用配置了不同的 Root Context,也能在 /actuator 中找到所有端点。
这意味着,一旦在 Maven 配置中添加了相应的 Stater,就可以访问 http://localhost:8080/actuator/health 和 http://localhost:8080/actuator/info 上的 /health 和 /info 端点。
访问 http://localhost:8080/actuator,查看可用端点列表,因为 Actuator 端点已启用 HATEOS。所以,应该能看到 /health 和 /info。
{"_links":{"self":{"href":"http://localhost:8080/actuator","templated":false}, "health":{"href":"http://localhost:8080/actuator/health","templated":false}, "info":{"href":"http://localhost:8080/actuator/info","templated":false}}} 3.1、暴露所有端点 现在,修改 application.
1、概览 在构建 Java Web 应用时,可以使用 Java Server Pages(JSP)作为 HTML 页面模板。
Spring Boot 是一个流行的框架,可以用它来快速开发 Java Web 应用。 但是,在 Spring Boot 中使用 JSP 有一定的局限性,应该考虑用 Thymeleaf 或 FreeMarker 来替代 JSP。
2、Maven 依赖 首先来看看在 Spring Boot 中使用 JSP 需要哪些依赖。
2.1、作为独立应用运行 首先,添加 spring-boot-starter-web 依赖。
该依赖提供了使用 Spring Boot 和默认的嵌入式 Tomcat Servlet 容器来运行 Web 应用的所有核心依赖。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.4.4</version> </dependency> 注意,使用 Undertow 作为嵌入式 Servlet 容器使用时不支持 JSP。
接下来,需要添加 tomcat-embed-jasper 依赖,以便应用能够编译和渲染 JSP 页面:
<dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <version>9.0.44</version> </dependency> 虽然可以手动提供上述两个依赖,但通常最好让 Spring Boot 管理这些依赖的版本,而我们只需管理 Spring Boot 版本即可。
1、概览 本文将带你了解如何把 Spring Context 中的 Bean 设置为 null。在某些情况下,这可能很有用。例如,在测试时不想提供 Mock 对象。以及,在使用一些可选功能时,可能希望避免创建实现,并直接传递 null。
2、组件设置 有几种方法可以将 Bean 设置为 null,具体取决于 Context 的配置方式,本文主要考虑 XML、注解和 Java 配置的方式。
使用一个简单的设置,包含两个类:
@Component public class MainComponent { private SubComponent subComponent; public MainComponent(final SubComponent subComponent) { this.subComponent = subComponent; } public SubComponent getSubComponent() { return subComponent; } public void setSubComponent(final SubComponent subComponent) { this.subComponent = subComponent; } } 本例将演示如何在 Spring Context 中将 SubComponent 设置为 null:
@Component public class SubComponent {} 3、在 XML 配置中使用占位符 在 XML 配置中,可以使用一个特殊的占位符来标识 null 值:
什么是精度丢失? Java 中长整形 Long (64位)的取值范围是:-9223372036854775808 - 9223372036854775807。
在这种情况下,由于 JavaScript 的 Number 类型是 64 位浮点数,它无法精确表示超过 53 位的整数。因此,当将 Java Long 类型的值传递给 JavaScript 时,可能会发生精度丢失。
你可以在浏览器控制台运行如下代码,更直观地感受 “精度丢失” 的问题。
let val = 9223372036854775807; console.log(val); //9223372036854776000 输出的值丢失了精度 如果我们在业务中使用 Long 作为数据类型,那么就必须要考虑浏览器客户端中 Js 存在精度丢失的问题。解决这个问题最简单的办法就是 把 Java 的 Long 值,序列化为字符串传递。
Jackson 的注解支持 Spring Boot 默认使用 Jackson 作为 JSON 的序列化、反序列化框架。Jackson 提供了 @JsonSerialize 注解,该注解的 using 属性可以指定一个 JsonSerializer 的实现类,用于自定义字段的序列化方式。
Jackson 已经预定义了一个实现 ToStringSerializer,用于把指定的字段序列化为字符串。
定义一个简单的 User 对象:
package cn.springdoc.demo.model; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; public class User { // 把 Long 类型的 id 序列化为 字符串 @JsonSerialize(using = ToStringSerializer.
1、概览 安全通信在现代应用中发挥着重要作用。客户端和服务器之间通过普通 HTTP 进行的通信并不安全。对于生产级的应用,应该在应用中通过 TLS(传输层安全)协议启用 HTTPS。
本文将带你了解如何在 Spring Boot 应用中启用 TLS。
2、TLS 协议 TLS 为客户端和服务器之间的数据传输提供保护,是 HTTPS 协议的关键组成部分。安全套接字层(SSL)和 TLS 经常被互换使用,但两者并不相同。事实上,TLS 是 SSL 的继承者。TLS 可以单向或双向实现。
2.1、单向 TLS 在单向 TLS 中,只有客户端对服务器进行验证,以确保从受信任的服务器接收数据。为实现单向 TLS,服务器会与客户端共享其公共证书。
2.2、双向 TLS 在双向 TLS 或相互 TLS(mTLS)中,客户端和服务器都要相互验证,以确保通信双方都是可信的。在实现 mTLS 时,双方要共享各自的公开证书。
3、Spring Boot 配置 TLS 3.1、生成密钥对 要启用 TLS,需要创建一对公钥/私钥。为此,可以使用 keytool 命令行工具,它默认 随 Java 发行版一起提供。
使用 keytool 生成一对密钥,并将其存储到 keystore.p12 文件中:
keytool -genkeypair -alias baeldung -keyalg RSA -keysize 4096 \ -validity 3650 -dname "CN=localhost" -keypass changeit -keystore keystore.