偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Java大模型集成攻略

開(kāi)發(fā) 前端
本文將介紹在 Java 項(xiàng)目中集成各種大模型的方法,并以阿里巴巴 DashScope SDK 為例進(jìn)行重點(diǎn)講解。項(xiàng)目環(huán)境:SpringBoot 3.4.4,JDK 21,Maven 3.8.4。

本文將介紹在 Java 項(xiàng)目中集成各種大模型的方法,并以阿里巴巴 DashScope SDK 為例進(jìn)行重點(diǎn)講解。項(xiàng)目環(huán)境:SpringBoot 3.4.4,JDK 21,Maven 3.8.4。

SDK 接入

SDK(軟件開(kāi)發(fā)工具包)是官方提供的集成工具,通常包含完善的類型定義和錯(cuò)誤處理機(jī)制,讓集成更便捷。

下面以阿里巴巴 DashScope SDK 為例,演示如何在 Java 項(xiàng)目中集成。

1. 安裝 DashScope SDK

? 首先,參考官方文檔安裝 SDK:安裝 SDK 官方指南

? 選擇 SDK 版本時(shí),建議前往 Maven 中央倉(cāng)庫(kù)確認(rèn)最新版本號(hào):Maven中央倉(cāng)庫(kù)版本信息

? 在項(xiàng)目的 pom.xml 文件中添加以下依賴:

<!-- https://mvnrepository.com/artifact/com.alibaba/dashscope-sdk-java -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>dashscope-sdk-java</artifactId>
    <version>2.19.1</version>
</dependency>

2. 在阿里云百煉平臺(tái)申請(qǐng) API Key。請(qǐng)務(wù)必妥善保管,防止泄露:

https://bailian.console.aliyun.com/?tab=app#/app-center

圖片圖片

3. 在項(xiàng)目中創(chuàng)建一個(gè)名為 demo.invoke 的包,用于存放調(diào)用大模型的示例代碼。

詳細(xì)代碼示例請(qǐng)參考官方文檔:通過(guò) API 調(diào)用通義千問(wèn),如下圖所示:

圖片圖片

為了安全地管理 API 密鑰,可以創(chuàng)建一個(gè)接口來(lái)存儲(chǔ)它。注意:在生產(chǎn)環(huán)境中,強(qiáng)烈建議使用配置文件或環(huán)境變量管理 API Key,避免將其硬編碼到代碼中。

public interface TestApiKey {
    // 請(qǐng)將下方的 "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 替換為您的真實(shí)有效 API Key
    String API_KEY = "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; 
}

以下是使用 SDK 調(diào)用模型的完整 Java 示例代碼:

// 建議 DashScope SDK 版本 >= 2.12.0
// 導(dǎo)入所需的Java標(biāo)準(zhǔn)庫(kù)類
import java.util.Arrays;
import java.lang.System;

// 導(dǎo)入阿里云靈積 DashScope SDK 相關(guān)類
import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.utils.JsonUtils;

/**
 * 阿里云靈積 AI SDK 調(diào)用示例。
 * <p>
 * 本類演示了如何使用 DashScope SDK 調(diào)用阿里云靈積大模型進(jìn)行對(duì)話,
 * 包括消息構(gòu)建、參數(shù)設(shè)置、API 調(diào)用及異常處理。
 */
