依賴nacos實例動態創建線程池并監聽服務上下線

版本

  • Spring Booot 版本 3.2.4
  • Spring Cloud 版本 2023.0.1
  • Spring Cloud Alibaba 版本 2023.0.1.2

依賴

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>${spring-cloud-alibaba.version}</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>

配置文件

  • bootstrap.yml配置
spring:application:name: ${app_name:${APP_NAME:demo}} cloud:nacos:username: ${config_username:${CONFIG_USERNAME:nacos}}password: ${config_password:${CONFIG_PASSWORD:nacos}}discovery:server-addr: ${config_server_uri:${CONFIG_SERVER_URI:10.244.36.167:8848}}namespace: ${config_profiles_active:${CONFIG_PROFILES_ACTIVE:dev}}group: ${config_group:${CONFIG_GROUP:demo}}service: ${spring.application.name}config:server-addr: ${config_server_uri:${CONFIG_SERVER_URI:10.244.36.167:8848}}namespace: ${config_profiles_active:${CONFIG_PROFILES_ACTIVE:dev}}group: ${config_group:${CONFIG_GROUP:demo}}file-extension: ymlrefresh-enabled: true # 開啟配置自動刷新,默認開啟,此處顯示聲明
  • ?application-dev.yml配置
thread-pool:core-size: 2          # 核心線程數max-size: 2           # 最大線程數queue-capacity: 100   # 隊列容量keep-alive-time: 60   # 空閑線程存活時間(秒)

配置類

  • NacosThreadPoolProperties
package com.xxx.xxx.amedia.media.properties;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;/*** nacos 線程池配置類* @author xxx* @date 2025-5-23 13:54:21*/
@Data
@Configuration
@ConfigurationProperties(prefix = "thread-pool")
public class NacosThreadPoolProperties {/*** 核心線程數*/private int coreSize;/*** 最大線程數*/private int maxSize;/*** 隊列容量*/private int queueCapacity;/*** 空閑線程活躍時間*/private int keepAliveTime;
}

  • NacosDiscoveryProperties
package com.xxx.xxx.amedia.media.properties;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;/*** nacos discovery 配置類* @author xxx* @date 2025-5-23 13:54:21*/
@Data
@Configuration
@ConfigurationProperties(prefix = "spring.cloud.nacos.discovery")
public class NacosDiscoveryProperties {/*** nacos服務地址*/private String serverAddr;/*** 命名空間*/private String namespace;/*** 分組*/private String group;
}
  • NacosTokenProperties
package com.xxx.xxx.amedia.media.properties;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;/*** nacos 線程池配置類* @author xxx* @date 2025-5-23 13:54:21*/
@Data
@Configuration
@ConfigurationProperties(prefix = "spring.cloud.nacos")
public class NacosTokenProperties {/*** 用戶名*/private String username;/*** 密碼*/private String password;
}

常量類

package com.xxx.xxx.amedia.media.constant;/*** nacos 常量類* @author xxx* @date 2025-5-26 10:07:23*/
public final class NacosConstants {private NacosConstants() {}/*** nacos配置 username*/public static final String USERNAME = "username";/*** nacos配置 password*/public static final String PASSWORD = "password";/*** nacos配置 server-addr*/public static final String SERVER_ADDR = "serverAddr";/*** nacos配置 namespace*/public static final String NAMESPACE = "namespace";/*** nacos配置 group*/public static final String GROUP = "group";}

nacos 核心類 NamingService 配置

