(JAVA)自建應用調用企業微信API接口,實現消息推送

建議先簡單了解企業微信開發者中心文檔:開發前必讀 - 文檔 - 企業微信開發者中心

了解一下企業微信調用接口的基礎參數:基本概念介紹 - 文檔 - 企業微信開發者中心

本篇每個步驟都會跟著官網文檔走,都會貼上相關鏈接,看完本篇文章,可以獲得技能:

1、學會查看各應用的開發文檔

2、學會調用接口,對接口的處理

3、學會redis和redisson的使用

4、學會封裝數據傳輸對象(DTO)來調用接口和獲取返回值

5、學會使用Spring WebFlux的非阻塞HTTP客戶端的使用

實現所需以下步驟:

1、獲取企業的IDSecretID

2、根據ID和SecretID從而獲取access_token

3、對access_token進行緩存

4、調用接口發送信息

1、獲取企業的ID和SecretID

操作:先注冊好你的企業 -> 點擊頭像 -> 管理企業

進入管理企業頁面后

操作:應用管理 - > 創建應用

進入創建應用后

填寫你的企業信息,點擊創建應用

創建應用完成后

操作:返回應用管理 - > 點擊你新創建的應用

1.1、獲取到企業的SecretID

操作:點擊查看就能獲取SecretID(會發送到你的企業微信)

1.2、獲取到企業的ID

操作 :我的企業 - > 企業信息 - > 拉到最底下能看到企業ID

2、根據ID和SecretID從而獲取access_token

文檔對應位置:獲取access_token - 文檔 - 企業微信開發者中心

注意點:

請求方式:?GET(HTTPS
請求地址:?https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ID&corpsecret=SECRET

參數必須說明
corpid企業ID,獲取方式參考:術語說明-corpid
corpsecret應用的憑證密鑰,注意應用需要是啟用狀態,獲取方式參考:術語說明-secret

2.1、獲取access_token

1、使用postman獲取

返回結果:

{ "errcode": 0, "errmsg": "ok", "access_token": "accesstoken000001", "expires_in": 7200 }

翻譯:

errcode出錯返回碼,為0表示成功,非0表示調用失敗
errmsg返回碼提示語
access_token獲取到的憑證,最長為512字節
expires_in憑證的有效時間(秒)

注意事項:(在文中第3點會貼出代碼,來實現如何通過redis來對access_token進行緩存
開發者需要緩存access_token,用于后續接口的調用(注意:不能頻繁調用gettoken接口,否則會受到頻率攔截)。當access_token失效或過期時,需要重新獲取。

access_token的有效期通過返回的expires_in來傳達,正常情況下為7200秒(2小時)。
由于企業微信每個應用的access_token是彼此獨立的,所以進行緩存時需要區分應用來進行存儲。
access_token至少保留512字節的存儲空間。
企業微信可能會出于運營需要,提前使access_token失效,開發者應實現access_token失效時重新獲取的邏輯。

2、springboot單元測試獲取

wxService代碼在后面講到redis緩存access_token時會貼上

2.2、獲取失敗解決 - 新版本需要加入企業可信IP

意思是不允許你當前的ip進行訪問(你的ip不可信)

新版本企業微信需要配置企業可信IP才能使用

配置IP地址:

如果出現以下情況:配置企業可信IP前,請先?設置可信域名?或?設置接收消息服務器URL

詳情解決辦法請看我另外一篇文章:

(JAVA)自建應用調用企業微信API接口,設置企業可信IP-CSDN博客

3、對access_token進行緩存

使用redis+redisson分布式鎖,對access_token進行相關緩存操作。

代碼實現:(思路邏輯都已經備注在代碼里)

public String getAccessTokenByRedis() {//從redis中獲取wx_access_tokenObject cacheObject = redisCache.getCacheObject("wx_access_token");//如果存在,直接返回access_tokenif(cacheObject != null){return cacheObject.toString();}//如果不存在,獲取分布式鎖RLock lock = redissonClient.getLock("wx_access_token_lock");//默認未上鎖boolean locked = false;try {//嘗試獲取鎖,最多等待3秒,上鎖后10秒自動釋放locked = lock.tryLock(3,10, TimeUnit.SECONDS);//如果獲取到鎖,再次從redis中獲取access_token,防止在上鎖期間,其他線程已經獲取到鎖并更新了access_token。if (locked) {cacheObject = redisCache.getCacheObject("wx_access_token");if(cacheObject != null){return cacheObject.toString();}String accessToken = getAccessTokenByApi();//企業微信接口的返回值access_token有效期為7200秒,這里存入redis設置為7000秒,防止臨界值過期問題。redisCache.setCacheObject("wx_access_token", accessToken,7000, TimeUnit.SECONDS);return accessToken;}else{//未取到鎖throw new RuntimeException("獲取 access_token 超時,請稍后再試");}}catch (Exception e){throw new RuntimeException("Redisson 鎖被中斷", e);}finally {if(locked && lock.isHeldByCurrentThread()){lock.unlock();}}}

代碼中的:redisCache是ruoyi框架封裝好的redis工具類,調用的是redis的redisTemplate,可自行封裝。

getCacheObject:

setCacheObject:

4、調用接口發送信息

了解調用消息推送的傳輸過程:概述 - 文檔 - 企業微信開發者中心

4.1、查看發送應用消息接口文檔

發送應用消息 - 文檔 - 企業微信開發者中心

4.2、接口地址與請求方式

請求方式:POST(HTTPS
請求地址:?https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=ACCESS_TOKEN

參數是否必須說明
access_token調用接口憑證

4.3、返回示例

{
? "errcode" : 0,
? "errmsg" : "ok",
? "invaliduser" : "userid1|userid2",
? "invalidparty" : "partyid1|partyid2",
? "invalidtag": "tagid1|tagid2",
? "unlicenseduser" : "userid3|userid4",
? "msgid": "xxxx",
? "response_code": "xyzxyz"
}

返回結果說明:

參數說明
errcode返回碼
errmsg對返回碼的文本描述內容
invaliduser不合法的userid,不區分大小寫,統一轉為小寫
invalidparty不合法的partyid
invalidtag不合法的標簽id
unlicenseduser沒有基礎接口許可(包含已過期)的userid
msgid消息id,用于撤回應用消息
response_code僅消息類型為“按鈕交互型”,“投票選擇型”和“多項選擇型”的模板卡片消息返回,應用可使用response_code調用更新模版卡片消息接口,72小時內有效,且只能使用一次/4、

4.4、請求示例

4.4.1請求消息類型(文本

{
? ?"touser" : "UserID1|UserID2|UserID3",
? ?"toparty" : "PartyID1|PartyID2",
? ?"totag" : "TagID1 | TagID2",
? ?"msgtype" : "text",
? ?"agentid" : 1,
? ?"text" : {
? ? ? ?"content" : "你的快遞已到,請攜帶工卡前往郵件中心領取。\n出發前可查看<a href=\"https://work.weixin.qq.com\">郵件中心視頻實況</a>,聰明避開排隊。"
? ?},
? ?"safe":0,
? ?"enable_id_trans": 0,
? ?"enable_duplicate_check": 0,
? ?"duplicate_check_interval": 1800
}

參數說明:

參數是否必須說明
touser指定接收消息的成員,成員ID列表(多個接收者用‘|’分隔,最多支持1000個)。
特殊情況:指定為"@all",則向該企業應用的全部成員發送
toparty指定接收消息的部門,部門ID列表,多個接收者用‘|’分隔,最多支持100個。
當touser為"@all"時忽略本參數
totag指定接收消息的標簽,標簽ID列表,多個接收者用‘|’分隔,最多支持100個。
當touser為"@all"時忽略本參數
msgtype消息類型,此時固定為:text
agentid企業應用的id,整型。企業內部開發,可在應用的設置頁面查看;第三方服務商,可通過接口?獲取企業授權信息?獲取該參數值
content消息內容,最長不超過2048個字節,超過將截斷(支持id轉譯)
safe表示是否是保密消息,0表示可對外分享,1表示不能分享且內容顯示水印,默認為0
enable_id_trans表示是否開啟id轉譯,0表示否,1表示是,默認0。
enable_duplicate_check表示是否開啟重復消息檢查,0表示否,1表示是,默認0
duplicate_check_interval表示是否重復消息檢查的時間間隔,默認1800s,最大不超過4小時

注意:touser、toparty、totag不能同時為空,后面不再強調。

注意:成員ID是企業微信的唯一標識,查看方式如下:

注意:可以進行編輯修改,只有一次機會

修改建議:企業微信成員的企業郵箱作為賬號成員ID

樣式如下:

4.4.2請求消息類型(文本卡片

{
? ?"touser" : "UserID1|UserID2|UserID3",
? ?"toparty" : "PartyID1 | PartyID2",
? ?"totag" : "TagID1 | TagID2",
? ?"msgtype" : "textcard",
? ?"agentid" : 1,
? ?"textcard" : {
? ? ? ? ? ? "title" : "領獎通知",
? ? ? ? ? ? "description" : "<div class=\"gray\">2016年9月26日</div> <div class=\"normal\">恭喜你抽中iPhone 7一臺,領獎碼:xxxx</div><div class=\"highlight\">請于2016年10月10日前聯系行政同事領取</div>",
? ? ? ? ? ? "url" : "URL",
? ? ? ? ? ? ? ? ? ? ? ? "btntxt":"更多"
? ?},
? ?"enable_id_trans": 0,
? ?"enable_duplicate_check": 0,
? ?"duplicate_check_interval": 1800
}

參數是否必須說明
touser成員ID列表(消息接收者,多個接收者用‘|’分隔,最多支持1000個)。特殊情況:指定為@all,則向關注該企業應用的全部成員發送
toparty部門ID列表,多個接收者用‘|’分隔,最多支持100個。當touser為@all時忽略本參數
totag標簽ID列表,多個接收者用‘|’分隔,最多支持100個。當touser為@all時忽略本參數
msgtype消息類型,此時固定為:textcard
agentid企業應用的id,整型。企業內部開發,可在應用的設置頁面查看;第三方服務商,可通過接口?獲取企業授權信息?獲取該參數值
title標題,不超過128個字符,超過會自動截斷(支持id轉譯)
description描述,不超過512個字符,超過會自動截斷(支持id轉譯)
url點擊后跳轉的鏈接。最長2048字節,請確保包含了協議頭(http/https)
btntxt按鈕文字。 默認為“詳情”, 不超過4個文字,超過自動截斷。
enable_id_trans表示是否開啟id轉譯,0表示否,1表示是,默認0
enable_duplicate_check表示是否開啟重復消息檢查,0表示否,1表示是,默認0
duplicate_check_interval表示是否重復消息檢查的時間間隔,默認1800s,最大不超過4小時

樣式如下:

4.5接口工具測試(postman)

4.5.1、帶上請求參數param

4.5.2、帶上請求體

4.5.3、結果

5、使用springboot整合Spring-WebFlux開發發送消息接口

5.1、maven導入Spring-WebFlux

        <!-- webflux--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency>

5.2、配置WebClient(我們只需要用到webflux的http客戶端)

@Configuration
public class WebClientConfig {@Beanpublic WebClient webClient() {return WebClient.builder().defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).build();}
}

5.3、新增數據傳輸對象(DTO)

根據第4節的請求示例新建DTO

5.3.1 WeChatMessageDTO
@Data
public class WeChatMessageDTO {/*** 指定接收消息的成員,成員ID列表(多個接收者用‘|’分隔,最多支持1000個)。* 特殊情況:指定為"@all",則向該企業應用的全部成員發送*/private String touser;/*** 指定接收消息的部門,部門ID列表,多個接收者用‘|’分隔,最多支持100個。* 當touser為"@all"時忽略本參數*/private String toparty;/*** 指定接收消息的標簽,標簽ID列表,多個接收者用‘|’分隔,最多支持100個。* 當touser為"@all"時忽略本參數*/private String totag;/*** 消息類型,text為返回的文本*/private String msgtype;/*** 企業應用的id,整型。企業內部開發,可在應用的設置頁面查看;第三方服務商,可通過接口 獲取企業授權信息 獲取該參數值*/private Integer agentid;/*** 	消息內容,最長不超過2048個字節,超過將截斷(支持id轉譯)*/private WeChatTextDTO text;/*** 	卡片消息的展現形式非常靈活,支持使用br標簽或者空格來進行換行處理,也支持使用div標簽來使用不同的字體顏色,目前內置了3種文字顏色:灰色(gray)、高亮(highlight)、默認黑色(normal),將其作為div標簽的class屬性即可,具體用法請參考上面的示例。*/private WeChatTextDTO textcard;/*** 表示是否是保密消息,0表示可對外分享,1表示不能分享且內容顯示水印,默認為0*/private Integer safe;/*** 表示是否開啟id轉譯,0表示否,1表示是,默認0。*/private Integer enable_id_trans;/*** 表示是否開啟重復消息檢查,0表示否,1表示是,默認0*/private Integer enable_duplicate_check;/*** 表示是否重復消息檢查的時間間隔,默認1800s,最大不超過4小時*/private Integer duplicate_check_interval;//touser、toparty、totag不能同時為空,后面不再強調。
}
5.3.2?WeChatTextDTO
@Data
public class WeChatTextDTO {//text專用private String content;//消息內容,最長不超過2048個字節,超過將截斷(支持id轉譯)//textcard專用private String title;//標題,不超過128個字符,超過會自動截斷(支持id轉譯)private String description;//描述,不超過512個字符,超過會自動截斷(支持id轉譯)private String url;//點擊后跳轉的鏈接。最長2048字節,請確保包含了協議頭(http/https)private String btntxt;//按鈕文字。 默認為“詳情”, 不超過4個文字,超過自動截斷。//圖文、語音、視頻等...}

5.4 WxService

@Service
public class WxService {@Autowiredprivate WebClient webClient;@Autowiredprivate RedisCache redisCache;@Autowiredprivate RedissonClient redissonClient;private static final Logger logger = LoggerFactory.getLogger(WxService.class);//企業微信所需憑證private static final String corpid = "在第一節的1.2獲取到的企業ID";private static final String corpsecret = "在一節的1.1獲取到的企業SecretID";private String getAccessTokenByApi(){String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=" + corpid + "&corpsecret=" + corpsecret;Map<String, Object> response = webClient.get().uri(url).retrieve().bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {}).block();if (response == null || !response.containsKey("access_token")) {throw new RuntimeException("獲取 access_token 失敗:" + response);}return response.get("access_token").toString();}public String getAccessTokenByRedis() {//從redis中獲取wx_access_tokenObject cacheObject = redisCache.getCacheObject("wx_access_token");//如果存在,直接返回access_tokenif(cacheObject != null){return cacheObject.toString();}//如果不存在,獲取分布式鎖RLock lock = redissonClient.getLock("wx_access_token_lock");//默認未上鎖boolean locked = false;try {//嘗試獲取鎖,最多等待3秒,上鎖后10秒自動釋放locked = lock.tryLock(3,10, TimeUnit.SECONDS);//如果獲取到鎖,再次從redis中獲取access_token,防止在上鎖期間,其他線程已經獲取到鎖并更新了access_token。if (locked) {cacheObject = redisCache.getCacheObject("wx_access_token");if(cacheObject != null){return cacheObject.toString();}String accessToken = getAccessTokenByApi();//企業微信接口的返回值access_token有效期為7200秒,這里設置為7000秒,防止臨界值過期問題。//將access_token存入redis,有效期7000秒。redisCache.setCacheObject("wx_access_token", accessToken,7000, TimeUnit.SECONDS);return accessToken;}else{//未取到鎖throw new RuntimeException("獲取 access_token 超時,請稍后再試");}}catch (Exception e){throw new RuntimeException("Redisson 鎖被中斷", e);}finally {if(locked && lock.isHeldByCurrentThread()){lock.unlock();}}}public Map<String,Object> pushMessage(WeChatMessageDTO weChatMessageDTO){String accessToken = getAccessTokenByRedis();String url = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token="+accessToken;return webClient.post().uri(url).contentType(MediaType.APPLICATION_JSON).bodyValue(weChatMessageDTO).retrieve().bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {}).block(); // 阻塞獲取響應(適用于同步調用場景)}/*** 推送企業微信通知*/public void sendWeChatNotification(String title, String content, String receiverWxId) {try {WeChatTextDTO textDTO = new WeChatTextDTO();textDTO.setTitle(title);textDTO.setDescription(content);textDTO.setUrl("填寫你要跳轉的URL");textDTO.setBtntxt("點擊查看");WeChatMessageDTO messageDTO = new WeChatMessageDTO();messageDTO.setTouser(receiverWxId);messageDTO.setMsgtype("textcard");messageDTO.setAgentid(1000002);messageDTO.setTextcard(textDTO);Map<String, Object> result = pushMessage(messageDTO);logger.info("企業微信推送結果: {}", result);} catch (Exception e) {logger.error("企業微信推送失敗", e);}}}

5.5?WxTest

使用springboot的單元測試來測試。

@SpringBootTest
@DisplayName("單元測試案例")
public class WxTest {@Autowiredprivate WxService wxService;@DisplayName("獲取accessToken")@Testpublic void test1(){//獲取accessTokenString accessToken = wxService.getAccessTokenByRedis();System.out.println("accessToken:"+accessToken);}@DisplayName("推送信息-文本")@Testpublic void test2(){WeChatTextDTO weChatTextDTO = new WeChatTextDTO();weChatTextDTO.setContent("私聊測試");WeChatMessageDTO weChatMessageDTO = new WeChatMessageDTO();weChatMessageDTO.setTouser("ChenPengWei");//填入企業ID則是私聊weChatMessageDTO.setMsgtype("text");weChatMessageDTO.setAgentid(1000002);weChatMessageDTO.setText(weChatTextDTO);Map<String,Object> map = wxService.pushMessage(weChatMessageDTO);System.out.println(map);}@DisplayName("推送信息-文本卡片")@Testpublic void test3(){WeChatTextDTO weChatTextDTO = new WeChatTextDTO();weChatTextDTO.setTitle("CRM系統通知");weChatTextDTO.setDescription("<div class=\"gray\">2025年07月01日</div> <div class=\"normal\">天氣不錯</div><div class=\"highlight\">在一個陽光明媚的下午....</div>");weChatTextDTO.setUrl("https://www.baidu.com");weChatTextDTO.setBtntxt("點擊查看");WeChatMessageDTO weChatMessageDTO = new WeChatMessageDTO();weChatMessageDTO.setTouser("@all");//@all是公告,群廣播weChatMessageDTO.setMsgtype("textcard");weChatMessageDTO.setAgentid(1000002);weChatMessageDTO.setTextcard(weChatTextDTO);//textcardMap<String,Object> map = wxService.pushMessage(weChatMessageDTO);System.out.println(map);}}

效果圖:

小彈窗:

窗口:

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

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

相關文章

P/Invoke 在默認封送(marshalling)規則下,常見托管 ? 非托管類型的對應關系

下表整理了 P/Invoke 在默認封送&#xff08;marshalling&#xff09;規則下&#xff0c;常見托管???非托管類型的對應關系。 內容主要依據微軟官方 Marshalling Data with?Platform?Invoke 文檔&#xff0c;并補充了常見指針&#xff0f;句柄用法與字符串緩沖區&#xff…

2.isaacsim4.2 教程-初識OmniGraph

1. OmniGraph&#xff08;視覺編程&#xff09; OmniGraph 是 Omniverse 的可視化編程框架。它提供了一個圖狀結構&#xff0c;將 Omniverse 內多個系統的功能節點串聯起來&#xff1b;同時也是一個計算框架&#xff0c;允許你編寫高度自定義的節點&#xff0c;將自己的功能無…

MonoGame 游戲開發框架日記 -03

第三章&#xff1a;創建類庫 內容介紹 主要內容&#xff1a;創建Core類并編寫 創建這個類主要是為了后續開發方便&#xff0c;并介紹游戲開發中的一種非常重要編程模式 單例模式&#xff0c;以及了解MonoGame基本圖形渲染知識單例模式&#xff1a; 第一步我們得先了解什么是單例…

AES 256 CBC加密和解密

AES-256-CBC 是一種對稱加密算法&#xff0c;使用 256位密鑰 和 CBC&#xff08;Cipher Block Chaining&#xff09;模式。它的典型使用場景包括對敏感信息進行加密存儲或傳輸。下面是 AES-256-CBC 的加密與解密的 Python 示例&#xff0c;使用 pycryptodome 庫&#xff1a; &a…

Git 版本控制完全指南:從入門到精通

Git 版本控制完全指南&#xff1a;從入門到精通 作為當今最流行的分布式版本控制系統&#xff0c;Git 已經成為開發者必備的技能之一。無論你是獨立開發者還是團隊協作&#xff0c;Git 都能幫助你高效管理代碼版本。本文將帶你從零開始&#xff0c;逐步掌握 Git 的核心概念和常…

408第三季part2 - 計算機網絡 - 計算機網絡分層結構

理解 PCI會放一些控制信息&#xff0c;源地址目的地址都在里面 SDU是放的數據 整個加起來是PDU 每一層的SDU都是上一層的PDU 看一看 也是簡單看一看就行 網絡層有時候也叫IP數據報 這里斷點下載的意思就是&#xff0c;你下載東西的時候網絡斷了&#xff0c;再連回來的時候會接…

打開攝像頭,服務器和客戶端傳輸攝像頭圖像數據

1&#xff1a;Camera Server 主要功能&#xff0c;打開攝像頭&#xff0c;接收客戶端請求 接收到客戶端請求“R”字符后開始傳輸攝像頭圖像。 #include "mainwindow.h" #include "ui_mainwindow.h"#include<QDebug>MainWindow::MainWindow(QWidget…

Android實現獲取前臺應用信息

Android實現獲取前臺應用信息 1.前言&#xff1a; 之前需要獲取在后臺運行的App信息&#xff0c;比如包名、版本這些常規的&#xff0c;今天是講解獲取在前臺的App信息&#xff0c;雖然App在前臺&#xff0c;但是具體的信息可能不知道&#xff0c;今天就嘗試獲取一下&#xf…

快訊|美團即時零售日訂單已突破1.2億,餐飲訂單占比過億

據美團內網公布信息顯示&#xff0c;截至22時54分&#xff0c;美團即時零售當日訂單已經突破了1.2億單&#xff0c;其中&#xff0c;餐飲訂單已超過1億單。 值得注意的是&#xff0c;就在當晚20時45分&#xff0c;美團內網曾顯示即時零售日訂單突破了1億。這也意味著&#xff…

pycharm2018配置gitee操作

一、gitee介紹及下載安裝 gitee介紹&#xff1a; gitee別名碼云&#xff0c;是中國的一個代碼托管平臺&#xff0c;類似于GitHub&#xff0c;基于Git技術&#xff0c;提供遠程倉庫托管、協作功能和開源社區服務&#xff0c;優勢包括訪問速度快、本地化服務和政策合規git和gite…

數據結構——棧的講解(超詳細)

數據結構——棧的講解&#xff08;超詳細&#xff09;-騰訊云開發者社區-騰訊云 #include"Stack.h" void STInit(ST* ps) {ps->arr NULL;ps->capacity ps->top 0; //總空間個數和有用空間個數都初始化為0 }void STDestroy(ST* ps) {if (ps -> arr) …

MySQL允許root用戶遠程連接

注意&#xff1a;在實際生產環境中&#xff0c;允許root用戶從任意主機&#xff08;‘%’&#xff09;連接存在安全風險&#xff0c;建議使用強密碼并限制訪問IP&#xff0c;或者創建具有必要權限的單獨用戶用于遠程連接。MySQL 配置遠程連接指南 1. 登錄 MySQL 服務器 mysql -…

STM32的 syscalls.c 和 sysmem.c

syscalls.c 是 STM32CubeIDE 自動生成的標準系統調用適配文件&#xff0c;用于裸機環境下支持 newlib 標準庫&#xff08;如 printf, scanf, malloc&#xff09;的運行。這份文件提供了標準庫運行所需的最小系統調用實現。現在我來逐段解析其作用&#xff0c;并補充你可能需要修…

Java零基礎筆記01(JKD及開發工具IDEA安裝配置)

1.Java簡介 Java是一種廣泛使用的計算機編程語言&#xff0c;由美國的Sun Microsystems公司&#xff08;Stanford University Network&#xff09;在1995年推出。Java以其跨平臺、面向對象、安全性高等特點&#xff0c;廣泛應用于企業級應用開發、移動應用開發等領域。2009年&a…

Spark SQL架構及高級用法

Spark SQL 架構概述 架構核心組件 API層&#xff08;用戶接口&#xff09; 輸入方式&#xff1a;SQL查詢&#xff1b;DataFrame/Dataset API。統一性&#xff1a; 所有接口最終轉換為邏輯計劃樹&#xff08;Logical Plan&#xff09;&#xff0c;進入優化流程。 編譯器層&…

【機器學習深度學習】什么是下游任務模型?

目錄 前言 一、什么是下游任務模型&#xff1f; 二、為什么需要下游任務模型&#xff1f; 三、下游任務模型都在干嘛&#xff1f; 四、下游模型怎么訓練出來的&#xff1f; 五、圖解理解&#xff1a;上游 vs 下游 六、一個現實案例&#xff1a;BERT做情感分析 原始數據…

補充:問題:CORS ,前后端訪問跨域問題

補充&#xff1a;問題&#xff1a;CORS &#xff0c;前后端訪問跨域問題 我這邊的解決方法是&#xff1a; myAxios.defaults.withCredentials true; // 配置為true&#xff0c;表示前端向后端發送請求的時候&#xff0c;需要攜帶上憑證cookie整體的&#xff1a; import axio…

洛谷 P13014 [GESP202506 五級] 最大公因數-普及-

題目描述 對于兩個正整數 a,ba,ba,b&#xff0c;他們的最大公因數記為 gcd?(a,b)\gcd(a,b)gcd(a,b)。對于 k>3k > 3k>3 個正整數 c1,c2,…,ckc_1,c_2,\dots,c_kc1?,c2?,…,ck?&#xff0c;他們的最大公因數為&#xff1a; gcd?(c1,c2,…,ck)gcd?(gcd?(c1,c2,……

前端-CSS-day1

目錄 1、初識CSS 2、CSS引入方式 3、標簽選擇器 4、類選擇器 5、id選擇器 6、通配符選擇器 7、畫盒子 8、字體大小 9、字體粗細 10、字體傾斜 11、行高 12、行高-垂直居中 13、字體族 14、font屬性 15、文本縮進 16、文本對齊方式 17、圖片對齊方式 18、文本…

解鎖萬能文件內容提取器:Apache Tika

01 引言 在日常工作中&#xff0c;你是否曾為這些場景頭疼過&#xff1f; 堆積如山的PDF、Word、Excel文檔&#xff0c;如何快速提取關鍵信息&#xff1f;用戶上傳的文件五花八門&#xff0c;如何自動識別類型并安全處理&#xff1f;構建搜索引擎時&#xff0c;如何讓系統“讀懂…