Java中Sentinel框架詳解
一、簡(jiǎn)介
Sentinel 是一個(gè)高可用、高擴(kuò)展、高穩(wěn)定性的開(kāi)源流量控制和熔斷降級(jí)框架,可以在分布式系統(tǒng)中實(shí)現(xiàn)實(shí)時(shí)的流量控制,防止系統(tǒng)因流量過(guò)大導(dǎo)致系統(tǒng)崩潰和服務(wù)降級(jí)。
Sentinel 提供了以下功能:
- 流量控制:通過(guò)配置不同的規(guī)則,對(duì)請(qǐng)求流量進(jìn)行限制。
- 熔斷降級(jí):當(dāng)系統(tǒng)異常情況發(fā)生時(shí),可以自動(dòng)熔斷系統(tǒng),保證系統(tǒng)的可用性。
- 系統(tǒng)負(fù)載保護(hù):在系統(tǒng)負(fù)載高峰期間,可以限制請(qǐng)求流量,避免系統(tǒng)資源耗盡。
- 實(shí)時(shí)監(jiān)控:可以實(shí)時(shí)監(jiān)控系統(tǒng)的請(qǐng)求流量、響應(yīng)時(shí)間、錯(cuò)誤率等指標(biāo)。
Sentinel 面向所有的 Java 應(yīng)用,可以支持基于 Spring Cloud、Dubbo、gRPC 等服務(wù)框架的應(yīng)用,也可以集成到基于 Tomcat、Jetty 等 Web 容器的應(yīng)用中。
二、Sentinel 的原理
Sentinel 實(shí)現(xiàn)流量控制和熔斷降級(jí)的原理是通過(guò)對(duì)應(yīng)用程序進(jìn)行攔截,然后根據(jù)預(yù)定義的規(guī)則,來(lái)判斷該請(qǐng)求是否被允許或者需要進(jìn)行降級(jí)處理。
Sentinel 的攔截器會(huì)在應(yīng)用程序中建立一個(gè)責(zé)任鏈,對(duì)請(qǐng)求進(jìn)行逐一攔截。在攔截過(guò)程中,Sentinel 會(huì)對(duì) Request、Response、Exception 等參數(shù)進(jìn)行統(tǒng)計(jì),根據(jù)統(tǒng)計(jì)信息來(lái)對(duì)請(qǐng)求進(jìn)行熔斷或者限流等操作。
衡量系統(tǒng)穩(wěn)定性主要有以下三個(gè)指標(biāo):
- TPS(Transactions Per Second):每秒鐘處理的事務(wù)數(shù)。
- RT(Response Time):響應(yīng)時(shí)間,即從發(fā)送請(qǐng)求到接收到響應(yīng)的時(shí)間。
- Error Rate:錯(cuò)誤率,即發(fā)生錯(cuò)誤的請(qǐng)求次數(shù)占總請(qǐng)求數(shù)的比例。
Sentinel 根據(jù)這三個(gè)指標(biāo)來(lái)評(píng)估應(yīng)用程序的健康狀況,當(dāng)這些指標(biāo)達(dá)到某個(gè)閾值時(shí),Sentinel 會(huì)自動(dòng)觸發(fā)相應(yīng)的流量控制和熔斷降級(jí)操作。
三、Sentinel 快速入門(mén)
以下是 Sentinel 快速入門(mén)的幾個(gè)步驟:
- 首先,在 Maven 中引入 Sentinel 的依賴(lài):
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>- 在 Spring Boot 中配置 Sentinel 的啟動(dòng)參數(shù):
spring.cloud.sentinel.transport.dashboard=http://localhost:8080 spring.cloud.sentinel.transport.port=8719 # Sentinel 控制臺(tái)連接超時(shí)時(shí)間(ms) spring.cloud.sentinel.transport.dashboard.request-timeout=5000 # 配置資源的默認(rèn)規(guī)則 spring.cloud.sentinel.rules.defaults[0].grade=QPS spring.cloud.sentinel.rules.defaults[0].count=10
其中,spring.cloud.sentinel.transport.dashboard 配置了 Sentinel 控制臺(tái)的地址,spring.cloud.sentinel.transport.port 配置了 Sentinel 的啟動(dòng)端口。
- 在需要進(jìn)行流量控制的方法上添加注解:
@SentinelResource(value = "demoMethod", blockHandler = "handleBlock")
public String demoMethod() {
return "Hello World";
}
public String handleBlock(BlockException ex) {
return "請(qǐng)求被攔截: " + ex.getClass().getSimpleName();
}在上述代碼中,我們使用 @SentinelResource 注解對(duì) demoMethod 方法進(jìn)行了流量控制,并設(shè)置了 fallback 方法為 handleBlock。當(dāng)觸發(fā)限流時(shí),就會(huì)執(zhí)行 handleBlock 方法來(lái)返回自定義的響應(yīng)結(jié)果。
四、使用 Sentinel 進(jìn)行熔斷降級(jí)
Sentinel 不僅能夠進(jìn)行流量控制,還能夠進(jìn)行熔斷降級(jí)。當(dāng)系統(tǒng)出現(xiàn)一定程度的異常時(shí),就會(huì)觸發(fā)熔斷降級(jí)策略來(lái)保證系統(tǒng)的可用性。以下是使用 Sentinel 進(jìn)行熔斷降級(jí)的幾個(gè)步驟:
- 在業(yè)務(wù)方法上添加
@SentinelResource注解,并指定fallbackClass和fallback屬性值:
@SentinelResource(value = "demoMethod", blockHandler = "handleBlock", fallbackClass = DemoServiceFallback.class, fallback = "fallback")
public String demoMethod() {
return "Hello World";
}
public String handleBlock(BlockException ex) {
return "請(qǐng)求被攔截: " + ex.getClass().getSimpleName();
}在上述代碼中,我們指定了
fallbackClass和fallback屬性來(lái)定義 fallback 方法的實(shí)現(xiàn)類(lèi)和方法名。當(dāng)服務(wù)出現(xiàn)熔斷降級(jí)時(shí),就會(huì)執(zhí)行 fallback 方法來(lái)返回自定義的響應(yīng)結(jié)果。定義 fallback 方法及其實(shí)現(xiàn)類(lèi):
在上述代碼中,我們定義了 fallback 方法及其實(shí)現(xiàn)類(lèi) DemoServiceFallback。當(dāng)服務(wù)出現(xiàn)熔斷降級(jí)時(shí),就會(huì)執(zhí)行 fallback 方法來(lái)返回自定義的響應(yīng)結(jié)果。
五、Sentinel 的流控規(guī)則和熱點(diǎn)參數(shù)限流
Sentinel 支持多種多樣的流控規(guī)則和熱點(diǎn)參數(shù)限流策略,可以根據(jù)業(yè)務(wù)場(chǎng)景進(jìn)行靈活配置。
流控規(guī)則
Sentinel 的流控規(guī)則有以下幾種:
QPS 流量控制:通過(guò)對(duì) API 進(jìn)行 QPS 控制,即限定接口在一定時(shí)間內(nèi)能夠處理的請(qǐng)求次數(shù)。
@SentinelResource(value = "demoMethod", blockHandler = "handleBlock")
@RateLimiter(10)
public String demoMethod() {
return "Hello World";
}
public String handleBlock(BlockException ex) {
return "請(qǐng)求被攔截: " + ex.getClass().getSimpleName();
}在上述代碼中,我們使用
@RateLimiter注解對(duì)接口進(jìn)行了 QPS 流控,并設(shè)置了限流閾值為 10。線(xiàn)程數(shù)流控:通過(guò)對(duì)線(xiàn)程池中的線(xiàn)程數(shù)進(jìn)行限制,來(lái)避免線(xiàn)程池過(guò)載。
@SentinelResource(value = "demoMethod", blockHandler = "handleBlock")
@ThreadPool(name = "demoMethod", coreSize = 5, maxQueueSize = 10)
public String demoMethod() {
return "Hello World";
}
public String handleBlock(BlockException ex) {
return "請(qǐng)求被攔截: " + ex.getClass().getSimpleName();
}在上述代碼中,我們使用
@ThreadPool注解對(duì)線(xiàn)程池進(jìn)行了流控,并設(shè)置了線(xiàn)程池的核心線(xiàn)程數(shù)為 5。
熱點(diǎn)參數(shù)限流
熱點(diǎn)參數(shù)限流是 Sentinel 的一個(gè)重要特性,可以有效避免因某個(gè)參數(shù)的惡意使用而導(dǎo)致整個(gè)系統(tǒng)崩潰的情況。例如,假設(shè)有一個(gè)商品詳情接口,其中的參數(shù) skuId 很可能存在熱點(diǎn),即某些具體的商品 skuId 會(huì)被大量請(qǐng)求。如果不進(jìn)行限流,當(dāng)出現(xiàn)某個(gè)特定 skuId 的惡意攻擊時(shí),系統(tǒng)可能會(huì)崩潰。
以下是一個(gè)使用 Sentinel 實(shí)現(xiàn)熱點(diǎn)參數(shù)限流的示例:
@SentinelResource(value = "demoMethod", blockHandler = "handleBlock")
@HotParam(value = "skuId", mode = ParamFlowItem.FlowControlMode.QPS, threshold = 100)
public String demoMethod(@RequestParam Long skuId) {
return "Hello World";
}在上述代碼中,我們使用 @HotParam 注解對(duì) skuId 參數(shù)進(jìn)行限流,并設(shè)置了限流閾值為 100 QPS。這樣,當(dāng)某個(gè) skuId 的請(qǐng)求超過(guò) 100 QPS 時(shí),就會(huì)觸發(fā) Sentinel 的限流機(jī)制。通過(guò)這種方式,我們可以避免因某個(gè)熱點(diǎn)參數(shù)的異常使用而導(dǎo)致整個(gè)系統(tǒng)崩潰的情況。
六、Sentinel 的優(yōu)缺點(diǎn)
Sentinel 作為一個(gè)成熟的分布式系統(tǒng)的流量防衛(wèi)兵,具有以下優(yōu)點(diǎn):
- 功能豐富:Sentinel 提供了流量控制、熔斷降級(jí)、系統(tǒng)保護(hù)、實(shí)時(shí)監(jiān)控等全方位的服務(wù)質(zhì)量保障。
- 易于使用:Sentinel 提供了友好的 Web 界面,可以方便的進(jìn)行規(guī)則的配置和管理。
- 高度可定制:Sentinel 提供了多種 SPI 擴(kuò)展點(diǎn),可以根據(jù)業(yè)務(wù)需求進(jìn)行自定義擴(kuò)展。
- 開(kāi)源免費(fèi):Sentinel 是完全開(kāi)源的,可以免費(fèi)使用。
當(dāng)然,Sentinel 還存在以下一些缺點(diǎn):
- 不支持語(yǔ)言多樣性:Sentinel 目前只支持 Java 應(yīng)用,對(duì)于其他編程語(yǔ)言的應(yīng)用不夠友好。
- 文檔略顯簡(jiǎn)單:Sentinel 的文檔雖然已經(jīng)比較全面,但是在一些實(shí)踐場(chǎng)景中仍然存在一些坑點(diǎn)需要注意。
七、Sentinel 高級(jí)特性
同時(shí)支持同步和異步調(diào)用
Sentinel 可以方便地支持同步和異步調(diào)用。 對(duì)于同步調(diào)用,可以使用 @SentinelResource 注解,在注解中指定需要進(jìn)行保護(hù)的方法,并設(shè)置相應(yīng)的熔斷降級(jí)、流控規(guī)則等限制條件。
對(duì)于異步調(diào)用,則需要使用 Sentinel 提供的異步 Entry 類(lèi)實(shí)現(xiàn)保護(hù)。 在使用異步 Entry 進(jìn)行保護(hù)時(shí),需要在異步調(diào)用過(guò)程中插入 Sentinel 的攔截器,并在異步操作完成后手動(dòng)釋放相應(yīng)的資源,以便 Sentinel 統(tǒng)計(jì)并記錄相應(yīng)的數(shù)據(jù)。
例如,以下是一個(gè)使用異步 Entry 進(jìn)行保護(hù)的示例:
CompletableFuture.supplyAsync(() -> {
Entry entry = null;
try {
entry = SphU.asyncEntry("demoMethod");
// 異步邏輯
return "Hello World";
} catch (BlockException ex) {
return "blocked by Sentinel: " + ex.getClass().getSimpleName();
} finally {
if (entry != null) {
entry.exit();
}
}
}).thenAccept(result -> System.out.println("result: " + result));在上述代碼中,我們首先使用 SphU.asyncEntry 方法創(chuàng)建一個(gè)異步 Entry,然后在異步邏輯中執(zhí)行業(yè)務(wù)操作。要注意的是,當(dāng)異步操作完成時(shí),需要手動(dòng)調(diào)用 entry.exit() 方法釋放相應(yīng)的資源。
支持多種限流模式
Sentinel 支持多種限流模式,可以根據(jù)實(shí)際需求選擇不同的限流算法。
- 直接模式:直接對(duì)資源進(jìn)行限制,超出閾值即觸發(fā)限流。
- 關(guān)聯(lián)模式:通過(guò)關(guān)聯(lián)資源來(lái)進(jìn)行限流,例如對(duì)某個(gè) API 進(jìn)行流量控制時(shí),可以通過(guò)關(guān)聯(lián)訪(fǎng)問(wèn)該 API 的數(shù)據(jù)庫(kù)連接池來(lái)實(shí)現(xiàn)流量控制。
- 鏈路模式:通過(guò)對(duì)整個(gè)鏈路進(jìn)行流量控制來(lái)保障系統(tǒng)的穩(wěn)定性。
使用關(guān)聯(lián)模式和鏈路模式時(shí),需要在規(guī)則中設(shè)置相關(guān)的關(guān)聯(lián)鏈接和鏈路信息。
例如,以下是一個(gè)使用關(guān)聯(lián)模式進(jìn)行流量控制的示例:
@SentinelResource(value = "demoMethod", blockHandler = "handleBlock")
public void demoMethod(@RequestParam("id") Long id) {
System.out.println("request id: " + id);
}
@Bean
public RequestOriginParser requestOriginParser() {
return new DemoRequestOriginParser();
}
public static class DemoRequestOriginParser implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest request) {
String origin = request.getParameter("origin");
if (StringUtils.isEmpty(origin)) {
return "unknown";
}
return origin;
}
}
@Configuration
public class SentinelConfig {
@Autowired
private RequestOriginParser requestOriginParser;
@PostConstruct
public void init() {
FlowRuleManager.register2(Arrays.asList(
new FlowRule("demoMethod").setCount(5)
.setGrade(RuleConstant.FLOW_GRADE_QPS)
.setLimitApp("default")
.as(FlowRule.class)
.setStrategy(RuleConstant.STRATEGY_RELATE)
.setRefResource("demoDatabase")));
}
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
return new SentinelResourceAspect();
}
@Bean
public SentinelServletRequestAspect sentinelServletRequestAspect() {
return new SentinelServletRequestAspect();
}
}在上述代碼中,我們使用 @SentinelResource 注解進(jìn)行流量控制,并通過(guò) setRefResource 和 setStrategy 來(lái)關(guān)聯(lián)數(shù)據(jù)庫(kù)連接池資源,并設(shè)置限流策略為關(guān)聯(lián)模式。
支持多種規(guī)則匹配方式
Sentinel 支持多種規(guī)則匹配方式,可以根據(jù)實(shí)際需求選擇不同的規(guī)則匹配策略。
- 精確匹配:精確匹配是最常用的匹配方式,可以根據(jù)資源名稱(chēng)、限流參數(shù)等精確匹配規(guī)則。
- 子串匹配:通常用于對(duì)資源名稱(chēng)進(jìn)行模糊匹配,例如對(duì)某個(gè) API 的所有請(qǐng)求進(jìn)行限流。
- 正則匹配:可以根據(jù)正則表達(dá)式進(jìn)行規(guī)則匹配,提供更高級(jí)別的靈活性。
例如,以下是一個(gè)使用正則匹配規(guī)則的示例:
@SentinelResource(value = "demoMethod", blockHandler = "handleBlock")
public void demoMethod(@RequestBody Map<String, Object> data) {
System.out.println("request data: " + data);
}
@Configuration
public class SentinelConfig {
@PostConstruct
public void init() {
SystemRuleManager.loadRules(Collections.singletonList(
new SystemRule()
.setHighestSystemLoad(1.0)
.setAvgLoad(0.8)
.setQps(200))));
ParamFlowRuleManager.loadRules(Collections.singletonList(
new ParamFlowRule()
.setParamIdx(0)
.setGrade(RuleConstant.FLOW_GRADE_QPS)
.setCount(5)
.setDurationInSec(1)
.setParamFlowItemList(Collections.singletonList(
new ParamFlowItem().setObject("special_object")
.setCount(2)))));
DegradeRuleManager.loadRules(Collections.singletonList(
new DegradeRule("demoMethod")
.setCount(100)
.setTimeWindow(10)
.setGrade(RuleConstant.DEGRADE_GRADE_RT)
.setCount(20)
.setMinRequestAmount(10))));
FlowRuleManager.loadRules(Collections.singletonList(
new FlowRule()
.setGrade(RuleConstant.FLOW_GRADE_QPS)
.setResourceRegex("/api/.*")
.setCount(10)
.setLimitApp("default")
.as(FlowRule.class))));
}
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
return new SentinelResourceAspect();
}
}在上述代碼中,我們使用 setResourceRegex 方法設(shè)置了一個(gè)正則匹配規(guī)則,對(duì)所有以 /api/ 開(kāi)頭的資源進(jìn)行流量控制。
八、使用案例
使用 Sentinel 和 Spring Cloud Gateway 實(shí)現(xiàn)網(wǎng)關(guān)限流
首先,我們需要在項(xiàng)目中引入 Sentinel 和 Spring Cloud Gateway 的依賴(lài):
<!-- 引入 Sentinel -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- 引入 Spring Cloud Gateway -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>然后,我們可以在 application.yml 文件中添加 Sentinel 和 Spring Cloud Gateway 的相關(guān)配置:
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8250
server:
port: 8080
spring:
cloud:
gateway:
routes:
- id: test_route
uri: http://httpbin.org
predicates:
- Path=/anything/**在上面的配置中,我們指定了 Sentinel 的 dashboard 地址和 Spring Cloud Gateway 的端口號(hào),在 Spring Cloud Gateway 中添加了一個(gè)名為 test_route 的路由,匹配路徑為 /anything/**,并將該路由轉(zhuǎn)發(fā)到 http://httpbin.org。
接下來(lái),我們需要為 Spring Cloud Gateway 添加 Sentinel 規(guī)則,以控制請(qǐng)求的流量:
@Bean
public SentinelGatewayFilterFactory sentinelGatewayFilterFactory() {
return new SentinelGatewayFilterFactory();
}
@Bean
public GatewayFilterChain gatewayFilterChain(RouteLocator routeLocator,
List<GatewayFilterFactory> gatewayFilters) {
DefaultGatewayFilterChain chain = new DefaultGatewayFilterChain(routeLocator.getRoutes(), gatewayFilters);
chain.add(0, sentinelGatewayFilterFactory.apply(new Object()));
return chain;
}在上面的代碼片段中,我們創(chuàng)建了一個(gè)名為 sentinelGatewayFilterFactory 的 Bean,用于創(chuàng)建 Sentinel 的網(wǎng)關(guān)過(guò)濾器,并添加到 Gateway 中。
最后,我們需要在 Sentinel dashboard 中進(jìn)行規(guī)則配置,以控制請(qǐng)求流量:
- 打開(kāi) Sentinel 控制臺(tái),在左側(cè)導(dǎo)航欄中,選擇
Flow,并點(diǎn)擊新增。 - 在
Resource輸入框中輸入/anything/**。 - 在
限流閾值輸入框中輸入限制請(qǐng)求流量的最大數(shù)值。 - 點(diǎn)擊
新增。
使用 Sentinel 和 RocketMQ 實(shí)現(xiàn)消息流量控制
首先,我們需要在項(xiàng)目中引入 Sentinel 和 RocketMQ 的依賴(lài):
<!-- 引入 Sentinel -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- 引入 RocketMQ -->
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.0.3</version>
</dependency>然后,在 application.yml 文件中添加 Sentinel 和 RocketMQ 的相關(guān)配置:
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8250
rocketmq:
name-server: localhost:9876
producer:
group: my-group其中,我們指定了 Sentinel 的 dashboard 地址和 RocketMQ 的 NameServer 地址,以及 RocketMQ 的生產(chǎn)者組名。
接下來(lái),我們需要為生產(chǎn)者添加 Sentinel 規(guī)則,以控制消息發(fā)送的流量:
@Slf4j
@Service
public class MyProducer {
@Autowired
private RocketMQTemplate rocketMQTemplate;
@PostConstruct
public void init() {
// 添加 Sentinel 規(guī)則
String resourceName = "myTopic:myTag";
String ruleKey = "myRuleKey";
int threshold = 100;
DegradeRule rule = new DegradeRule(resourceName, ruleKey, threshold);
rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
rule.setTimeWindow(10);
List<DegradeRule> rules = new ArrayList<>();
rules.add(rule);
DegradeRuleManager.loadRules(rules);
}
public void sendMessage(String message) {
try {
rocketMQTemplate.convertAndSend("myTopic", "myTag", message);
} catch (Exception e) {
log.error("發(fā)送消息失敗,message: {}", message, e);
}
}
}在上面的代碼中,我們?yōu)?myTopic:myTag 資源添加了一條 Sentinel 規(guī)則,該規(guī)則的作用是:當(dāng)該資源的 RT(響應(yīng)時(shí)間)超過(guò) 10 毫秒時(shí),將觸發(fā)熔斷,拒絕進(jìn)一步的請(qǐng)求,防止影響消息系統(tǒng)的正常運(yùn)行。規(guī)則的閾值為 100,即當(dāng)一秒鐘內(nèi)超過(guò) 100 條消息時(shí)會(huì)觸發(fā)限流。
最后,在消費(fèi)者中也需要添加 Sentinel 的規(guī)則,以控制消息消費(fèi)的流量:
@Slf4j
@Service
public class MyConsumer {
@RocketMQMessageListener(topic = "myTopic", consumerGroup = "my-group")
@SentinelResource(value = "myTopic:myTag", blockHandler = "handleBlockedMessage")
public void handleMessage(@Payload String message) {
log.info("接收到消息:{}", message);
}
public void handleBlockedMessage(String message, BlockException e) {
log.error("消息被拒絕,message: {}", message);
}
}在上面的代碼中,我們?yōu)?nbsp;myTopic:myTag 資源添加了 Sentinel 規(guī)則,并指定了發(fā)生 Sentinel 規(guī)則限制時(shí)的處理方法。在消費(fèi)過(guò)程中,如果超過(guò) Sentinel 規(guī)則的閾值,則會(huì)觸發(fā)限流,拒絕進(jìn)一步的消息消費(fèi)。
以上就是Java中Sentinel框架詳解的詳細(xì)內(nèi)容,更多關(guān)于Java Sentinel框架的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
springcloud整合到項(xiàng)目中無(wú)法啟動(dòng)報(bào)錯(cuò)Failed to start bean&n
這篇文章主要介紹了springcloud整合到項(xiàng)目中無(wú)法啟動(dòng)報(bào)錯(cuò)Failed to start bean 'eurekaAutoServiceRegistration'問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
Java中如何將list轉(zhuǎn)為樹(shù)形結(jié)構(gòu)
這篇文章主要介紹了Java中如何將list轉(zhuǎn)為樹(shù)形結(jié)構(gòu),本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09
SpringCloud融入Python的實(shí)現(xiàn)
這篇文章主要介紹了SpringCloud融入Python的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12
Mybatis動(dòng)態(tài)SQL?foreach批量操作方法
這篇文章主要介紹了Mybatis動(dòng)態(tài)SQL?foreach批量操作方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03
Java設(shè)計(jì)模式中組合模式應(yīng)用詳解
組合模式,又叫部分整體模式,它創(chuàng)建了對(duì)象組的數(shù)據(jù)結(jié)構(gòu)組合模式使得用戶(hù)對(duì)單個(gè)對(duì)象和組合對(duì)象的訪(fǎng)問(wèn)具有一致性。本文將通過(guò)示例為大家詳細(xì)介紹一下組合模式,需要的可以參考一下2022-11-11
SpringBoot四大神器之Auto onfiguration的使用
本文主要介紹了SpringBoot四大神器之Auto Configuration,springboot auto configuration的本質(zhì)就是自動(dòng)配置spring的各種bean。感興趣的可以了解一下2021-10-10

