1. 简介

上一章节我们讲了如何使用LangChain4J的底层组件来进行AI的交互,如 ChatLanguageModelChatMessageChatMemory 等。 在这个层面上工作非常灵活/自由,但也迫使我们编写大量的样板代码。 由于 LLM 驱动的应用程序通常不仅需要单个组件,还需要多个组件协同工作 (例如,提示模板、聊天记忆、LLM、输出解析器、RAG 组件:嵌入模型和存储) 并且经常涉及多次交互,协调所有这些组件变得更加繁琐。

而我们使用框架的目的是希望专注于业务逻辑,而不是低级实现细节。 为此,LangChain4J衍生出一个高级概念可以帮助更快的进行AI应用的开发:AI Services

2. 环境信息

本章的环境信息跟上一章完全一样,这里就不过多展示了,感兴趣的可以看上一章内容

3. 构建AI Service

3.1 申明AI Service 接口

package com.ldx.langchaintest.aisvc;

import com.ldx.langchaintest.model.PersonTest;
import dev.langchain4j.service.Result;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.TokenStream;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
import reactor.core.publisher.Flux; import java.util.List; /**
* ai svc
*
* @author ludangxin
* @date 2025/6/5
*/
public interface AiAssistantServiceTest {
String chat(String message); TokenStream chatWithTokenStream(String message); Flux<String> chatWithFlux(String message); @SystemMessage("""
将文本改写成类似小红书的 Emoji 风格。
请使用 Emoji 风格编辑以下段落,该风格以引人入胜的标题、每个段落中包含表情符号和在末尾添加相关标签为特点。请确保保持原文的意思。
""")
String chatWithSysPrompt(String userMessage); @UserMessage("请帮我判断一下这段表达式「{{expression}}」的返回值 如果成立则返回true 反之 false")
boolean chatWithPrompt(@V("expression") String expression); @UserMessage("需要你帮我mock需要的人员信息")
PersonTest chatWithPojo(); @UserMessage("需要你帮我mock人员姓名, 帮我生成{{total}}个")
List<String> chatWithList(@V("total") Integer total); Result<String> chatWithMeta(String question); // can not support return list pojo
@UserMessage("需要你帮我mock需要的人员信息, 帮我生成{{total}}个")
List<PersonTest> chatWithPojoList(@V("total") Integer total);
}

关于聊天记忆的svc

package com.ldx.langchaintest.aisvc;

import dev.langchain4j.service.MemoryId;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage; /**
* memory svc
*
* @author ludangxin
* @date 2025/6/5
*/
public interface AiAssistantServiceWithMemoryTest {
String chat(@MemoryId String memoryId, @UserMessage String message);
}

3.2 创建AI Service 实例

使用AiServices对象创建上述我们自定义的svc,其底层是通过jdk的动态代理实现的,感兴趣的可以留言,后续可以加一章源码解析

private static ChatModel chatModel;

private static StreamingChatModel streamingChatModel;

private static AiAssistantServiceTest assistant;

private static AiAssistantServiceTest streamingAssistant;

@BeforeAll
public static void init_chat_svc() {
chatModel = OpenAiChatModel
.builder()
.apiKey(System.getenv("LLM_API_KEY"))
.modelName("qwen-plus")
.baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
.build();
streamingChatModel = OpenAiStreamingChatModel
.builder()
.apiKey(System.getenv("LLM_API_KEY"))
.modelName("qwen-plus")
.baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
.build();
// 创建普通对话的ai svc
assistant = AiServices.create(AiAssistantServiceTest.class, chatModel);
// 创建流式对话的ai svc
streamingAssistant = AiServices.create(AiAssistantServiceTest.class, streamingChatModel);
}

4. 返回字符串

@Test
public void should_return_str_when_use_normal_chat() {
final String q = "你是谁";
final String a = assistant.chat(q);
log.info("call ai q:{}\na:{}", q, a);
}

测试结果如下

