Xxl-Job學習筆記

目錄

概述

核心架構

核心特點

應用場景

什么是任務調度

快速入門

獲取源碼

初始化調度數據庫

基本配置

數據源datasource

郵箱email(可選)

會話令牌access token

啟動調度中心

啟動執行器

依賴

yaml基本配置

XxlJobConfig類配置

定義執行任務

添加執行任務

初級階段

時間轉為Cron表達式工具類

XxlJobRemoteApiUtils工具類

引入遠程發送請求依賴

允許遠程調用

概述

????????XXL-Job 是一個輕量級、分布式任務調度平臺,由國內技術團隊開發并開源。它旨在解決分布式系統中的定時任務調度問題,提供了一整套簡單、高效且可靠的解決方案

核心架構

XXL-Job 的架構主要由以下幾部分組成:

  • 調度中心(Admin):負責任務的管理、調度策略、觸發時機以及調度請求的發起。它提供了可視化的 Web 管理界面,方便用戶進行任務的增刪改查和調度監控。
  • 執行器(Executor):部署在業務服務環境中,用于接收調度中心的請求并執行具體的任務邏輯

  • 任務代碼:由開發者編寫的業務邏輯代碼,注冊到執行器中,由調度中心觸發執行

核心特點

  • 輕量級設計:核心代碼簡潔高效,易于集成和部署

  • 分布式調度:支持多機分布式部署,可水平擴展,提高系統可用性和負載能力

  • 簡單易用:提供簡潔的 API 和可視化界面,便于任務的創建、管理和監控

  • 功能豐富:支持多種任務類型(如定時任務、周期任務、一次性任務),并提供任務分片、失敗重試、任務依賴等功能

  • 彈性擴縮容:支持動態添加或移除執行器節點,無需停止服務

  • 高可用性:通過多節點部署和故障轉移機制,確保任務的不中斷執行

應用場景

XXL-Job 廣泛應用于以下場景:

  • 定時任務:如數據備份、報表生成、系統維護等

  • 分布式任務處理:支持任務分片并行執行,提高任務處理效率

  • 彈性擴縮容:根據業務量動態調整執行器數量,應對業務波動

  • 業務流程自動化:實現復雜業務流程的自動化調度

什么是任務調度

我們可以思考一下下面業務場景的解決方案:

  • 某電商平臺需要每天上午10點,下午3點,晚上8點發放一批優惠券
  • 某銀行系統需要在信用卡到期還款日的前三天進行短信提醒
  • 某財務系統需要在每天凌晨0:10分結算前一天的財務數據,統計匯總

以上場景就是任務調度所需要解決的問題。

任務調度是為了自動完成特定任務,在約定的特定時刻去執行任務的過程。

快速入門

官網:?分布式任務調度平臺XXL-JOB

獲取源碼

源碼倉庫地址
https://github.com/xuxueli/xxl-job
xxl-job: 一個分布式任務調度平臺,其核心設計目標是開發迅速、學習簡單、輕量級、易擴展。現已開放源代碼并接入多家公司線上產品線,開箱即用。
GitCode - 全球開發者的開源社區,開源代碼托管平臺

獲取源碼解壓即可

初始化調度數據庫

打開項目我們可以獲取到 調度數據庫 ,路徑為: xxl-job-master/doc/db/tables_xxl_job.sql

使用 數據庫連接工具初始化運行即可。

基本配置

數據源datasource

隨后打開使用 xxl-job-admin 模塊,這個模塊就是用于管理我們的調度。并修改我們數據相關配置:

郵箱email(可選)

email 的相關配置,就是 當我們調度執行失敗的時候,可以通過 email 進行通知。具體email 的配置,通過個人的郵箱平臺相關配置即可。

會話令牌access token

執行器 連接 調度中心 所需要的令牌。

啟動調度中心

啟動 admin 模塊

調度中心訪問地址: http://localhost:8080/xxl-job-admin

默認登錄賬號“admin/123456”,登錄后運行界面如下圖所示

啟動執行器

打開你自己的項目,并進行相關配置。