public class SdkAiInvoke {
    /**
     * 調(diào)用阿里云靈積大模型生成接口,傳入對(duì)話消息,并返回生成結(jié)果。
     *
     * @return GenerationResult 生成結(jié)果對(duì)象,包含模型回復(fù)等信息。
     * @throws ApiException           API 調(diào)用異常。
     * @throws NoApiKeyException      未配置 API Key 異常。
     * @throws InputRequiredException 輸入?yún)?shù)缺失異常。
     */
    public static GenerationResult callWithMessage() throws ApiException, NoApiKeyException, InputRequiredException {
        // 創(chuàng)建 Generation 實(shí)例,用于發(fā)起生成請(qǐng)求
        Generation gen = new Generation();

        // 構(gòu)建系統(tǒng)消息,設(shè)定 AI 助手的角色和行為
        // Role.SYSTEM 代表系統(tǒng)角色,用于設(shè)定 AI 的行為或身份。
        // content 字段為系統(tǒng)提示內(nèi)容,用以指導(dǎo) AI 如何回復(fù)。
        Message systemMsg = Message.builder()
                .role(Role.SYSTEM.getValue())
                .content("You are a helpful assistant.")
                .build();

        // 構(gòu)建用戶消息,模擬用戶輸入
        // Role.USER 代表用戶角色,content 字段為用戶輸入內(nèi)容。
        Message userMsg = Message.builder()
                .role(Role.USER.getValue())
                .content("你是誰(shuí)?")
                .build();

        // 構(gòu)建生成參數(shù),包括 API Key、模型名稱、消息列表、返回格式等
        // GenerationParam 用于封裝所有請(qǐng)求參數(shù)。
        GenerationParam param = GenerationParam.builder()
                // 設(shè)置 API Key。TestApiKey.API_KEY 從接口獲取。
                // 生產(chǎn)環(huán)境建議通過(guò)環(huán)境變量配置,或直接使用 .apiKey("sk-您的真實(shí)APIKey") 替換此行。
                .apiKey(TestApiKey.API_KEY) 
                // 此處以qwen-plus為例,可按需更換模型名稱。模型列表:https://help.aliyun.com/zh/model-studio/getting-started/models
                .model("qwen-plus")
                // .messages() 傳入對(duì)話消息列表,通常順序?yàn)橄到y(tǒng)消息、用戶消息。
                .messages(Arrays.asList(systemMsg, userMsg))
                // .resultFormat() 設(shè)置返回結(jié)果的格式為消息格式。
                .resultFormat(GenerationParam.ResultFormat.MESSAGE)
                .build();

        // 調(diào)用生成接口,獲取模型回復(fù)
        // gen.call(param) 方法向阿里云靈積大模型服務(wù)發(fā)起請(qǐng)求。
        // 返回 GenerationResult 對(duì)象,其中包含模型回復(fù)、Token 用量等信息。
        return gen.call(param);
    }

    /**
     * 主方法,程序入口。
     *
     * @param args 命令行參數(shù)
     */
    public static void main(String[] args) {
        try {
            // 調(diào)用 callWithMessage() 方法,獲取 AI 回復(fù)結(jié)果。
            // GenerationResult 對(duì)象中包含了模型回復(fù)內(nèi)容、Token 用量等詳細(xì)信息。
            GenerationResult result = callWithMessage();

            // 將結(jié)果對(duì)象轉(zhuǎn)為 JSON 字符串并打印
            // JsonUtils.toJson(result) 方法將 Java 對(duì)象序列化為 JSON 字符串,方便查看完整的響應(yīng)結(jié)構(gòu)。
            System.out.println(JsonUtils.toJson(result));

            // 示例輸出結(jié)構(gòu)如下(已注釋):
            // {
            //     "requestId": "...", // 請(qǐng)求唯一標(biāo)識(shí)
            //     "usage": {
            //         "input_tokens": ..., // 輸入token數(shù)
            //         "output_tokens": ..., // 輸出token數(shù)
            //         "total_tokens": ...  // 總token數(shù)
            //     },
            //     "output": {
            //         "choices": [
            //             {
            //                 "finish_reason": "stop", // 結(jié)束原因
            //                 "message": {
            //                     "role": "assistant", // 回復(fù)角色
            //                     "content": "..."      // AI回復(fù)內(nèi)容
            //                 }
            //             }
            //         ]
            //     }
            // }
        } catch (ApiException | NoApiKeyException | InputRequiredException e) {
            // 捕獲并處理調(diào)用生成服務(wù)時(shí)可能發(fā)生的異常。
            // ApiException:API 調(diào)用異常,可能由網(wǎng)絡(luò)問(wèn)題、服務(wù)端錯(cuò)誤等引起。
            // NoApiKeyException:未配置 API Key 時(shí)拋出的異常。
            // InputRequiredException:必要輸入?yún)?shù)缺失時(shí)拋出的異常。
            // 此處直接打印到標(biāo)準(zhǔn)錯(cuò)誤輸出。在實(shí)際項(xiàng)目中,建議使用日志框架記錄異常,以便追蹤和排查問(wèn)題。
            System.err.println("調(diào)用生成服務(wù)時(shí)發(fā)生錯(cuò)誤: " + e.getMessage());
        }
        // 程序執(zhí)行完畢,正常退出。
        System.exit(0);
    }
}