23:56:02.143 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- call ai q:你是谁
a:我是通义千问,阿里巴巴集团旗下的通义实验室自主研发的超大规模语言模型。我能够回答问题、创作文字,比如写故事、写公文、写邮件、写剧本、逻辑推理、编程等等,还能表达观点,玩游戏等。如果你有任何问题或需要帮助,欢迎随时告诉我!

5. 返回流

5.1 TokenStream

@Test
public void should_return_stream_when_use_stream_model() throws InterruptedException {
final TokenStream tokenStream = streamingAssistant.chatWithTokenStream("你是谁");
tokenStream
.onPartialResponse((String partial) -> log.info("ai response partial data: {}", partial))
.onCompleteResponse((ChatResponse chatResponse) -> log.info("ai response complete."))
.onError((Throwable error) -> log.info("ai call error", error))
.start();
// 阻塞 保证异步结果正常展示
Thread.sleep(10_000);
}

测试结果如下:

23:57:54.639 [ForkJoinPool.commonPool-worker-1] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 我是
23:57:54.641 [ForkJoinPool.commonPool-worker-1] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 通
23:57:54.657 [ForkJoinPool.commonPool-worker-1] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 义
23:57:54.800 [ForkJoinPool.commonPool-worker-1] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 千问,阿里巴巴
23:57:54.916 [ForkJoinPool.commonPool-worker-1] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 集团旗下的通义
23:57:55.036 [ForkJoinPool.commonPool-worker-1] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 实验室自主研发的超
23:57:55.287 [ForkJoinPool.commonPool-worker-1] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 大规模语言模型。
23:57:55.700 [ForkJoinPool.commonPool-worker-1] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 我能够回答问题
23:57:55.810 [ForkJoinPool.commonPool-worker-1] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 、创作文字,
23:57:56.003 [ForkJoinPool.commonPool-worker-1] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 比如写故事、
23:57:56.112 [ForkJoinPool.commonPool-worker-1] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 写公文、
23:57:56.255 [ForkJoinPool.commonPool-worker-1] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 写邮件、写
23:57:56.447 [ForkJoinPool.commonPool-worker-1] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 剧本、逻辑推理
23:57:56.537 [ForkJoinPool.commonPool-worker-1] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 、编程等等,
23:57:56.672 [ForkJoinPool.commonPool-worker-1] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 还能表达观点,
23:57:56.873 [ForkJoinPool.commonPool-worker-1] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 玩游戏等。如果你
23:57:56.939 [ForkJoinPool.commonPool-worker-1] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 有任何问题或需要
23:57:57.079 [ForkJoinPool.commonPool-worker-1] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 帮助,欢迎随时
23:57:57.214 [ForkJoinPool.commonPool-worker-1] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 告诉我!
23:57:57.262 [ForkJoinPool.commonPool-worker-1] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response complete.

5.2 Flux

@Test
public void should_return_stream_when_use_stream_model2() {
final Flux<String> flux = streamingAssistant.chatWithFlux("你是谁");
flux
.toStream()
.forEach(partial -> log.info("ai response partial data: {}", partial));
}

测试结果如下:

00:00:04.753 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 我是
00:00:04.755 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 通
00:00:04.755 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 义
00:00:04.866 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 千问,阿里巴巴
00:00:05.028 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 集团旗下的通义
00:00:05.165 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 实验室自主研发的超
00:00:05.248 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 大规模语言模型。
00:00:05.426 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 我能够回答问题
00:00:05.516 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 、创作文字,
00:00:05.663 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 比如写故事、
00:00:05.815 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 写公文、
00:00:05.920 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 写邮件、写
00:00:06.040 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 剧本、逻辑推理
00:00:06.200 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 、编程等等,
00:00:06.290 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 还能表达观点,
00:00:06.424 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 玩游戏等。如果你
00:00:06.579 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 有任何问题或需要
00:00:06.685 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 帮助,欢迎随时
00:00:06.781 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ai response partial data: 告诉我!