依賴
<!--       xxl-job --><dependency><groupId>com.xuxueli</groupId><artifactId>xxl-job-core</artifactId><version>2.3.1</version></dependency>
yaml基本配置
dev:xxl:job:admin:### 調度中心部署根地址 [選填]:如調度中心集群部署存在多個地址則用逗號分隔。執行器將會使用該地址進行"執行器心跳注冊"和"任務結果回調";為空則關閉自動注冊;addresses: http://localhost:8080/xxl-job-admin### 調度中心通訊TOKEN [選填]:非空時啟用;accessToken: default### 調度中心通訊超時時間[選填],單位秒;默認3s;executor:### 執行器AppName [選填]:執行器心跳注冊分組依據;為空則關閉自動注冊appname: xxl-job-executor-sample### 執行器注冊 [選填]:優先使用該配置作為注冊地址,為空時使用內嵌服務 ”IP:PORT“ 作為注冊地址。從而更靈活的支持容器類型執行器動態IP和動態映射端口問題。address:### 執行器IP [選填]:默認為空表示自動獲取IP,多網卡時可手動設置指定IP,該IP不會綁定Host僅作為通訊使用;地址信息用于 "執行器注冊" 和 "調度中心請求并觸發任務";ip: localhost### 執行器端口號 [選填]:小于等于0則自動獲取;默認端口為9999,單機部署多個執行器時,注意要配置不同執行器端口;port: 9999### 執行器運行日志文件存儲磁盤路徑 [選填] :需要對該路徑擁有讀寫權限;為空則使用默認路徑;logpath: /data/applogs/xxl-job/jobhandler### 執行器日志文件保存天數 [選填] : 過期日志自動清理, 限制值大于等于3時生效; 否則, 如-1, 關閉自動清理功能;logretentiondays: 30
XxlJobConfig類配置
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Slf4j
@Configuration
public class XxlJobConfig {@Value("${xxl.job.admin.addresses}")private String adminAddresses;@Value("${xxl.job.admin.accessToken}")private String accessToken;@Value("${xxl.job.executor.appname}")private String appname;@Value("${xxl.job.executor.ip}")private String ip;@Value("${xxl.job.executor.port}")private int port;@Value("${xxl.job.executor.logpath}")private String logPath;@Value("${xxl.job.executor.logretentiondays}")private int logRetentionDays;@Beanpublic XxlJobSpringExecutor xxlJobExecutor() {log.info(">>>>>>>>>>> xxl-job config init.");log.info("adminAddress:{}", adminAddresses);log.info("appname:{}", appname);log.info("ip:{}", ip);log.info("port:{}", port);log.info("accessToken:{}", accessToken);log.info("logPath:{}", logPath);log.info("logRetentionDays:{}", logRetentionDays);log.info(">>>>>>>>>>> xxl-job config init finish.");XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();xxlJobSpringExecutor.setAdminAddresses(adminAddresses);xxlJobSpringExecutor.setAppname(appname);xxlJobSpringExecutor.setIp(ip);xxlJobSpringExecutor.setPort(port);xxlJobSpringExecutor.setAccessToken(accessToken);xxlJobSpringExecutor.setLogPath(logPath);xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);return xxlJobSpringExecutor;}
}

隨后啟動我們自己的項目。

同時查看執行器管理器

可以發現遠程注冊端口節點成功。

定義執行任務

添加執行任務

import com.xxl.job.core.handler.annotation.XxlJob;
import org.springframework.stereotype.Component;import java.util.Date;@Component
public class SimpleXxlJob {@XxlJob("simpleJobHandler")   // 注解內的參數為我們運行模式為 Bean 類型對應的 JobHandlerpublic void simpleJobHandler() throws Exception {System.out.println("執行定時任務,執行時間>>>>>>>>>>> xxl-job, Hello World." + new Date());}
}

嘗試執行一次。

通過我們執行一次成功后并調用對應方法,即可。可以根據我們自己需求進行啟動配置對應的方法了。

初級階段

有時候我們需要的是,用戶使用自己的前端去設置觸發的時間。并不是我們去xxl-job-admin 的管理端進行添加定時任務的。

時間轉為Cron表達式工具類

以下是我收集的所用到的工具類。可以參考一下。