4. 運(yùn)行項(xiàng)目后,可以看到 AI 的回復(fù):

圖片圖片

HTTP 接入

如果 SDK 不支持您的編程語(yǔ)言,或者您需要更靈活地控制請(qǐng)求,可以直接通過(guò) HTTP 請(qǐng)求調(diào)用 AI 大模型的 API。

?? 建議:如果官方提供了 SDK,優(yōu)先使用 SDK。僅當(dāng) SDK 不支持或不適用時(shí),才考慮直接通過(guò) HTTP 調(diào)用。

HTTP 調(diào)用的詳細(xì)說(shuō)明請(qǐng)參考官方文檔:通過(guò) API 調(diào)用通義千問(wèn)

圖片圖片

您可以讓 AI 將上述 CURL 命令轉(zhuǎn)換為使用 Java Hutool 工具類的網(wǎng)絡(luò)請(qǐng)求代碼。示例 Prompt 如下:

將上述請(qǐng)求轉(zhuǎn)換為 Hutool 工具類的請(qǐng)求代碼

圖片圖片

AI 生成的代碼如下(可根據(jù)實(shí)際需求調(diào)整):

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;

import java.util.HashMap;
import java.util.Map;

/**
 * 本類演示了如何通過(guò) HTTP 請(qǐng)求調(diào)用阿里云通義千問(wèn)大模型接口進(jìn)行文本生成,
 * 并使用 Hutool 工具庫(kù)簡(jiǎn)化 HTTP 請(qǐng)求和 JSON 構(gòu)建。
 */
public class HttpAiInvoke {
    public static void main(String[] args) {
        // 定義接口請(qǐng)求的 URL,替換為實(shí)際的 API 地址
        String url = "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation";

        // 創(chuàng)建請(qǐng)求頭的 Map,用于存放 HTTP 請(qǐng)求頭信息
        Map<String, String> headers = new HashMap<>();
        // 設(shè)置 Authorization 頭,使用 Bearer 方式攜帶 API 密鑰
        headers.put("Authorization", "Bearer " + TestApiKey.API_KEY);
        // 設(shè)置 Content-Type 頭,指定請(qǐng)求體為 JSON 格式
        headers.put("Content-Type", "application/json");

        // 構(gòu)建請(qǐng)求體的 JSON 對(duì)象
        JSONObject requestBody = new JSONObject();
        // 指定使用的模型名稱
        requestBody.put("model", "qwen-plus");

        // 創(chuàng)建 input 字段的 JSON 對(duì)象
        JSONObject input = new JSONObject();
        // 創(chuàng)建消息數(shù)組,包含 system 和 user 兩種角色的消息
        JSONObject[] messages = new JSONObject[2];

        // 構(gòu)建 system 消息,指定 AI 助手的身份和行為
        JSONObject systemMessage = new JSONObject();
        systemMessage.put("role", "system");
        systemMessage.put("content", "You are a helpful assistant.");
        messages[0] = systemMessage;

        // 構(gòu)建 user 消息,指定用戶輸入的內(nèi)容
        JSONObject userMessage = new JSONObject();
        userMessage.put("role", "user");
        userMessage.put("content", "你是誰(shuí)?");
        messages[1] = userMessage;

        // 將消息數(shù)組放入 input 對(duì)象
        input.put("messages", messages);
        // 將 input 對(duì)象放入請(qǐng)求體
        requestBody.put("input", input);

        // 構(gòu)建參數(shù)對(duì)象,設(shè)置返回結(jié)果格式為 message
        JSONObject parameters = new JSONObject();
        parameters.put("result_format", "message");
        // 將參數(shù)對(duì)象放入請(qǐng)求體
        requestBody.put("parameters", parameters);

        // 發(fā)送 HTTP POST 請(qǐng)求,攜帶請(qǐng)求頭和請(qǐng)求體
        HttpResponse response = HttpRequest.post(url)
                .addHeaders(headers)
                .body(requestBody.toString())
                .execute();

        // 判斷響應(yīng)是否成功
        if (response.isOk()) {
            // 請(qǐng)求成功時(shí)輸出響應(yīng)內(nèi)容
            System.out.println("請(qǐng)求成功,響應(yīng)內(nèi)容:");
            System.out.println(response.body());
        } else {
            // 請(qǐng)求失敗時(shí)輸出狀態(tài)碼和響應(yīng)內(nèi)容
            System.out.println("請(qǐng)求失敗,狀態(tài)碼:" + response.getStatus());
            System.out.println("響應(yīng)內(nèi)容:" + response.body());
        }
    }
}