package com.xxx.amedia.media.config;import com.xxx.amedia.media.constant.NacosConstants;
import com.xxx.amedia.media.properties.NacosDiscoveryProperties;
import com.xxx.amedia.media.properties.NacosTokenProperties;import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.Properties;/*** nacos 核心類 NamingService 配置* @author xxx* @date 2025-5-23 15:18:24*/
@Configuration
public class NamingServiceConfig {@Autowiredprivate NacosTokenProperties nacosTokenProperties;@Autowiredprivate NacosDiscoveryProperties nacosDiscoveryProperties;@Beanpublic NamingService namingService() throws NacosException {Properties properties = new Properties();// nacos 服務器地址properties.put(NacosConstants.SERVER_ADDR, nacosDiscoveryProperties.getServerAddr());// 命名空間properties.put(NacosConstants.NAMESPACE, nacosDiscoveryProperties.getNamespace());properties.put(NacosConstants.GROUP, nacosDiscoveryProperties.getGroup());properties.put(NacosConstants.USERNAME, nacosTokenProperties.getUsername());properties.put(NacosConstants.PASSWORD, nacosTokenProperties.getPassword());return NacosFactory.createNamingService(properties);}
}

?nacos實例 線程池管理類

package com.xxx.amedia.media.manager;import com.xxx.amedia.media.properties.NacosDiscoveryProperties;
import com.xxx.amedia.media.properties.NacosThreadPoolProperties;
import com.xxx.amedia.rpc.config.MediaRpcProperties;import cn.hutool.core.thread.ThreadFactoryBuilder;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.listener.NamingEvent;
import com.alibaba.nacos.api.naming.pojo.Instance;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;/*** nacos實例 線程池管理類* @author xxx* @date 2025-5-23 10:30:21*/
@Slf4j
@Component
public class NacosThreadPoolManager {@Autowiredprivate MediaRpcProperties mediaRpcProperties;@Autowiredprivate NacosDiscoveryProperties nacosDiscoveryProperties;@Autowiredprivate NacosThreadPoolProperties nacosThreadPoolConfig;/*** 訂閱服務上線和下線事件*/@Autowiredprivate NamingService namingService;/*** 存儲 IP 和線程池的映射關系*/private final Map<String, ThreadPoolExecutor> ipThreadPoolMap = new ConcurrentHashMap<>();@PostConstructpublic void init() {// 注冊監聽器registerServiceListener(mediaRpcProperties.getServiceName());}/*** 注冊服務監聽器,監聽指定服務的實例變化** @param serviceName 服務名稱*/private void registerServiceListener(String serviceName) {try {namingService.subscribe(serviceName, nacosDiscoveryProperties.getGroup(), event -> {if (event instanceof NamingEvent namingEvent) {String serviceNameFromEvent = namingEvent.getServiceName();if (StringUtils.equals(serviceNameFromEvent, serviceName)) {handleInstanceChange(namingEvent);}}});} catch (NacosException ex) {// 處理異常,例如記錄日志log.error("Register service listener occur exception.", ex);}}/*** 處理實例變化事件* @param event NamingEvent*/private void handleInstanceChange(NamingEvent event) {// 獲取當前所有實例的 IPSet<String> currentIps = event.getInstances().stream().map(Instance::getIp).collect(Collectors.toSet());// 處理實例變化事件handleInstanceChange(currentIps);}/*** 處理實例變化事件* @param currentIps 當前所有實例的 IP*/private void handleInstanceChange(Set<String> currentIps) {// 舊實例IP集合Set<String> previousIps = new HashSet<>(ipThreadPoolMap.keySet());// 新增的 IPSet<String> newIps = new HashSet<>(currentIps);newIps.removeAll(previousIps);// 移除的 IPSet<String> removedIps = new HashSet<>(previousIps);removedIps.removeAll(currentIps);// 對新增的 IP 創建線程池for (String ip : newIps) {createThreadPoolForIp(ip);}// 對移除的 IP 銷毀線程池for (String ip : removedIps) {destroyThreadPoolForIp(ip);}}/*** 創建指定 IP 的線程池* @param ip 實例 IP*/public ThreadPoolExecutor createThreadPoolForIp(String ip) {// ThreadFactoryBuilder 設置線程名稱ThreadFactory customThreadFactory = new ThreadFactoryBuilder().setNamePrefix("nacos-pool-" + ip + "-thread-%d").setDaemon(false).setPriority(Thread.NORM_PRIORITY).build();// 創建線程池,超出隊列長度由調用者執行ThreadPoolExecutor executor = new ThreadPoolExecutor(nacosThreadPoolConfig.getCoreSize(),nacosThreadPoolConfig.getMaxSize(),nacosThreadPoolConfig.getKeepAliveTime(),TimeUnit.SECONDS,new LinkedBlockingQueue<>(nacosThreadPoolConfig.getQueueCapacity()),customThreadFactory,new ThreadPoolExecutor.CallerRunsPolicy());log.info("Created thread pool for IP: {}", ip);ipThreadPoolMap.put(ip, executor);return executor;}/*** 銷毀指定 IP 的線程池* @param ip 實例 IP*/private void destroyThreadPoolForIp(String ip) {ThreadPoolExecutor executor = ipThreadPoolMap.remove(ip);if (executor == null) {return;}executor.shutdown(); // 關閉線程池,不再接受新任務try {if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {executor.shutdownNow(); // 強制關閉}} catch (InterruptedException e) {executor.shutdownNow();Thread.currentThread().interrupt();}log.info("Destroyed thread pool for IP: {}", ip);}/*** 獲取指定 IP 的線程池* @param ip 實例 IP* @return 對應的線程池,如果不存在則返回 null*/public ThreadPoolExecutor getThreadPoolForIp(String ip) {ThreadPoolExecutor executor = ipThreadPoolMap.get(ip);// 獲取不到線程池手動創建if (executor == null) {executor = createThreadPoolForIp(ip);}return executor;}/*** 應用關閉時銷毀所有線程池*/@PreDestroypublic void shutdownAllThreadPools() {for (Map.Entry<String, ThreadPoolExecutor> entry : ipThreadPoolMap.entrySet()) {String ip = entry.getKey();ThreadPoolExecutor executor = entry.getValue();executor.shutdown();try {if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {executor.shutdownNow();}} catch (InterruptedException e) {executor.shutdownNow();Thread.currentThread().interrupt();}}ipThreadPoolMap.clear();log.info("succeed shutdown all thread pools.");}/*** 每分鐘監控一次線程池的狀態*/@Scheduled(fixedRate = 60000)public void monitorThreadPool() {for (Map.Entry<String, ThreadPoolExecutor> entry : ipThreadPoolMap.entrySet()) {String ip = entry.getKey();ThreadPoolExecutor executor = entry.getValue();log.info("Monitor thread pool. ip: {}, Active Threads: {}, Queue Size: {}",ip,executor.getActiveCount(),executor.getQueue().size());}}
}

執行線程任務 管理類?

package com.xxx.amedia.media.manager;import com.xxx.amedia.media.bo.FailureTaskBO;
import com.xxx.amedia.rpc.enums.RpcTypeEnum;
import com.xxx.amedia.rpc.model.RpcReloadResponse;
import com.xxx.amedia.rpc.proxy.RpcReloadProxy;
import com.xxx.amedia.system.api.NacosService;import cn.hutool.core.lang.Pair;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ThreadPoolExecutor;/*** 執行線程任務 管理類* @author xxx* @date 2025-5-23 11:01:07*/
@Slf4j
@Service
public class RpcReloadManager {@Autowiredprivate NacosService nacosService;@Autowiredprivate RpcReloadProxy rpcReloadProxy;@Autowiredprivate NacosThreadPoolManager threadPoolManager;/*** 異步執行任務  所有節點  無參* @param rpcTypeEnum rpc類型枚舉* @return 失敗節點列表*/public List<FailureTaskBO> execute(RpcTypeEnum rpcTypeEnum) {return execute(rpcTypeEnum, Collections.emptyList());}/*** 異步執行任務  所有節點  無參* @param rpcTypeEnum rpc類型枚舉* @param params rpc接口參數* @return 失敗節點列表*/public List<FailureTaskBO> execute(RpcTypeEnum rpcTypeEnum, Object params) {List<String> ips = nacosService.getInstanceIps();List<FailureTaskBO> failureList = new ArrayList<>();if (CollectionUtils.isEmpty(ips)) {return failureList;}CountDownLatch countDownLatch = new CountDownLatch(ips.size());ips.forEach(execNodeIp -> {try {execute(execNodeIp, rpcTypeEnum, params, failureList);} catch (Exception ex) {FailureTaskBO failureTaskBO = FailureTaskBO.builder().ip(execNodeIp).code(500).msg("rpc任務執行失敗").build();failureList.add(failureTaskBO);log.error("execute task occur exception: ip is {}, rpcTypeEnum is {}, msg is {}.", execNodeIp, rpcTypeEnum, ex.getMessage(), ex);} finally {countDownLatch.countDown();}});try {// 主線程等待所有任務完成countDownLatch.await();} catch (InterruptedException e) {// 恢復中斷狀態interrupt();}return failureList;}/*** 異步執行任務  指定節點列表* @param rpcTypeEnum rpc類型枚舉* @param ips 指定節點列表* @return 失敗節點列表*/public List<FailureTaskBO> executeForIps(RpcTypeEnum rpcTypeEnum, List<String> ips) {return executeForIps(rpcTypeEnum, ips, Collections.emptyList());}/*** 異步執行任務  指定節點列表* @param rpcTypeEnum rpc類型枚舉* @param ips 指定節點列表* @param params rpc接口參數* @return 失敗節點列表*/public List<FailureTaskBO> executeForIps( RpcTypeEnum rpcTypeEnum, List<String> ips, Object params) {List<FailureTaskBO> failureList = new ArrayList<>();if (CollectionUtils.isEmpty(ips)) {return failureList;}CountDownLatch countDownLatch = new CountDownLatch(ips.size());ips.forEach(execNodeIp -> {try {execute(execNodeIp, rpcTypeEnum, params, failureList);} catch (Exception ex) {FailureTaskBO failureTaskBO = FailureTaskBO.builder().ip(execNodeIp).code(500).msg("rpc reload error").build();failureList.add(failureTaskBO);log.error("execute task occur exception: ip is {}, rpcTypeEnum is {}, msg is {}.", execNodeIp, rpcTypeEnum, ex.getMessage(), ex);} finally {countDownLatch.countDown();}});try {// 主線程等待所有任務完成countDownLatch.await();} catch (InterruptedException e) {// 恢復中斷狀態interrupt();}return failureList;}/*** 恢復中斷狀態*/private void interrupt() {// 恢復中斷狀態Thread.currentThread().interrupt();log.info("Thread {} is interrupted.", Thread.currentThread().getName());}/*** 異步線程池執行rpc任務* @param execNodeIp 執行節點IP* @param rpcTypeEnum rpc類型枚舉* @param failureList 失敗節點信息* @throws ExecutionException 執行異常* @throws InterruptedException 中斷異常*/private void execute(String execNodeIp, RpcTypeEnum rpcTypeEnum, Object params, List<FailureTaskBO> failureList)throws ExecutionException, InterruptedException {ThreadPoolExecutor executor = threadPoolManager.getThreadPoolForIp(execNodeIp);FutureTask<Pair<Boolean, RpcReloadResponse>> futureTask = new FutureTask<>(() -> {return rpcReloadProxy.reload(execNodeIp, rpcTypeEnum, params);});executor.submit(futureTask);Pair<Boolean, RpcReloadResponse> pair = futureTask.get();if (!pair.getKey()) {FailureTaskBO failureTaskBO = bulidFailureTaskBO(pair, execNodeIp);failureList.add(failureTaskBO);}}/*** 構建失敗信息* @param pair rpc響應信息* @param execNodeIp 執行節點IP* @return FailureTaskBO*/private FailureTaskBO bulidFailureTaskBO(Pair<Boolean, RpcReloadResponse> pair, String execNodeIp) {RpcReloadResponse res = pair.getValue();FailureTaskBO failureTaskBO;if (res == null) {failureTaskBO = FailureTaskBO.builder().ip(execNodeIp).code(500).msg("rpc reload error").build();} else {failureTaskBO = FailureTaskBO.builder().ip(execNodeIp).code(res.getCode()).msg(res.getMsg()).build();}return failureTaskBO;}
}

nacos服務實例service類

package com.xxx.amedia.system.api;import com.xxx.amedia.system.converter.ServiceInstanceConverter;
import com.xxx.amedia.system.vo.ServiceInstanceVO;
import com.xxx.amedia.tool.common.constants.CommonConstants;import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;/*** nacos服務實例service類* @author xxx* @date 2025-5-17 11:38:22*/
@Service
public class NacosService{@Value("${media.rpc.service-name}")private String serviceName;@Autowiredprivate DiscoveryClient discoveryClient;@Autowiredprivate ServiceInstanceConverter serviceInstanceConverter;@Overridepublic List<ServiceInstanceVO> list() {List<ServiceInstance> serviceInstances = getInstances();return serviceInstanceConverter.toServiceInstanceVOList(serviceInstances);}/*** 從nacos獲取指定服務名的實例IP集合* @return 實例IP集合*/@Overridepublic List<String> getInstanceIps() {List<ServiceInstance> instances = getInstances();if (CollectionUtils.isEmpty(instances)) {return Collections.emptyList();}List<String> instanceIps = new ArrayList<>(instances.size());instances.forEach(instance -> {instanceIps.add(instance.getHost());});return instanceIps;}/*** 檢查icc-amedia-admin服務中是否存在指定 IP 的節點* @param instanceIps 獲取 icc-amedia-rpc 服務的所有實例Ip* @param targetIp 目標 IP(如 10.199.1.1)* @return true 存在 / false 不存在*/@Overridepublic boolean checkNodeExists(List<String> instanceIps, String targetIp) {// 遍歷實例,檢查 IPfor (String instanceIp : instanceIps) {if (StringUtils.equals(targetIp, instanceIp)) {return true;}}return false;}/*** 從nacos獲取指定服務名的實例集合* @return 實例集合*/private List<ServiceInstance> getInstances() {List<ServiceInstance> serviceInstances = discoveryClient.getInstances(serviceName);// 按host升序排列serviceInstances.sort(Comparator.comparing(ServiceInstance::getHost));return serviceInstances;}}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/81618.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/81618.shtml
英文地址,請注明出處:http://en.pswp.cn/web/81618.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

全面指南:使用Node.js和Python連接與操作MongoDB

在現代Web開發中&#xff0c;數據庫是存儲和管理數據的核心組件。MongoDB作為一款流行的NoSQL數據庫&#xff0c;以其靈活的數據模型、高性能和易擴展性廣受開發者歡迎。無論是使用Node.js還是Python&#xff0c;MongoDB都提供了強大的官方驅動和第三方庫&#xff0c;使得數據庫…

LeetCode 3068.最大節點價值之和:腦筋急轉彎+動態規劃(O(1)空間)

【LetMeFly】3068.最大節點價值之和&#xff1a;腦筋急轉彎動態規劃&#xff08;O(1)空間&#xff09; 力扣題目鏈接&#xff1a;https://leetcode.cn/problems/find-the-maximum-sum-of-node-values/ 給你一棵 n 個節點的 無向 樹&#xff0c;節點從 0 到 n - 1 編號。樹以長…

HTTPS加密通信詳解及在Spring Boot中的實現

HTTPS&#xff08;Hyper Text Transfer Protocol Secure&#xff09;是HTTP的安全版本&#xff0c;通過SSL/TLS協議為通訊提供加密、身份驗證和數據完整性保護。 一、HTTPS核心原理 1.加密流程概述 客戶端發起HTTPS請求&#xff08;連接到服務器443端口&#xff09;服務器返…

解決線程安全問題

前言 昨天學習了如何去解決線程不安全的問題。一般方法都是通過加鎖來處理&#xff0c;跟大家分享一波 。 解決線程安全問題 結語 希望可以幫助到大家~ byebye

網絡常識:網線和光纖的區別

網絡常識&#xff1a;網線和光纖的區別 一. 介紹二. 網線2.1 什么是網線&#xff1f;2.2 網線的主要類別2.3 網線的優勢2.4 網線的劣勢 三. 光纖3.1 什么是光纖&#xff1f;3.2 光纖的主要類別3.3 光纖的優勢3.4 光纖的劣勢 四. 網線 vs 光纖&#xff1a;誰更適合你&#xff1f…

win11 禁用/恢復 內置筆記本鍵盤(保證管用)

文章目錄 禁用啟用 禁用 1&#xff09;按下 win x&#xff0c;點擊 設備管理器 2&#xff09;拔掉所有筆記本外設&#xff08;一定要都拔掉&#xff0c;不然后面禁用設備會混淆&#xff09;&#xff0c;然后右鍵點擊 鍵盤 > HID Keyboard Device 2&#xff09;點擊 更新…

Three.js搭建小米SU7三維汽車實戰(5)su7登場

汽車模型加載 我們在sktechfab上下載的汽車是glb的文件格式&#xff0c;所以使用gltfLoader進行加載。這里將小車直接加載進來看看效果&#xff1b; import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js"; ....其余代碼省略 const gltfLoader new GLT…

ETL怎么實現多流自定義合并?

隨著信息技術的迅猛發展以及數據生成環境的多樣化&#xff0c;互聯網、物聯網和社交媒體的廣泛應用導致各種設備和平臺不斷產生大量數據&#xff0c;需要整合這些數據&#xff0c;從而進行數據融合。數據集成和管理平臺ETLCloud&#xff0c;主要用于支持數據的抽取&#xff08;…

數據結構- 10種常見樹:二叉樹、平衡二叉樹、完全二叉樹

一、樹 樹型結構是一類重要的非線性數據結構。其中以樹和二叉樹最為常用&#xff0c;直觀看來&#xff0c;樹是以分支關系定義的層次結構。把它叫做“樹”是因為它常看起來像一棵倒掛的樹&#xff0c;也就是說它常是根朝上&#xff0c;而葉朝下的。 1.樹的定義&#xff1a; 樹…

Java常用加密方式

一&#xff0c;加密算法分類 對稱加密&#xff1a;指加密和解密的密鑰相同&#xff0c;優點就是加解密的效率高且易于實現。 非對稱加密&#xff1a;指加密和解密的密鑰不相同&#xff0c;也稱為公私要加密。 不可逆加密&#xff1a;特征就是加密過程不需要密鑰&#xff0c;…

SQLite軟件架構與實現源代碼淺析

概述 SQLite 是一個用 C 語言編寫的庫&#xff0c;它成功打造出了一款小型、快速、獨立、具備高可靠性且功能完備的 SQL 數據庫引擎。本文檔將為您簡要介紹其架構、關鍵組件及其協同運作模式。 SQLite 顯著特點之一是無服務器架構。不同于常規數據庫&#xff0c;它并非以單獨進…

讓 Deepseek GPS測速

下面是一個簡單的微信小程序GPS測速功能的實現代碼&#xff0c;包括前端頁面和后端邏輯。 1. 頁面結構 (index.wxml) <view class"container"><view class"speed-display"><text class"speed-value">{{speed}}</text>…

什么是軟件的生命周期,以及常見的開發測試模型

目錄 一、軟件的生命周期 1、什么是生命周期&#xff1f; 2、每個階段都要做些什么&#xff1f; 二、常見的開發模型 1、瀑布模型 2、螺旋模型 3、增量模型、迭代模型 4、敏捷模型 scrum模型 三個角色 五個會議 一、軟件的生命周期 1、什么是生命周期&#xff…

JWT安全:弱簽名測試.【實現越權繞過.】

JWT安全&#xff1a;假密鑰【簽名隨便寫實現越權繞過.】 JSON Web 令牌 (JWT)是一種在系統之間發送加密簽名 JSON 數據的標準化格式。理論上&#xff0c;它們可以包含任何類型的數據&#xff0c;但最常用于在身份驗證、會話處理和訪問控制機制中發送有關用戶的信息(“聲明”)。…

數據分析與應用-----使用scikit-learn構建模型

目錄 一、使用sklearn轉換器處理數據 &#xff08;一&#xff09;、加載datasets模塊中的數據集 &#xff08;二&#xff09;、將數據集劃分為訓練集和測試集 ?編輯 train_test_spli &#xff08;三&#xff09;、使用sklearn轉換器進行數據預處理與降維 PCA 二、 構…

【Tomcat】Tomcat端口僅允許本地訪問設置方法

要設置Tomcat端口僅允許本地訪問&#xff0c;可以通過以下兩種主要方式實現&#xff1a; 方法一&#xff1a;修改Tomcat配置文件&#xff08;推薦&#xff09; 修改 server.xml 文件 打開Tomcat的配置文件 conf/server.xml&#xff0c;找到 <Connector> 標簽&#xff08;…

arcgis字段計算器中計算矢量面的每個點坐標

python腳本 函數 def ExportCoordinates(feat):coors = []partnum = 0partcount = feat.partCountwhile partnum < partcount:part = feat.getPart(partnum)pnt = part.next()while pnt:coors.append("({}, {})".format(pnt.X,pnt.Y))pnt = part.next()if not p…

企業級AI開啟落地戰,得場景者得天下

文&#xff5c;白 鴿 編&#xff5c;王一粟 這兩周&#xff0c;企業級智能體開發平臺頗有你方唱罷我方登臺的架勢。 微軟、騰訊、網易等國內外巨頭&#xff0c;近期都相繼宣布推出了新一代智能體開發平臺。相比于兩年前&#xff0c;智能體開發的產品邏輯已經有了翻天覆地的變…

探索C++標準模板庫(STL):String接口實踐+底層的模擬實現(中篇)

前引&#xff1a;上一篇文章小編已經整理出了String的常用接口&#xff0c;梳理了各個接口的功能、參數&#xff0c;如何使用等各種實例。本篇文章將帶大家看看String這些接口的實踐使用&#xff0c;探索這些接口的實用性&#xff0c;是如何增加代碼效率的。在本篇文章的末尾&a…

【模型顯著性分析】配對樣本 t 檢驗

寫在前面&#xff1a;本博客僅作記錄學習之用&#xff0c;部分圖片來自網絡&#xff0c;如需引用請注明出處&#xff0c;同時如有侵犯您的權益&#xff0c;請聯系刪除&#xff01; 文章目錄 前言 t t t 檢驗配對樣本 t t t 檢驗&#xff08;適用于相關組&#xff09;代碼論文描…