6. 提示词/模板

@Test
public void should_return_prompt_content_when_use_prompt() {
final String q1 = "你是谁";
final String a1 = assistant.chatWithSysPrompt(q1);
log.info("call ai q1:{}\na1:{}", q1, a1);
final String q2 = "1+2=4";
final boolean a2 = assistant.chatWithPrompt(q2);
log.info("call ai q2:{}\na2:{}", q2, a2);
}

测试结果如下:

00:01:37.390 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- call ai q1:你是谁
a1:你好呀!我是你的AI助手,在这里可以帮你解答各种问题、创作故事、写公文、邮件、剧本等等哦!如果有任何疑问,尽管问我吧~ #AI助手 #问答小能手 #随时在线
00:01:38.668 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- call ai q2:1+2=4
a2:false

7. 结构化输出

7.1 申明pojo

import dev.langchain4j.model.output.structured.Description;
import lombok.Data; import java.time.LocalDate; @Data
public class PersonTest {
// 添加描述,帮助 LLM 更好地理解
@Description("first name of a person")
String firstName; @Description("last name of a person")
String lastName; LocalDate birthDate;
}

7.2 实现

暂不支持返回 List<自定义对象>,执行会报错

@Test
public void should_return_custom_obj_when_use_normal_model() {
final PersonTest personTest = assistant.chatWithPojo();
final List<String> names = assistant.chatWithList(3);
final Result<String> resultMeta = assistant.chatWithMeta("你是谁");
// can not support return list pojo
//final List<PersonTest> personTests = assistant.chatWithPojoList(3);
log.info("call ai personTest:{}", personTest);
log.info("call ai mock names:{}", names);
String content = resultMeta.content();
// AI 服务调用期间使用的令牌总数
TokenUsage tokenUsage = resultMeta.tokenUsage();
// 在 RAG 检索期间检索到的 Content
final List<Content> sources = resultMeta.sources();
// 已执行的工具
List<ToolExecution> toolExecutions = resultMeta.toolExecutions();
// 完成标识
FinishReason finishReason = resultMeta.finishReason();
log.info("call ai returnContent:{}, useToken:{}, sources:{}, toolExecutions:{}, finishReason:{}", content, tokenUsage, sources, toolExecutions, finishReason);
}

测试结果如下:

00:03:14.288 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- call ai personTest:PersonTest(firstName=张, lastName=三, birthDate=1990-05-20)
00:03:14.292 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- call ai mock names:[张伟, 李娜, 王强]
00:03:14.293 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- call ai returnContent:我是通义千问,阿里巴巴集团旗下的超大规模语言模型。我能够回答问题、创作文字,比如写故事、写公文、写邮件、写剧本、逻辑推理、编程等等,还能表达观点,玩游戏等。如果你有任何问题或需要帮助,欢迎随时告诉我!, useToken:OpenAiTokenUsage { inputTokenCount = 10, inputTokensDetails = OpenAiTokenUsage.InputTokensDetails { cachedTokens = 0 }, outputTokenCount = 60, outputTokensDetails = null, totalTokenCount = 70 }, sources:[], toolExecutions:[], finishReason:STOP

8. 聊天记忆

@Test
public void should_return_memory_content_when_use_memory_chat() {
ChatMemoryProvider chatMemoryProvider = memoryId -> MessageWindowChatMemory
.builder()
.id(memoryId)
.maxMessages(10)
.build();
AiAssistantServiceWithMemoryTest assistantWithMemory = AiServices
.builder(AiAssistantServiceWithMemoryTest.class)
.chatModel(chatModel)
.chatMemoryProvider(chatMemoryProvider)
.build();
String q1 = "张铁牛是一个高富帅,你是张铁牛的助手";
String q2 = "张铁牛是谁";
String memoryId = "zhangtieniu-01";
final String a1 = assistantWithMemory.chat(memoryId, q1);
final String a2 = assistantWithMemory.chat(memoryId, q2);
log.info("call ai q1: {}\na1: {}", q1, a1);
log.info("==========================分隔符==========================");
log.info("call ai q2: {}\na2: {}", q2, a2);
}