import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;/**** <p>* 將時間轉為Cron表達式* </p> ** @author Angindem* @since 2025-03-08**/
public class CronUtils {private static final DateTimeFormatter FORMAT = DateTimeFormatter.ofPattern("ss mm HH dd MM ? yyyy");public enum TimeCycle {YEAR, MONTH, WEEK, DAY, HOUR, MINUTE, SECOND}/*** 將LocalDateTime轉換為cron表達式的字符串。* @param dateTime 要轉換的時間字符串* @param format 要轉換的時間格式* @return cron表達式*/public static String toCronExpression(String dateTime, String format) {LocalDateTime localDate = LocalDateTime.parse(dateTime, DateTimeFormatter.ofPattern(format));String date = localDate.format(FORMAT);return date;}/*** 將LocalDateTime轉換為cron表達式的字符串。* @param dateTime 要轉換的LocalDateTime* @return cron表達式*/public static String toCronExpression(LocalDateTime dateTime) {String date = dateTime.format(FORMAT);return date;}/*** 將多個 LocalDateTime 對象轉換為一個 cron 表達式字符串* @param times LocalDateTime 對象列表* @return cron 表達式字符串*/public static String convertToCron(List<LocalDateTime> times) {// 提取秒、分、時、日、月、周幾int second = times.get(0).getSecond();int minute = times.get(0).getMinute();List<Integer> hours = new ArrayList<>();List<Integer> daysOfMonth = new ArrayList<>();List<Integer> months = new ArrayList<>();List<Integer> daysOfWeek = new ArrayList<>();for (LocalDateTime time : times) {hours.add(time.getHour());daysOfMonth.add(time.getDayOfMonth());months.add(time.getMonthValue());daysOfWeek.add(time.getDayOfWeek().getValue());}// 構造Cron表達式StringBuilder cron = new StringBuilder();cron.append(second).append(" ");cron.append(minute).append(" ");cron.append(String.join(",", hours.stream().map(Object::toString).collect(Collectors.toList()))).append(" ");cron.append(String.join(",", daysOfMonth.stream().map(Object::toString).collect(Collectors.toList()))).append(" ");cron.append(String.join(",", months.stream().map(Object::toString).collect(Collectors.toList()))).append(" ");cron.append(String.join(",", daysOfWeek.stream().map(Object::toString).collect(Collectors.toList())));return cron.toString();}/*** 將指定的 LocalDateTime 對象轉換為 指定周期的 cron 表達式字符串* @param dateTime LocalDateTime 對象* @param timeCycle 時間周期枚舉值* @return cron 表達式字符串*/public static String toCronExpression(LocalDateTime dateTime, TimeCycle timeCycle) {String cron = null;switch (timeCycle) {case YEAR:cron = String.format("%d %d %d %d %d ? *", dateTime.getSecond(),dateTime.getMinute(), dateTime.getHour(), dateTime.getDayOfMonth(),dateTime.getMonthValue());break;case MONTH:cron = String.format("%d %d %d %d * ? *", dateTime.getSecond(),dateTime.getMinute(), dateTime.getHour(), dateTime.getDayOfMonth());break;case WEEK:cron = String.format("%d %d %d ? * %d *", dateTime.getSecond(),dateTime.getMinute(), dateTime.getHour(), dateTime.getDayOfWeek().getValue() % 7);break;case DAY:cron = String.format("%d %d %d * * ? *", dateTime.getSecond(),dateTime.getMinute(), dateTime.getHour());break;case HOUR:cron = String.format("%d %d * * * ? *", dateTime.getSecond(),dateTime.getMinute());break;case MINUTE:cron = String.format("%d * * * * ? *", dateTime.getSecond());break;case SECOND:cron = "0/1 * * * * ? *";break;default:throw new IllegalArgumentException("Unknown time cycle: " + timeCycle);}return cron;}
}

XxlJobRemoteApiUtils工具類

轉完 Cron 表達式后,我們可以通過遠程調用 xxl-job-admin 的對應接口進行操作添加。

引入遠程發送請求依賴
        <!--httpclient的坐標用于在java中發起請求--><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version></dependency><!--使用fastjson解析json數據 --><dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><version>2.0.42</version></dependency>

以下是我收集并使用的工具類,可以做一下參考。


import com.fasterxml.jackson.databind.ObjectMapper;
import com.pea.mic.domain.po.XxlJobInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;@Slf4j
@Component
public class XxlJobRemoteApiUtils {private static String adminAddresses;private static String appname;private static String accessToken;private final static RestTemplate restTemplate = new RestTemplate();private static final String ADD_URL = "/jobinfo/add";private static final String UPDATE_URL = "/jobinfo/update";private static final String REMOVE_URL = "/jobinfo/remove";private static final String PAUSE_URL = "/jobinfo/pause";private static final String START_URL = "/jobinfo/start";@Autowiredpublic void init(Environment env) {adminAddresses = env.getProperty("xxl.job.admin.addresses");appname = env.getProperty("xxl.job.executor.appname");accessToken = env.getProperty("xxl.job.admin.accessToken");log.info("xxl.job.admin.addresses:{}", adminAddresses);log.info("xxl.job.executor.appname:{}", appname);log.info("xxl.job.accessToken:{}", accessToken);}public static Map getJobInfoByLocalDateTime(LocalDateTime times,String author,String JobDesc,String taskHandler){String cron = CronUtils.toCronExpression(times);XxlJobInfo jobInfo = new XxlJobInfo();jobInfo.setJobGroup(2);jobInfo.setJobDesc(JobDesc);jobInfo.setAuthor(author);jobInfo.setScheduleType("CRON");jobInfo.setMisfireStrategy("DO_NOTHING");//執行時間jobInfo.setScheduleConf(cron);jobInfo.setGlueType("BEAN");jobInfo.setExecutorHandler(taskHandler);jobInfo.setExecutorRouteStrategy("FIRST");jobInfo.setExecutorBlockStrategy("SERIAL_EXECUTION");jobInfo.setExecutorTimeout(0);jobInfo.setExecutorFailRetryCount(0);jobInfo.setGlueType("BEAN");jobInfo.setGlueRemark("GLUE代碼初始化");jobInfo.setTriggerStatus(0);jobInfo.setTriggerLastTime(0);jobInfo.setTriggerNextTime(0);ObjectMapper objectMapper = new ObjectMapper();Map map = objectMapper.convertValue(jobInfo, Map.class);return map;}public static String add(Map param){return doPost(adminAddresses + ADD_URL, param);}public static String update(String id, String cron){Map param = new HashMap<>();param.put("id", id);param.put("jobCron", cron);return doPost(adminAddresses + UPDATE_URL, param);}public static String remove(String id){Map param = new HashMap<>();param.put("id", id);return doGet(adminAddresses + REMOVE_URL, param);}public static String pause(String id){Map param = new HashMap<>();param.put("id", id);return doGet(adminAddresses + PAUSE_URL, param);}public static String start(String id){Map param = new HashMap<>();param.put("id", id);return doGet(adminAddresses + START_URL, param);}public static String doPost(String url, Map fromData){HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_JSON);headers.add("accessToken", accessToken);HttpEntity<Map> entity = new HttpEntity<>(fromData ,headers);log.info(entity.toString());ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity(url, entity, String.class);return stringResponseEntity.getBody().toString();}public static String doGet(String url, Map<String, String> params) {// 創建可關閉的HttpClient,使用try-with-resources確保資源自動關閉try (CloseableHttpClient httpClient = HttpClients.createDefault()) {// 使用URIBuilder來構建帶參數的URLURIBuilder uriBuilder = new URIBuilder(url);// 將Map中的參數添加到URL中if (params != null) {for (Map.Entry<String, String> entry : params.entrySet()) {uriBuilder.setParameter(entry.getKey(), entry.getValue());}}// 創建GET請求對象HttpGet httpGet = new HttpGet(uriBuilder.build());httpGet.setHeader("accessToken", accessToken);// 設置請求配置(超時等)
//            httpGet.setConfig(buildRequestConfig());// 執行請求并獲取響應try (CloseableHttpResponse response = httpClient.execute(httpGet)) {// 判斷響應狀態碼是否為200(成功)if (response.getStatusLine().getStatusCode() == 200) {// 獲取響應內容并轉換為字符串String result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);log.info("GET Response body: {}", result);return result;}}} catch (Exception e) {log.error("發送GET請求出錯: ", e);}return null;}
}

允許遠程調用

通過二次開發xxl-job-admin,允許遠程調用,修改方法如下:

通過發送請求并,走的流程,可以直到調用接口的時候是通過請求參數中的XXL_JOB_LOGIN_IDENTITY 進行校驗,我們可以通過當我們發送的請求參數,直接獲取即可cookieToken,即可。

PS:由于博主已經實驗成功過了,具體方法,大家可以參考參考即可。博主就不走結果啦。

----------------------------持續更新中----------------------------

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

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

相關文章

讓雙向鏈表不在云里霧里

又來博客留下我的足跡了&#xff0c;哈哈哈&#xff0c;這次是對于雙向鏈表的理解 目錄 創建雙向鏈表&#xff1a; 申請結點&#xff1a; 雙向鏈表初始化&#xff1a; 雙向鏈表插入結點&#xff1a; 雙向鏈表刪除結點&#xff1a; 雙向鏈表的打印&#xff1a; 雙向鏈表…

java虛擬機(JVM)以及各種參數詳解

Java 虛擬機&#xff08;JVM&#xff09;提供了許多參數來調整其行為和性能&#xff0c;以便更好地適應不同的應用場景。理解和使用這些參數對于優化 Java 應用程序的性能非常重要。以下是一些常用的 JVM 參數及其詳細說明&#xff1a; 1. 內存管理參數 -Xms<size>&…

如何搭配 AI 量化策略選股

AI 量化選股策略結合了 技術指標、基本面數據、市場情緒&#xff0c;利用 機器學習、深度學習、因子分析 等方法&#xff0c;提高選股精準度和交易決策效率。下面介紹 如何搭配 AI 量化策略選股。 1. AI 量化選股的核心方法 AI 量化選股主要依靠 數據驅動&#xff0c;包括&…

Python 爬蟲:一文掌握 SVG 映射反爬蟲

更多內容請見: 爬蟲和逆向教程-專欄介紹和目錄 文章目錄 1. SVG 概述1.1 SVG的優點1.1 映射反爬蟲的原理2. SVG 映射反爬蟲的示例3. 應對 SVG 映射反爬蟲的方法3.1 解析 SVG 圖像3.2 處理自定義字體3.3 使用 OCR 技術3.4 動態生成 SVG 的處理4. 實戰案例4.1 使用 SVG 映射顯示…

前端工程化之前端工程化詳解 包管理工具

前端工程化詳解 & 包管理工具 前端工程化什么是前端工程化前端工程化發展腳手架能力 體驗度量規范流程效能流程扭轉 穩定性建設針對整體穩定性建設 可監控&#xff1a;前端監控系統 包管理工具npm包詳解package.jsonname 模塊名description 模塊描述信息keywords&#xff1…

《Python實戰進階》No24: PyAutoGUI 實現桌面自動化

No24: PyAutoGUI 實現桌面自動化 摘要 PyAutoGUI 是一個跨平臺的桌面自動化工具&#xff0c;能夠模擬鼠標點擊、鍵盤輸入、屏幕截圖與圖像識別&#xff0c;適用于重復性桌面任務&#xff08;如表單填寫、游戲操作、批量文件處理&#xff09;。本集通過代碼截圖輸出日志的實戰形…

一周學會Flask3 Python Web開發-SQLAlchemy查詢所有數據操作-班級模塊

鋒哥原創的Flask3 Python Web開發 Flask3視頻教程&#xff1a; 2025版 Flask3 Python web開發 視頻教程(無廢話版) 玩命更新中~_嗶哩嗶哩_bilibili 我們來新建一個的藍圖模塊-班級模塊&#xff0c;后面可以和學生模塊&#xff0c;實現一對多的數據庫操作。 blueprint下新建g…

Neural Architecture Search for Transformers:A Survey

摘要 基于 Transformer 的深度神經網絡架構因其在自然語言處理 (NLP) 和計算機視覺 (CV) 領域的各種應用中的有效性而引起了極大的興趣。這些模型是多種語言任務&#xff08;例如情緒分析和文本摘要&#xff09;的實際選擇&#xff0c;取代了長短期記憶 (LSTM) 模型。視覺 Tr…

TCP 全連接隊列 內核層理解socket

TCP 全連接隊列 理解 listen 的第二個參數 int listen(int sockfd, int backlog);backlog 參數表示 全連接隊列&#xff08;accept 隊列&#xff09;的最大長度。 那什么是全連接隊列呢&#xff1f; 三次握手 & accept() 處理流程 客戶端發送 SYN&#xff0c;服務器收到并…

程序化廣告行業(18/89):交易模式與關鍵概念解析

程序化廣告行業&#xff08;18/89&#xff09;&#xff1a;交易模式與關鍵概念解析 大家好呀&#xff01;一直以來&#xff0c;我都在深入研究程序化廣告這個充滿挑戰與機遇的領域&#xff0c;在學習過程中收獲了很多&#xff0c;也迫不及待想和大家分享。寫這篇博客&#xff…

在離線情況下如何使用 Python 翻譯文本

以下是在離線環境下使用Python進行文本翻譯的兩種主流方案&#xff0c;包含本地模型部署和輕量級詞典兩種方法&#xff1a; 方案一&#xff1a;使用本地神經網絡翻譯模型&#xff08;推薦&#xff09; # 安裝依賴&#xff08;需提前下載&#xff09; # pip install argos-tra…

OpenEuler-22.03-LTS上利用Ansible輕松部署MySQL 5.7

一、需求 使用ansible自動化部署mysql二進制部署mysql部署mysql并創建JDBC用戶 二、環境信息 本文涉及的代碼&#xff0c;配置文件地址&#xff1a; 鏈接&#xff1a;百度網盤 請輸入提取碼 提取碼&#xff1a;1g6y 軟件名稱版本備注Ansible2.9.27All modules — Ansible Doc…

基于javaweb的SpringBoot農資商城購物商城系統設計與實現(源碼+文檔+部署講解)

技術范圍&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬蟲、數據可視化、小程序、安卓app、大數據、物聯網、機器學習等設計與開發。 主要內容&#xff1a;免費功能設計、開題報告、任務書、中期檢查PPT、系統功能實現、代碼編寫、論文編寫和輔導、論…

angular打地鼠

說明&#xff1a;我計劃用angular做一款打地鼠的小游戲&#xff0c; 打地鼠游戲實現文檔 &#x1f3ae; 游戲邏輯 ?游戲場景 采用 3x3 網格布局的 9 個地鼠洞?核心機制 地鼠隨機從洞口彈出點擊有效目標獲得積分30 秒倒計時游戲模式 ?難度系統 簡單模式&#xff1a;生成間…

博客網站(springboot)整合deepseek實現在線調用

&#x1f389;&#x1f389;&#x1f389;&#x1f389;&#x1f389;&#x1f389; 歡迎訪問的個人博客&#xff1a;https://swzbk.site/&#xff0c;加好友&#xff0c;拉你入福利群 &#x1f389;&#x1f389;&#x1f389;&#x1f389;&#x1f389;&#x1f389; 1、de…

Kubernetes 單節點集群搭建

Kubernetes 單節點集群搭建教程 本人嘗試基于Ubuntu搭建一個單節點K8S集群&#xff0c;其中遇到各種問題&#xff0c;最大的問題就是網絡&#xff0c;各種鏡像源下載不下來&#xff0c;特此記錄&#xff01;注意&#xff1a;文中使用了幾個鏡像&#xff0c;將看來可能失效導致安…

【PTA題目解答】7-3 字符串的全排列(20分)next_permutation

1.題目 給定一個全由小寫字母構成的字符串&#xff0c;求它的全排列&#xff0c;按照字典序從小到大輸出。 輸入格式: 一行&#xff0c;一個字符串&#xff0c;長度不大于8。 輸出格式: 輸出所有全排列&#xff0c;每行一種排列形式&#xff0c;字典序從小到大。 輸入樣例…

專題三0~n-1中缺失的數字

1.題目 給一個數組&#xff0c;單調性是遞增的&#xff0c;需要找到缺失的數字&#xff0c;加上這個數字就變為等差數組了。 2.算法原理 這里用二分來解決&#xff0c;而二段性是根據下標區分&#xff0c;臨界值前的數字于下標相對應&#xff0c;臨界值后的于下標相差1&#x…

【圖像處理】ISP(Image Signal Processor) 圖像處理器的用途和工作原理?

ISP&#xff08;圖像信號處理器&#xff09;是數字影像設備的“視覺大腦”&#xff0c;負責將傳感器捕獲的原始電信號轉化為我們看到的高清圖像。以下從用途和工作原理兩方面通俗解析&#xff1a; 一、ISP的核心用途&#xff1a;讓照片“更像眼睛看到的” 提升畫質&#xff1a…

python學習筆記-mysql數據庫操作

現有一個需求&#xff0c;調用高德api獲取全國縣級以上行政區數據并保存為json文件&#xff0c;使用python獲取&#xff1a; import requests import json# 高德API Key api_key "your_api_key"# 調用行政區域查詢API def fetch_districts():url f"https://r…