Spring Boot 4 與 Spring Framework 7新特性、升級(jí)要點(diǎn)與實(shí)戰(zhàn)指南
還記得 2022 年底不?當(dāng)時(shí)Spring Boot 3 和 Spring Framework 6 一出來,直接給整個(gè) Spring 生態(tài)來了個(gè) “大換血”, 這可是自 Spring 誕生以來動(dòng)靜最大的一次更新。不僅把 Java 17 設(shè)為了最低要求,還把以前的 javax.* 換成了 jakarta.*,連 GraalVM 原生鏡像也開始初步支持了。
轉(zhuǎn)眼到 2025 年,新一代版本馬上要來了:就是 Spring Boot 4 和 Spring Framework 7。
這倆版本沒跑偏,接著推進(jìn)生態(tài)現(xiàn)代化。一方面用上了最新的 Java 特性,跟 Jakarta EE 11 的適配也更緊密;另一方面還幫開發(fā)者省了不少事,而且默認(rèn)就支持打造 “抗造” 的應(yīng)用,不用額外折騰太多。
接下來我就跟大家捋捋這倆版本的核心亮點(diǎn),再配點(diǎn)說明和代碼例子,讓大家清楚升級(jí)后能用到啥好東西。
基線升級(jí)
在說具體功能之前,得先明確新版本對(duì) “基礎(chǔ)依賴” 的要求,這很關(guān)鍵。
現(xiàn)在行業(yè)里用 Java 17 的還挺多,所以它依然是最低要求版本。不過官方特別建議用 Java 21 或 25,因?yàn)槟苡蒙咸摂M線程這類新的 JVM 特性。關(guān)于這點(diǎn),Spring 博客里有官方說明,大家想細(xì)看可以去那看。
Spring Framework 7 現(xiàn)在完全適配 Jakarta EE 11 了,也就是說,它依賴的技術(shù)標(biāo)準(zhǔn)都升級(jí)了:Servlet 6.1、JPA 3.2,還有 Bean Validation 3.1。
另外,Kotlin 現(xiàn)在支持 2.2 及以上版本了。這么一來,寫協(xié)程會(huì)更順,處理響應(yīng)式代碼也感覺更 “自然”,不用繞彎子。
Spring Boot 4
作為第四個(gè)大版本,Spring Boot 這次加了不少實(shí)用改進(jìn),重點(diǎn)提一下:性能變快了、更容易 “監(jiān)控” 應(yīng)用了、維護(hù)起來更省心了,連配置支持都變強(qiáng)了。這些改動(dòng)讓它作為 “現(xiàn)代云原生 Java 應(yīng)用的基礎(chǔ)框架”,地位更穩(wěn)了。
原生鏡像更給力了
Spring Boot 4 還在使勁推進(jìn) GraalVM 原生鏡像的支持,現(xiàn)在已經(jīng)完全跟 GraalVM 24 對(duì)齊了。而且 “提前編譯(AOT)” 的能力也優(yōu)化了 —— 編譯速度更快,啟動(dòng)時(shí)占的內(nèi)存也更少了。
舉個(gè)例子,Spring Data 新增了AOT 倉(cāng)庫(kù),簡(jiǎn)單說就是:通過 AOT 處理,能把查詢方法轉(zhuǎn)成源代碼,然后跟應(yīng)用一起編譯。這樣一來,運(yùn)行效率會(huì)更高。
監(jiān)控應(yīng)用更方便:Micrometer 2 + OpenTelemetry
云原生應(yīng)用想跑穩(wěn),“可觀測(cè)性”(就是能看到應(yīng)用的運(yùn)行狀態(tài))特別重要。Spring Boot 3 之前就加了Spring 可觀測(cè)性,這次Spring Boot 4 直接升級(jí)到 Micrometer 2,還集成了 OpenTelemetry 的啟動(dòng)器。這樣一來,“Trace日志”、“普通日志” 和 “性能指標(biāo)(metrics)” 就能無縫配合,不用再自己湊一套了。
SSL 證書快過期?現(xiàn)在能清楚看到了
以前看 SSL 證書狀態(tài)有點(diǎn)麻煩,現(xiàn)在改進(jìn)了:如果證書鏈里有快過期的證書,會(huì)專門新增一個(gè) expiringChains 條目來顯示它們。而且之前的 “WILL_EXPIRE_SOON” 狀態(tài)沒了,快過期的證書會(huì)統(tǒng)一標(biāo)成 “VALID”。
這樣一來,團(tuán)隊(duì)在生產(chǎn)環(huán)境監(jiān)控 SSL 證書時(shí),能更清楚哪些要過期了,還不會(huì)出現(xiàn)沒必要的 “誤報(bào)”,省了不少排查時(shí)間。
代碼拆得更細(xì)了:模塊化改造
Spring Boot 4 剛啟動(dòng)開發(fā)時(shí),第一個(gè)重要目標(biāo)就是把自己的代碼庫(kù)拆成更 “模塊化” 的結(jié)構(gòu)。
以前 Spring Boot 3 里,很多核心模塊(比如自動(dòng)配置、啟動(dòng)器依賴、構(gòu)建工具這些)都打包在大的 “構(gòu)件” 里。雖然用著方便,但有時(shí)候依賴管理會(huì)很亂,類路徑掃描也慢,連原生鏡像的體積都會(huì)變大。
從 Spring Boot 4 開始,團(tuán)隊(duì)把 “自動(dòng)配置” 和 “支持代碼” 拆成了更小的模塊,每個(gè)模塊只負(fù)責(zé)一小塊功能。這么改有啥好處?
- 構(gòu)建和生成原生鏡像更快:GraalVM 的 AOT 處理不用管那些沒用的 “提示信息” 和 “元數(shù)據(jù)” 了。
- 依賴管理更清爽:像 Micrometer、OpenTelemetry 這些可選的功能,不再跟核心代碼打包在一起,而是單獨(dú)放一個(gè)模塊,想用就加,不想用也不占地方。
- Spring 團(tuán)隊(duì)維護(hù)起來更輕松:模塊和功能一一對(duì)應(yīng),找問題、改代碼都方便,貢獻(xiàn)代碼的人也更容易上手。
對(duì)咱們開發(fā)者來說,平時(shí)寫 pom.xml 或 build.gradle 可能感覺不到變化。只要用 “啟動(dòng)器依賴”(比如 spring-boot-starter-data-jpa),就不用改任何東西。比如要用到 JPA 和 Hibernate,直接在 pom.xml 里加這段依賴就行:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
真正的變化在 “底層”:JPA 的自動(dòng)配置、Hibernate 的集成、還有校驗(yàn)相關(guān)的配置,現(xiàn)在都在不同的小模塊里了。這樣框架在運(yùn)行時(shí)或者 AOT 編譯時(shí),能更精準(zhǔn)地加載需要的配置,不浪費(fèi)資源。
新增 @ConfigurationPropertiesSource 注解:跨模塊配置更省心
為了讓模塊化更好用,這次還加了個(gè)新注解 @ConfigurationPropertiesSource。注意哦,它不會(huì)改變 “運(yùn)行時(shí)配置屬性怎么綁定”,主要是在 “構(gòu)建階段” 給 spring-boot-configuration-processor(配置處理器)提個(gè)醒。
平時(shí)配置處理器給 @ConfigurationProperties 類生成 “元數(shù)據(jù)” 時(shí),只會(huì)從這個(gè)類所在的模塊里找信息。但在模塊化項(xiàng)目里,有時(shí)候會(huì)用到其他模塊的 “嵌套類型” 或者 “基類”,而這些模塊的源代碼在構(gòu)建時(shí)可能拿不到 —— 這樣生成的元數(shù)據(jù)就會(huì)不完整,比如少了屬性描述或者默認(rèn)值。
現(xiàn)在給類加個(gè) @ConfigurationPropertiesSource 注解,就能告訴處理器:“就算這個(gè)類沒標(biāo) @ConfigurationProperties,也得給它生成完整的元數(shù)據(jù)”。簡(jiǎn)單說,以后跨模塊開發(fā)時(shí),再也不用操心元數(shù)據(jù)缺失的問題了,處理器會(huì)自動(dòng)搞定。
Spring Framework 7
Spring Framework 7 這次既加了很多用戶盼了好久的功能,還在測(cè)試、API 設(shè)計(jì)、核心基礎(chǔ)功能上做了不少細(xì)節(jié)優(yōu)化。一方面讓框架更 “現(xiàn)代”,另一方面也幫咱們少寫很多重復(fù)的模板代碼。
測(cè)試功能更靈活了
Spring 在測(cè)試時(shí)會(huì)用 “上下文緩存”—— 就是為了平衡 “測(cè)試速度” 和 “環(huán)境隔離”(避免不同測(cè)試互相影響)。關(guān)于這個(gè)緩存的細(xì)節(jié)、可能踩的坑,還有怎么解決,大家可以看這篇文章。
這次 Spring Framework 7 加了個(gè) “測(cè)試上下文暫停” 的功能。以前跑長(zhǎng)時(shí)間的集成測(cè)試,就算測(cè)試閑著沒干活,也會(huì)占著資源;現(xiàn)在不一樣了,Spring 能把緩存里的 “上下文” 暫停,要用的時(shí)候再恢復(fù) —— 這樣能省內(nèi)存,跑大量測(cè)試的時(shí)候速度也會(huì)變快。比如處理 JMS 監(jiān)聽器容器、定時(shí)任務(wù)這些場(chǎng)景,這個(gè)功能特別有用。
另外,還新增了一個(gè)RestTestClient,用它測(cè)試 REST 接口特別方便 —— 用法跟 WebTestClient 差不多,但不用額外裝 “響應(yīng)式基礎(chǔ)設(shè)施”。
給大家看個(gè)例子,就能明白它多簡(jiǎn)單了:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class HelloWorldApiIntegrationTest {
RestTestClient client;
@BeforeEach
void setUp(WebApplicationContext context) {
client = RestTestClient.bindToApplicationContext(context)
.build();
}
@Test
void shouldFetchHelloV1() {
client.get()
.uri("/api/v1/hello")
.exchange()
.expectStatus()
.isOk()
.expectHeader()
.contentTypeCompatibleWith(MediaType.TEXT_PLAIN)
.expectBody(String.class)
.consumeWith(message -> assertThat(message.getResponseBody()).containsIgnoringCase("hello"));
}
}API 版本控制
很多人一直想要的 “API 版本控制”,這次終于成了框架的一級(jí)功能,不用再自己瞎折騰了。
以前咱們要搞 API 版本,得自己想辦法:比如在 URL 里加 /v1/,或者自定義請(qǐng)求頭、改媒體類型。現(xiàn)在框架原生就支持了,直接給 @GetMapping 加個(gè) version 屬性就行,看例子:
@RestController
@RequestMapping("/hello")
public class HelloWorldController {
// 版本1的接口,返回“Hello World”
@GetMapping(version = "1", produces = MediaType.TEXT_PLAIN_VALUE)
public String sayHelloV1() {
return "Hello World";
}
// 版本2的接口,返回“Hi World”
@GetMapping(version = "2", produces = MediaType.TEXT_PLAIN_VALUE)
public String sayHelloV2() {
return "Hi World";
}
}也可以在控制器級(jí)別統(tǒng)一設(shè)版本,比如下面這個(gè) “版本 3” 的控制器:
@RestController
@RequestMapping(path = "/hello", version = "3")
public class HelloWorldV3Controller {
// 不用再給方法加version了,默認(rèn)用控制器的版本3
@GetMapping(produces = MediaType.TEXT_PLAIN_VALUE)
public String sayHello() {
return "Hey World";
}
}不過得配置一下 “版本怎么映射到請(qǐng)求上”,有四種方式可選:
- 路徑映射:比如 /api/v1/hello 和 /api/v2/hello
- 查詢參數(shù):比如 /hello?version=1 和 /hello?version=2
- 請(qǐng)求頭:比如請(qǐng)求頭里加 X-API-Version: 1 或 2
- 媒體類型頭:比如請(qǐng)求頭 Accept: application/json; version=1
下面是 “路徑映射” 的配置例子,大家可以參考:
@Configuration
public class ApiConfig implements WebMvcConfigurer {
@Override
public void configureApiVersioning(ApiVersionConfigurer configurer) {
// 用路徑的第1段作為版本(比如/v1/里的1)
configurer.usePathSegment(1);
}
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
// 給所有@RestController的接口加前綴/api/v{version}
configurer.addPathPrefix("/api/v{version}", HandlerTypePredicate.forAnnotation(RestController.class));
}
}配置完之后,Spring 會(huì)自動(dòng)識(shí)別請(qǐng)求里的版本,對(duì)應(yīng)到正確的接口。這樣迭代 API 的時(shí)候,就不用擔(dān)心影響老用戶了。
@HttpServiceClient:寫 HTTP 客戶端更簡(jiǎn)單
還有個(gè)好用的功能:聲明式 HTTP 客戶端。靈感來自 Feign,但更輕量,而且跟 Spring 融得更緊。
以前用 Spring,要調(diào)用其他服務(wù)的 HTTP 接口,得給 HttpInterface 創(chuàng)建代理,想搞智能點(diǎn)還得自己寫代碼。比如這個(gè)倉(cāng)庫(kù)里,就有個(gè)自定義的 @HttpClient 注解和 Bean 注冊(cè)器的例子(Spring Framework 7 還優(yōu)化了 Bean 注冊(cè)器,這篇文章有說)。
現(xiàn)在不用自己寫了,框架直接給了 @HttpServiceClient 注解,開箱即用??磦€(gè)例子就懂了:
// 給這個(gè)接口加注解,指定服務(wù)名叫“christmasJoy”
@HttpServiceClient("christmasJoy")
public interface ChristmasJoyClient {
// 用@GetExchange指定請(qǐng)求地址,相當(dāng)于發(fā)GET請(qǐng)求到/greetings?random
@GetExchange("/greetings?random")
String getRandomGreeting();
}然后要配置一下 “掃描這個(gè)接口” 和 “服務(wù)的基礎(chǔ)地址”:
@Configuration
// 導(dǎo)入自定義的注冊(cè)器
@Import(HttpClientConfig.HelloWorldClientHttpServiceRegistrar.class)
public class HttpClientConfig {
// 自定義注冊(cè)器,負(fù)責(zé)掃描并注冊(cè)HttpServiceClient接口
static class HelloWorldClientHttpServiceRegistrar extends AbstractClientHttpServiceRegistrar {
@Override
protected void registerHttpServices(GroupRegistry registry, AnnotationMetadata metadata) {
// 掃描com.baeldung.spring.mvc包下的HttpServiceClient接口
findAndRegisterHttpServiceClients(registry, List.of("com.baeldung.spring.mvc"));
}
}
// 配置“christmasJoy”這個(gè)服務(wù)的基礎(chǔ)地址
@Bean
RestClientHttpServiceGroupConfigurer christmasJoyServiceGroupConfigurer() {
return groups -> {
groups.filterByName("christmasJoy") // 找到名叫christmasJoy的服務(wù)組
.forEachClient((group, clientBuilder) -> {
// 設(shè)置基礎(chǔ)URL
clientBuilder.baseUrl("https://christmasjoy.dev/api");
});
};
}
}配置完之后,這個(gè) ChristmasJoyClient 就能像普通 Bean 一樣注入到其他組件里用了,比如下面這個(gè)控制器:
@RestController
@RequestMapping(path = "/hello", version = "4")
@RequiredArgsConstructor // Lombok注解,自動(dòng)生成構(gòu)造器
public class HelloWorldV4Controller {
// 注入ChristmasJoyClient
private final ChristmasJoyClient christmasJoy;
@GetMapping(produces = MediaType.TEXT_PLAIN_VALUE)
public String sayHello() {
// 調(diào)用客戶端的方法,獲取隨機(jī)問候語(yǔ)
return this.christmasJoy.getRandomGreeting();
}
}彈性能力內(nèi)置:加個(gè)注解就有重試、限流
Spring Retry 雖然在生態(tài)里好多年了,但一直像個(gè) “外掛”,不是框架核心功能。這次 Spring Framework 7 直接把 “彈性能力”(比如重試、限流)做成內(nèi)置的了—— 給 Spring 組件的方法加個(gè)注解,就能實(shí)現(xiàn)重試邏輯或者并發(fā)限制,特別方便。
看個(gè)例子,還是剛才的 ChristmasJoyClient,加兩個(gè)注解就行:
@HttpServiceClient("christmasJoy")
public interface ChristmasJoyClient {
@GetExchange("/greetings?random")
// 重試:最多試3次,第一次等100ms,之后每次等的時(shí)間翻倍,最多等1000ms
@Retryable(maxAttempts = 3, delay = 100, multiplier = 2, maxDelay = 1000)
// 并發(fā)限制:最多3個(gè)請(qǐng)求同時(shí)調(diào)用
@ConcurrencyLimit(3)
String getRandomGreeting();
}不過要注意:這些注解默認(rèn)是不生效的,得在某個(gè)配置類上加 @EnableResilientMethods 才能啟用。
這樣一來,不用再依賴 Resilience4j 這類額外庫(kù)(當(dāng)然,想集成也能正常用),就能實(shí)現(xiàn)彈性功能,省了不少配置功夫。而且還能在運(yùn)行時(shí)驗(yàn)證這些策略有沒有生效,不用擔(dān)心注解白加了。
支持多個(gè) TaskDecorator:異步任務(wù)能加多個(gè) “鉤子”
以前用 Spring 的時(shí)候,想自定義異步任務(wù)的執(zhí)行邏輯,頂多只能在 ThreadPoolTaskExecutor 上掛一個(gè) TaskDecorator。比如把安全上下文(SecurityContext)或者日志里的 MDC 信息傳到異步線程里,靠它還能實(shí)現(xiàn)。但要是想同時(shí)搞好幾件事,比如:又傳上下文又打日志,就得自己手動(dòng)寫個(gè) “復(fù)合裝飾器”,特別麻煩。
好在從 Spring Framework 7 開始,咱們能在應(yīng)用上下文里聲明多個(gè) TaskDecorator Bean 了!Spring 會(huì)自動(dòng)把它們串成一個(gè) “裝飾鏈”,按 Bean 定義的順序或者 @Order 注解標(biāo)的順序,一個(gè)接一個(gè)生效。
舉個(gè)實(shí)際例子,咱們有個(gè)異步的事件監(jiān)聽器:
@Component
@Slf4j
public class HelloWorldEventLogger {
@Async // 標(biāo)了這個(gè)就是異步執(zhí)行
@EventListener
void logHelloWorldEvent(HelloWorldEvent event) {
log.info("Hello World Event: {}", event.message());
}
}要是想給這個(gè)異步任務(wù)加個(gè)簡(jiǎn)單日志(記錄開始結(jié)束),再算個(gè)執(zhí)行時(shí)間,不用寫復(fù)雜代碼,直接注冊(cè)兩個(gè) TaskDecorator Bean 就行:
@Configuration
@Slf4j
public class TaskDecoratorConfiguration {
// 第一個(gè)裝飾器:打任務(wù)開始/結(jié)束日志,@Order標(biāo)了2
@Bean
@Order(2)
TaskDecorator loggingTaskConfigurator() {
return runnable -> () -> {
log.info("Running Task: {}", runnable); // 任務(wù)開始日志
try {
runnable.run(); // 執(zhí)行實(shí)際任務(wù)
} finally {
log.info("Finished Task: {}", runnable); // 任務(wù)結(jié)束日志
}
};
}
// 第二個(gè)裝飾器:算執(zhí)行時(shí)間,@Order標(biāo)了1(比上面先執(zhí)行)
@Bean
@Order(1)
TaskDecorator measuringTaskConfigurator() {
return runnable -> () -> {
final var ts1 = System.currentTimeMillis(); // 開始時(shí)間
try {
runnable.run(); // 執(zhí)行實(shí)際任務(wù)
} finally {
final var ts2 = System.currentTimeMillis(); // 結(jié)束時(shí)間
log.info("Finished within {}ms (Task: {})", ts2 - ts1, runnable); // 輸出耗時(shí)
}
};
}
}最后日志會(huì)輸出這樣的內(nèi)容:
Running Task: com.baeldung.spring.mvc.TaskDecoratorConfiguration$$Lambda/0x00000ff0014325f8@57e8609
Hello World Event: "Happy Christmas"
Finished within 0ms (Task: java.util.concurrent.FutureTask@bb978d6[Completed normally])
Finished Task: com.baeldung.spring.mvc.TaskDecoratorConfiguration$$Lambda/0x00000ff0014325f8@57e8609
這波改進(jìn)是真省心,不用再寫一堆重復(fù)的復(fù)合裝飾器代碼了,想給異步任務(wù)加多個(gè)功能(比如日志、計(jì)時(shí)、權(quán)限校驗(yàn)),直接加 Bean 就行,特別方便。
用 JSpecify 搞定空安全,終于不混亂了
之前 Java 生態(tài)里的空值注解隨處可見(@Nonnull、@Nullable、@NotNull 等),現(xiàn)在 Spring Framework 7 干脆定了標(biāo)準(zhǔn):用 JSpecify,示例長(zhǎng)這樣:
這改進(jìn)了 IDE 工具和 Kotlin 互操作性,減少了大型代碼庫(kù)中 NullPointerException 的風(fēng)險(xiǎn)。
總結(jié)
Spring Boot 4 和 Spring Framework 7 真不是 “小打小鬧的更新”,而是 Spring 特意朝著 Java 開發(fā)的 “現(xiàn)代化、模塊化、云原生” 方向邁的一大步:
- 有了 API 版本控制和彈性注解,應(yīng)用既能輕松升級(jí),又能扛住各種異常
- 靠 JSpecify 的空安全和 Kotlin 支持,運(yùn)行時(shí)出錯(cuò)能少很多。
- 聲明式 HTTP 客戶端,服務(wù)之間調(diào)用不用寫一堆請(qǐng)求代碼了。
- 原生鏡像支持和可觀測(cè)性工具加強(qiáng),往云環(huán)境上部署更順了。
跟所有大版本升級(jí)一樣,關(guān)鍵是早點(diǎn)拿項(xiàng)目測(cè)。尤其是依賴升級(jí)和舊 API 替換這兩塊,早發(fā)現(xiàn)問題早解決。不過話說回來,升級(jí)后開發(fā)效率變高、性能變好、維護(hù)也省心,這點(diǎn)麻煩還是值得的。
到此這篇關(guān)于Spring Boot 4 與 Spring Framework 7 全面解析:新特性、升級(jí)要點(diǎn)與實(shí)戰(zhàn)指南的文章就介紹到這了,更多相關(guān)Spring Boot 4 與 Spring Framework 7 新特性內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot3.4.0無法找到StringRedisTemplate?bean的問題Consider?defining?a?bean?of?type?‘org.springframework
- SpringBoot引入Redis報(bào)org.springframework.data.redis.core.RedisTemplate類找不到錯(cuò)誤問題
- 解決springboot3:mybatis-plus依賴錯(cuò)誤:org.springframework.beans.factory.UnsatisfiedDependencyException
- SpringBoot org.springframework.beans.factory.UnsatisfiedDependencyException依賴注入異常
- 啟動(dòng)springboot項(xiàng)目時(shí)報(bào)錯(cuò):無法訪問org.springframework.web.bind.annotation.GetMapping …具有錯(cuò)誤的版本 61.0,應(yīng)為52.0?的解決方案
- springboot的類加載器(org.springframework.boot.loader)過程詳解
相關(guān)文章
Java實(shí)現(xiàn)產(chǎn)生隨機(jī)字符串主鍵的UUID工具類
這篇文章主要介紹了Java實(shí)現(xiàn)產(chǎn)生隨機(jī)字符串主鍵的UUID工具類,涉及java隨機(jī)數(shù)與字符串遍歷、轉(zhuǎn)換等相關(guān)操作技巧,需要的朋友可以參考下2017-10-10
Java中的線程池如何實(shí)現(xiàn)線程復(fù)用
這篇文章主要介紹了Java中的線程池如何實(shí)現(xiàn)線程復(fù)用問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03
關(guān)于spring中不同包中類名相同報(bào)錯(cuò)問題的總結(jié)
這篇文章主要介紹了關(guān)于spring中不同包中類名相同報(bào)錯(cuò)問題的總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06
SpringBoot實(shí)現(xiàn)接口冪等性的4種方案
這篇文章主要介紹了SpringBoot實(shí)現(xiàn)接口冪等性的4種方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
簡(jiǎn)單了解springboot中的配置文件相關(guān)知識(shí)
這篇文章主要介紹了簡(jiǎn)單了解springboot中的配置文件相關(guān)知識(shí),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11