SpringAI 接入

關(guān)于 Spring AI 的基礎(chǔ)知識(shí),可以參考我之前的文章:Spring AI 搭建本地 AI。

Spring AI 默認(rèn)并不支持所有大模型(特別是國(guó)產(chǎn)模型),它主要支持與 OpenAI API 兼容的大模型集成(詳見(jiàn)官方模型對(duì)比)。因此,要調(diào)用阿里系大模型(如通義千問(wèn)),推薦使用阿里封裝的 Spring AI Alibaba 框架。該框架能便捷地集成阿里系大模型,并與標(biāo)準(zhǔn) Spring AI 兼容。

您可以參考以下官方文檔來(lái)完成大模型的調(diào)用流程:

? 靈積模型接入指南

? 通義千問(wèn)接入指南

1. 引入依賴:

<dependency>
    <groupId>com.alibaba.cloud.ai</groupId>
    <artifactId>spring-ai-alibaba-starter</artifactId>
    <version>1.0.0-M6.1</version>
</dependency>

官方提示:由于部分 spring-ai 相關(guān)依賴包尚未發(fā)布到 Maven 中央倉(cāng)庫(kù),如果遇到 spring-ai-core 等依賴解析問(wèn)題,請(qǐng)?jiān)陧?xiàng)目的 pom.xml 文件的 <repositories> 配置中添加以下倉(cāng)庫(kù):

<repositories>
  <repository>
    <id>spring-milestones</id>
    <name>Spring Milestones</name>
    <url>https://repo.spring.io/milestone</url>
    <snapshots>
      <enabled>false</enabled>
    </snapshots>
  </repository>
</repositories>

2. 編寫(xiě)配置:

spring:
  application:
    name: spring-ai-alibaba-qwq-chat-client-example
  ai:
    dashscope:
      # 請(qǐng)?zhí)鎿Q為您的 API Key 或通過(guò)環(huán)境變量設(shè)置
      api-key: ${AI_DASHSCOPE_API_KEY}
      chat:
        options:
          model: qwen-plus

3. 編寫(xiě)示例代碼 (注意注入 dashscopeChatModel):

import jakarta.annotation.Resource;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component; // 確保導(dǎo)入 Component 注解

@Component // 將此類聲明為 Spring 組件
public class SpringAiAiInvoke implements CommandLineRunner {

    /**
     * 注入 ChatModel 實(shí)例,代表一個(gè)可用的 AI 聊天模型。
     * 通過(guò) @Resource 注解自動(dòng)裝配,bean 名稱為 dashscopeChatModel。
     */
    @Resource
    private ChatModel dashscopeChatModel;