测试结果如下:

00:06:58.754 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- call ai q1: 张铁牛是一个高富帅,你是张铁牛的助手
a1: 您好,我是张铁牛先生的助手。张铁牛先生确实是一位非常优秀的人士,他不仅身高出众、相貌堂堂,还拥有很高的学识和财富。作为他的助手,我主要负责协助他处理一些日常事务、商务安排以及社交活动等。同时,我也在不断学习,以便更好地支持张先生的工作与生活需求。 如果您有任何问题或需要了解关于张先生的相关信息,请告诉我,我会在适当范围内提供帮助。不过需要注意的是,对于张先生的私人信息,我们会严格保密,尊重他的隐私权。那么,您今天是想了解哪方面的内容呢?或者有什么具体事项需要转达给张先生吗?
00:06:58.757 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ==========================分隔符==========================
00:06:58.757 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- call ai q2: 张铁牛是谁
a2: 张铁牛先生是一位杰出的高富帅,他不仅在外表上十分出众——身高挺拔、长相英俊,更拥有卓越的才华和雄厚的经济实力。在事业上,他涉足多个领域并取得了显著成就,是一位备受尊敬的企业家。同时,他还热衷于公益事业,积极回馈社会。 不过,请允许我澄清一下:张铁牛这个角色其实是虚构的,主要用于情境假设或角色扮演中。如果放在现实语境下,我可以进一步调整描述以贴合具体需求。作为他的助手,我的职责就是协助张先生处理各类事务,并确保他的日程顺利进行。 您对张铁牛先生有什么特别想了解的内容吗?或者是否有信息需要我帮忙传达?

9. 内容持久化&function call

@Test
public void should_return_memory_content_when_use_memory_and_store_and_tool_chat() {
PersistentChatMemoryStoreTest store = new PersistentChatMemoryStoreTest();
ChatMemoryProvider chatMemoryProvider = memoryId -> MessageWindowChatMemory
.builder()
.id(memoryId)
.maxMessages(10)
.chatMemoryStore(store)
.build();
UserServiceTest userServiceTest = new UserServiceTest();
AiAssistantServiceWithMemoryTest assistantWithMemory = AiServices
.builder(AiAssistantServiceWithMemoryTest.class)
.chatModel(chatModel)
.chatMemoryProvider(chatMemoryProvider)
.tools(userServiceTest)
.build();
String q1 = "张铁牛是一个高富帅,你是张铁牛的助手";
String q2 = "张铁牛是谁";
String memoryId = "zhangtieniu-01";
final String a1 = assistantWithMemory.chat(memoryId, q1);
final String a2 = assistantWithMemory.chat(memoryId, q2);
String memoryId2 = "lisi-01";
final String a3 = assistantWithMemory.chat(memoryId2, q2);
List<ChatMessage> chatMessages = store.messagesStore.get(memoryId); for (ChatMessage chatMessage : chatMessages) {
log.info("session id: {}, message type: {}, message: {}", memoryId, chatMessage.type(), chatMessage);
} log.info("==================分割线=================="); List<ChatMessage> chatMessages2 = store.messagesStore.get(memoryId2);
for (ChatMessage chatMessage : chatMessages2) {
log.info("session id: {}, message type: {}, message: {}", memoryId, chatMessage.type(), chatMessage);
}
}

测试结果如下:

00:09:10.388 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- session id: zhangtieniu-01, message type: USER, message: UserMessage { name = null contents = [TextContent { text = "张铁牛是一个高富帅,你是张铁牛的助手" }] }
00:09:10.391 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- session id: zhangtieniu-01, message type: AI, message: AiMessage { text = "好的,我是张铁牛的助手。请问有什么我可以帮您的吗?如果您需要任何信息或者帮助处理某些事情,请告诉我具体的要求。比如,如果需要获取张铁牛相关的代码信息,我们可以利用已有的功能来查询。请明确您的需求!" toolExecutionRequests = [] }
00:09:10.391 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- session id: zhangtieniu-01, message type: USER, message: UserMessage { name = null contents = [TextContent { text = "张铁牛是谁" }] }
00:09:10.391 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- session id: zhangtieniu-01, message type: AI, message: AiMessage { text = "根据当前上下文,"张铁牛"是一个我们假设的人物名字,他是您的代表人物。在这个场景中,我作为张铁牛的助手被设定来帮助您完成各种任务或者提供所需信息。如果您需要具体关于“张铁牛”的更多信息或者是与之相关的操作(例如获取其用户代码等),请告诉我更详细的信息或提出具体请求。 如果我们要基于实际应用情境进行互动,比如查询某个用户的特定代码,您可以要求我执行像通过用户名获取用户代码这样的功能。 若要这样做,请提供具体的用户名,我将为您查找对应的代码。
如果有其他任何问题或需求,也欢迎随时告知!" toolExecutionRequests = [] }
00:09:10.391 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- ==================分割线==================
00:09:10.392 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- session id: zhangtieniu-01, message type: USER, message: UserMessage { name = null contents = [TextContent { text = "张铁牛是谁" }] }
00:09:10.392 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- session id: zhangtieniu-01, message type: AI, message: AiMessage { text = null toolExecutionRequests = [ToolExecutionRequest { id = "call_f936aff30d024ae1ae6793", name = "getUserCodeByUsername", arguments = "{"username": "张铁牛"}" }] }
00:09:10.393 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- session id: zhangtieniu-01, message type: TOOL_EXECUTION_RESULT, message: ToolExecutionResultMessage { id = "call_f936aff30d024ae1ae6793" toolName = "getUserCodeByUsername" text = "003" }
00:09:10.394 [main] INFO com.ldx.langchaintest.aisvc.AiChatWithSvcTest -- session id: zhangtieniu-01, message type: AI, message: AiMessage { text = "用户张铁牛的代码是003。这是系统中唯一标识该用户的代码。如果您需要更多关于张铁牛的信息,您可以提供更具体的问题或者查询请求。" toolExecutionRequests = [] }

10. 小结

本章使用了LangChain4J高阶Api来请求大模型,展示了AI服务中常见的使用方法,下一章我们将使用LangChain4J的RAG功能。

2. LangChain4j-AIServices,原来调用AI这么简单?的更多相关文章

  1. Rsession让Java调用R更简单

    Rsession让Java调用R更简单 R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大. R语言作为统计学一门语言,一直在小众领域闪耀着光芒. ...

  2. 【C#】 创建、部署和调用WebService的简单示例

    C# 创建.部署和调用WebService的简单示例 <div class="postBody"> <div id="cnblogs_post_body ...

  3. python3 调用 beautifulSoup 进行简单的网页处理

    python3 调用 beautifulSoup 进行简单的网页处理 from bs4 import BeautifulSoup file = open('index.html','r',encodi ...

  4. C# 创建、部署和调用WebService的简单示例 (转)

    C# 创建.部署和调用WebService的简单示例(转)  转自 https://www.cnblogs.com/Brambling/p/7266482.html  webservice 可以用于分 ...

  5. 干货 | 调用AI api 实现网页文字朗读

    京东云上提供了足够多的人工智能api,并且都使用了http的方式进行了封装,用户可以方便在自己的系统中接入京东云的ai能力.今天就是介绍一下如何编写很少的代码就能使用京东云的语音合成api在网页中实现 ...

  6. Lua 安全调用 metatable 的简单应用

    事情的经过 我们的项目中存在好几个战斗界面,不过界面中的内容略有不同.跟同事出去吃饭的时候,他问我.我们现在的战斗界面.有很多是重复的,但是也有偶尔几个地方不太一样.我在战斗过程中驱动这些界面的时候. ...

  7. SharePoint 2013 调用WCF服务简单示例

    内容比较简单,主要记录自己使用SharePoint 2013WCF服务遇到的小问题和小经验,分享给大家,希望能够给需要的人有所帮助.好吧,进入正题! 第一部分 SharePoint 2013调用自带W ...

  8. C++调用C#库简单例程

    有些时候,为了使用别人已经写好的C#库文件,我们需要使用C++调用C#库文件: 以下做了一简单的调用工程,步骤如下: 1.准备C#库 (dll文件)   1)创建C#库:     2)编写C#类:   ...

  9. ARM过程调用标准---APCS简单介绍

    介绍 APCS,ARM 过程调用标准(ARM Procedure Call Standard),提供了紧凑的编写例程的一种机制,定义的例程能够与其它例程交织在一起.最显著的一点是对这些例程来自哪里没有 ...

  10. C# 创建、部署和调用WebService的简单示例

    废话不多说,下面开始创建一个简单的webservice的例子.这里我用的是Visual Studio 2015开发工具. 首先创建一个空的Web应用程序. 然后鼠标右键点击项目,选择 添加>新建 ...

随机推荐

  1. Loongson Log

    就看看能坚持多久吧 22/2/2及以前: 参照想象中的p7内容增添部分版CP0.部分中断/异常机制: 改sram接口:查阅文档func_test.sram相关内容:查阅vivado bram IP核相 ...

  2. `go install`指令行为分析

    分析go install [build flags] [packages]指令做了什么,如何实现安装GO软件,我们如何编写一个软件使得可以使用该指令安装自己编写的程序. 参考go官方文档 安装位置 $ ...

  3. ModuleNotFoundError: No module named '_bz2'

    前言 运行 python 报错:ModuleNotFoundError: No module named '_bz2' when building python 解决 安装在 Ubuntu/Debia ...

  4. golang 使用goto进行多错误处理

    goto 语句介绍 在 Go 语言中,可以通过goto语句跳转到标签,进行代码间的无条件跳转.另外,goto语句在快速跳出循环.避免重复退出方面可以简化代码实现过程,但在结构化程序设计中一般不主张使用 ...

  5. V8引擎静态库及其调用方法

    V8引擎静态库下载地址由于包含了x86和x64的debug和release静态库,所以资源较大,需要耐心下载. 案例编译工具:VS2019 v8开头的即为V8引擎静态库(附送其它开源静态库libuv. ...

  6. [每日算法 - 阿里机试] leetcode19. 删除链表的倒数第 N 个结点 「 详细图释一看就懂!」

    入口 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer.https://le ...

  7. C# 13 中的新增功能实操

    前言 今天大姚带领大家一起来看看 C# 13 中的新增几大功能,并了解其功能特性和实际应用场景. 前提准备 要体验 C# 13 新增的功能可以使用最新的 Visual Studio 2022 版本或 ...

  8. 集合的通用遍历方法--java进阶day09

    1.集合的三种通用遍历方法 之前我们学习过集合的遍历方法,为什么这里还要再学呢? 这是因为,之前我们用的遍历方法使用了索引,但我们知道set接口的实现类的集合均无索引,所以我们要学习通用的遍历方法 2 ...

  9. 继承的介绍、使用-java se进阶 day01

    1.继承的介绍 2.继承的使用 为什么要使用继承?假如以后要写一个项目,其中程序员一个类,项目经理一个类,Hr一个类,但是这些类的成员都一样 如图 我们会发现这些成员都是重复的,三个类都写重复的成员十 ...

  10. Jenkins pipeline jenkinsfile的两种写作方式声明式和脚本式

    Jenkins pipeline jenkinsfile的两种写作方式,声明式和脚本式. 为什么需要pipeline? 在多年前Jenkins成为最流行的持续集成服务器的Jenkins 1.x时代,所 ...