    /**
     * 應(yīng)用啟動(dòng)時(shí)自動(dòng)調(diào)用的方法。
     * 該方法向 AI 聊天模型發(fā)送問(wèn)候語(yǔ),并打印 AI 的回復(fù)。
     *
     * @param args 啟動(dòng)參數(shù)
     * @throws Exception 可能拋出的異常
     */
    @Override
    public void run(String... args) throws Exception {
        // 創(chuàng)建一個(gè)新的 Prompt 實(shí)例,內(nèi)容為“你好,我是 NEO”
         Prompt prompt = new Prompt("你好,我是 NEO");

        // 調(diào)用 dashscopeChatModel 的 call 方法,傳入 prompt,獲取 AI 回復(fù)
        AssistantMessage assistantMessage = dashscopeChatModel.call(prompt)
                .getResult() // 獲取調(diào)用結(jié)果對(duì)象
                .getOutput(); // 獲取 AI 輸出的消息對(duì)象

        // 打印 AI 助手的回復(fù)文本到控制臺(tái)
        System.out.println("Assistant Response: " + assistantMessage.getText());
    }
}

上述代碼實(shí)現(xiàn)了 CommandLineRunner 接口。啟動(dòng) Spring Boot 項(xiàng)目時(shí),會(huì)自動(dòng)注入大模型 ChatModel 依賴,并執(zhí)行一次該類的 run 方法,用于測(cè)試。

圖片圖片

?? 上述代碼通過(guò) ChatModel 對(duì)象調(diào)用大模型,適合簡(jiǎn)單對(duì)話場(chǎng)景。Spring AI 還提供了 ChatClient 調(diào)用方式,支持會(huì)話記憶等高級(jí)功能,更適合復(fù)雜場(chǎng)景,后續(xù)會(huì)有詳細(xì)介紹。

LangChain4j

與 Spring AI 類似,LangChain4j 是一個(gè)用于構(gòu)建基于大語(yǔ)言模型(LLM)應(yīng)用的 Java 框架。作為知名 AI 框架 LangChain 的 Java 版,它提供了豐富的工具和抽象,簡(jiǎn)化了與 LLM 的交互及應(yīng)用開(kāi)發(fā)。

LangChain 官方目前未直接支持阿里系大模型,但可以使用社區(qū)版整合的大模型包。

圖片圖片

支持的模型列表可在其官方文檔中查詢:LangChain4j模型集成

要接入阿里云靈積模型,可參考官方文檔:DashScope模型集成,其中包含依賴和示例代碼。

1. 引入依賴:

<!-- https://mvnrepository.com/artifact/dev.langchain4j/langchain4j-community-dashscope -->
<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-community-dashscope</artifactId>
    <version>1.0.0-beta2</version> <!-- 請(qǐng)檢查并使用最新穩(wěn)定版 -->
</dependency>

值得注意的是,LangChain4j 也提供了 Spring Boot Starter,方便在 Spring 項(xiàng)目中使用(最新版本號(hào)可在 Maven 中央倉(cāng)庫(kù)查詢)。本示例僅為演示,且已引入 Spring AI Starter,故不再引入 LangChain Starter,以避免潛在沖突。

2. 編寫(xiě)示例代碼:參考官方文檔創(chuàng)建一個(gè) ChatModel 并調(diào)用,其用法與 Spring AI 類似。

import dev.langchain4j.community.model.dashscope.QwenChatModel;

public class LangChainAiInvoke {
    /**
     * 程序主入口。
     * 運(yùn)行后會(huì)向 Qwen Max 模型發(fā)送消息,并輸出模型回復(fù)。
     * 
     * @param args 命令行參數(shù)(本示例未使用)
     */
    public static void main(String[] args) {
        // 創(chuàng)建 QwenChatModel 的構(gòu)建器,用于配置模型參數(shù)
        QwenChatModel qwenChatModel = QwenChatModel.builder()
                // 設(shè)置 API Key,用于身份認(rèn)證,必須替換為你自己的有效 Key
                .apiKey(TestApiKey.API_KEY) // 確保 TestApiKey.API_KEY 已正確配置
                // 指定要使用的模型名稱,這里選擇 "qwen-max"
                .modelName("qwen-max") // 可根據(jù)需求選擇其他模型,如 qwen-plus, qwen-turbo 等
                // 構(gòu)建出 QwenChatModel 實(shí)例,后續(xù)可以用它與大模型對(duì)話
                .build();

        // 向 Qwen Max 發(fā)送一條消息,chat 方法會(huì)返回模型的回復(fù)內(nèi)容
        String response = qwenChatModel.chat("你好,Qwen Max!請(qǐng)問(wèn)你能幫我做什么?");

        // 將模型的回答輸出到控制臺(tái),方便查看結(jié)果
        System.out.println("Qwen Max的回答: " + response);
    }
}

最后,直接運(yùn)行 main 方法即可測(cè)試。

接入方式對(duì)比

以下是四種 AI 大模型接入方式的優(yōu)缺點(diǎn)對(duì)比:

接入方式

優(yōu)點(diǎn)

缺點(diǎn)

適用場(chǎng)景

SDK 接入

? 類型安全,編譯時(shí)檢查
? 完善的錯(cuò)誤處理
? 通常有詳細(xì)文檔
? 性能較優(yōu)

? 依賴特定版本
? 可能增加項(xiàng)目體積
? 受限于特定編程語(yǔ)言

? 需要深度集成
? 針對(duì)單一模型提供商
? 對(duì)性能要求高的場(chǎng)景

HTTP 接入

? 無(wú)編程語(yǔ)言限制
? 不增加額外依賴
? 靈活性高

? 需手動(dòng)處理錯(cuò)誤
? 序列化/反序列化處理繁瑣
? 代碼可能較冗長(zhǎng)

? SDK 不支持的編程語(yǔ)言
? 簡(jiǎn)單原型驗(yàn)證
? 臨時(shí)或輕量級(jí)集成

Spring AI

? 統(tǒng)一的抽象接口
? 易于切換模型提供商
? 與 Spring 生態(tài)完美融合
? 提供高級(jí)功能(如多模態(tài)、函數(shù)調(diào)用)

? 存在額外抽象層
? 可能無(wú)法支持特定模型的全部特性
? 版本迭代快,需關(guān)注兼容性

? Spring 應(yīng)用
? 需支持多種模型或平滑切換
? 需要高級(jí) AI 功能的場(chǎng)景

LangChain4j

? 提供完整的 AI 應(yīng)用工具鏈
? 支持復(fù)雜工作流編排
? 擁有豐富的組件和工具
? 適合構(gòu)建 AI 代理(Agent)等復(fù)雜應(yīng)用

? 學(xué)習(xí)曲線較陡峭
? 部分社區(qū)模塊文檔可能不完善
? 抽象層可能引入性能開(kāi)銷

? 構(gòu)建復(fù)雜 AI 應(yīng)用
? 需要鏈?zhǔn)讲僮骱凸ぷ髁?br data-filtered="filtered">? RAG(檢索增強(qiáng)生成)應(yīng)用開(kāi)發(fā)

個(gè)人推薦優(yōu)先考慮 Spring AI。它屬于主流的 Spring 生態(tài),簡(jiǎn)單易學(xué),社區(qū)資源豐富,能滿足大多數(shù) AI 項(xiàng)目的開(kāi)發(fā)需求。掌握一個(gè) AI 開(kāi)發(fā)框架后,學(xué)習(xí)其他類似框架也會(huì)更容易。

責(zé)任編輯:武曉燕 來(lái)源: 程序員NEO
相關(guān)推薦

2023-07-24 15:20:05

機(jī)器學(xué)習(xí)集成學(xué)習(xí)

2023-11-03 07:47:12

機(jī)器資源大模型:

2024-12-02 08:10:31

2024-04-15 13:51:03

模型LLMLLMs

2023-10-28 13:29:27

2025-03-18 08:00:00

大語(yǔ)言模型KubeMQOpenAI

2023-08-30 13:09:43

AI數(shù)據(jù)

2025-04-08 03:22:00

2024-05-31 14:23:15

2025-04-30 16:48:07

2025-03-31 00:33:00

2025-03-06 07:28:31

DeepSeek大模型人工智能

2023-07-28 08:08:09

大淘寶數(shù)據(jù)模型數(shù)據(jù)治理

2023-11-27 15:06:24

2023-05-10 14:40:40

AI模型算力

2024-07-19 12:48:29

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)