Vue3+NodeJS 接入文心一言, 发布一个 VSCode 大模型问答插件

目录

一:首先明确插件开发方式

二:新建一个Vscode 插件项目

1. 官网教程地址

2. 一步一步来创建

3. 分析目录结构以及运行插件

三:新建一个Vue3 项目,在侧边栏中展示,实现vscode插件 <=> vue项目 双向消息传递

1. 新建vue3+vite+ts项目

2. 将web页面展示在vscode侧边栏

(1) 插件项目修改,把视图注册到侧边栏,完成消息传递

(2) web项目修改,增加事件监听

四:接入大模型对话能力,实现ChatUI

1. 大模型接入准备

2. nodejs调用api

3. 前端接口调试

五:注册开发者账号并发布插件

1. 推荐教程

2. 增加插件商店图标

3. 前端资源的缓存策略会影响插件web页面的实时更新

六:实战能力探讨(会持续更新,欢迎探讨)

1. 行内提示功能的设计与实现(InlineCompletionItemProvider[9])

2. SSH 远程打开文件能力(使用 remote-ssh 插件提供的命令)

3. Json 文件可视化编辑(JsonToHtml)


        随着大模型能力越来越卷,在垂直领域的落地也在加快,对于大模型代码生成能力而言,最简洁高效的方式就是集成为常用IDE的插件,在vscode的插件战场中,比较知名的就有 GitHub Copilot, 智谱清言的codegeex, 讯飞星火的iFlyCode。

那么我们就以开发一个简易的大模型对话插件,来探究一下vscode插件开发到发布的流程,研究一下文心一言大模型api的接入

跟着操作大约30-60分钟,你需要

  • 安装vscode,npm/yarn等,node版本 >12.0

  • 最好有时间提前看一看 vscode 官网api开发文档[1]

万字长文 Action!

一:首先明确插件开发方式

  1. 如果你的插件只提供原生vscode能力,没有复杂的UI需求,只需要在vscode插件项目上开发即可,类似插件比如Volar Git History Eslint

  2. 如果提供复杂UI交互,定制化界面,就需要在vscode插件内嵌iframe页面(用iframe展示线上web地址与使用vscode提供的一套UI组件皆可,详见第三节),我这里选择访问线上地址,因此需要开发一个vscode插件项目与一个vue3项目(其他框架亦可),类似的复杂插件比如 CodeGeeX iFlyCode,会将web页面展示在侧边栏中。

图片

image.png

本文主要讲解 如何在vscode插件中通过iframe展示web页面,获得更好的拓展性与可维护性

二:新建一个Vscode 插件项目

1. 官网教程地址

开始你的第一个插件项目[2]

2. 一步一步来创建
  • 找到一个比较舒服的文件夹,打开cmd,通过以下命令安装 vscode项目脚手架,取的是 registry.npmjs.org[3] 镜像源,因此可能会有科学问题

  npm install -g yo generator-code
  • 安装完成后,直接用命令创建新的插件项目

 yo code
  • 进入配置页面,默认就选择 NewExtension(TypeScript),后面的按照图中来就可

    图片

  • 然后会自动创建好项目,并执行npm i,然后用 vscode 打开项目

3. 分析目录结构以及运行插件

图片

目录结构就很清晰了,我们主要涉及修改 extension.ts 以及 package.json文件
上图中,extension.ts 中 activate() 方法就是插件的入口函数,每次插件启动都会执行此函数,当前代码是注册了一个hello world命令,当你在vscode中通过 ctrl+shift+p 调出输入框并输入hello world,就会执行此注册命令的回调,弹出一个message框,下面我们来试一下

在当前项目中,直接按F5,会启动一个扩展开发宿主,你的插件就运行在这个vscode窗口上啦 下面我们调出命令输入框ctrl+shift+p ,输入 hello world, 会提示命令,选中执行,右下角会发现弹了一个message!!!
什么?你的没弹出?那你岂不是和我当时一样倒霉,但你不需要花时间去挖这个奇怪的~bug !
首先看一下你的vscode版本

图片

image.png

当前vscode版本不能低于 package.json 中的最低版本要求!

图片

这样写表示最低支持到1.83.0版本!改一下重新reload一下宿主插件,再试试命令就可以弹出啦!到此我们的插件侧项目就搭建好了,下面我们简单建一个vue项目,嵌入到侧边栏中

三:新建一个Vue3 项目,在侧边栏中展示,实现vscode插件 <=> vue项目 双向消息传递

文章开头我们提到,插件内展示丰富的UI,既可以用iframe展示线上web网页,也可以在插件内部用vsode ui实现。下面我主要演示用iframe的方式,另一种嵌入方式推荐大家去看一下 CodeGeeX 插件[4]源码如何做的,引入了一套vscode风格的UI组件@vscode/webview-ui-toolkit,源码里面的webviewUI文件夹与translationWebviewProvider.ts文件都是相关代码。

1. 新建vue3+vite+ts项目

找一个舒服的文件夹,打开cmd

    npm init vite

执行后按需选择自己的框架与开发环境,然后run dev一下子,拿到地址, 比如 http://localhost:5173/

2. 将web页面展示在vscode侧边栏
(1) 插件项目修改,把视图注册到侧边栏,完成消息传递

第一步当然是先建一个iframe把我们的web项目的地址填进去呗,开始。

vscode 提供了两种创建iframe的方法,WebviewViewProvider 和 createWebviewPanel,选其一即可,这里我们介绍一下WebviewViewProvider如何使用

首先在extension.ts 同级目录下新建 chatWebview.ts

  • WebviewViewProvider 是一个接口,因此建一个自己的类实现它的方法即可

    图片

    下面我们创建一个实现WebviewViewProvider接口的类ChatWebview

    chatWebview.ts 文件: (可直接运行)
    具体代码作用看注释

import { window, Position, WebviewView, WebviewViewProvider } from "vscode";
export class ChatWebview implements WebviewViewProvider {// 写一个public变量,方便对象引用创建后的webview实例,但是可能存在还未完全解析完成时,访问值为null// 看了vscode api发现,resolveWebView 返回一个 Thenable,可以在解析完成后拿到webview实例// 但是这个函数是在webview容器第一次显示时自动执行,不需要手动调用,不知道怎么拿到Thenablepublic webview: WebviewView | null = null;resolveWebviewView(webviewView: WebviewView): void | Thenable<void> {this.webview = webviewView;webviewView.webview.options = {enableScripts: true,};// 监听web端传来的消息webviewView.webview.onDidReceiveMessage((message) => {switch (message.command) {case "WebSendMesToVscode":// 实现一个简单的功能,将web端传递过来的消息插入到当前活动编辑器中let editor = window.activeTextEditor;editor?.edit((edit) => {let position = editor?.selection? editor?.selection.start: new Position(0, 0);edit.insert(position, message.data);});return;}}, undefined);// webview 展示的内容本身就是嵌套在一个iframe中,因此在此html中再嵌套一个iframe时,需要传递两次postMessagewebviewView.webview.html = `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><style>html,body {margin: 0;padding: 0;width: 100%;height: 100%;background-color:#000000;overflow:hidden;}.webView_iframe {width: 100%;height: 100%;border: none;}.outer{width: 100%;height: 100%;overflow: hidden;}</style></head><body><script>console.log('Hello from the webview!');// 向vscode 传递消息的固定写法, vscode 为我们封装好了postMessageconst vscode = acquireVsCodeApi();// 接收来自web页面的消息window.addEventListener('message', event => {const message = event.data;switch (message.command) {// 插件传递消息给web端case 'vscodeSendMesToWeb':let iframe = document.getElementById('WebviewIframe')WebviewIframe.contentWindow.postMessage(message, "*")console.log("fromWebViewIframe: "+message.data)break;// web端发送消息给插件case 'WebSendMesToVscode':vscode.postMessage(message);break;}});</script><div class="outer"><iframe id='WebviewIframe' class="webView_iframe" sandbox="allow-scripts allow-same-origin allow-forms allow-pointer-lock allow-downloads" allow="cross-origin-isolated; clipboard-read; clipboard-write;" src="http://localhost:5173/"></iframe></div></body></html>`;}
}

提供webview视图的类创建好了,然后我们需要在入口函数中实例化一个webview,然后把这个视图注册到vscode侧边栏中

打开extension.ts文件,修改如下 (代码可直接运行)

// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from "vscode";
import { ChatWebview } from "./chatWebview";
// This method is called when your extension is activated
// vscode 插件入口函数,当插件第一次加载时会执行activate
export function activate(context: vscode.ExtensionContext) {console.log('Congratulations, your extension "Chat" is now active!');// 实现侧边栏的初始化// 实例化一个chatWebviewconst chatWebview = new ChatWebview();// 注册webview 到id为 Chat-sidebar 的views中,这个id为 Chat-sidebar 的视图我们稍后会在// package.json 中声明,先理解为我们要把iframe渲染在那个地方(侧边栏还是标签页)需要在// packagea.json 中控制context.subscriptions.push(vscode.window.registerWebviewViewProvider("Chat-sidebar", chatWebview, {webviewOptions: {// 这是一个比较有用的配置项,可以确保你的插件在不可见时不会被销毁,建议开启,否侧每次打开都会重新加载一次插件retainContextWhenHidden: true,},}));// 这里实现了一个简单的功能,在vscode打开的文件中,选中代码时会实时展示在web页面上// 监听用户选中文本事件vscode.window.onDidChangeTextEditorSelection((event) => {const editor = event.textEditor;let document = editor.document;let selection = editor.selection;// 获取当前窗口的文本let text = document.getText(selection);// 上文提到chatWebview可能为null 因此需要可选链写法,所以这里存在不稳定性,不过测试没问题~chatWebview?.webview?.webview.postMessage({// 第一次postMessage,下一次在chatWebview文件的iframe中 command: "vscodeSendMesToWeb",data: text,});});
}// This method is called when your extension is deactivated
export function deactivate() {}

至此,我们实例化了ChatWebview,并将其与视图Chat-siderbar绑定

下面我们需要在package.json中将视图注册到侧边栏中,并指定名字,图标等 打开package.json 文件,修改如下 将原本的 contributes 字段替换一下

确保activitybar 中的id,在views中有对应的视图,我们这里id是Chat-sidebar-view,在views就要有对应名字的视图, 并且该视图 Chat-sidebar-view 的id为我们 ChatWebview 绑定的视图id

"contributes": {"commands": [],"viewsContainers": {"activitybar": [{"id": "Chat-sidebar-view","title": "Chat","icon": "images/vite.svg"}]},"views": {"Chat-sidebar-view": [{"type": "webview","id": "Chat-sidebar","name": " Chat","icon": "images/vite.svg","contextualTitle": "Chat"}]}},

至此!我们的视图和双向通讯在插件侧已经完成了,我们试一下!直接F5运行,打开拓展开发宿主

图片

image.png

点击左侧栏图标,会看见我们deweb页面加载出来啦!
再试一下选中文本的事件和postMessage通讯,点击上方help,选择倒数第三个Toggle developer tools或者按ctrl+shift+i 可以打开谷歌开发者工具,调试vscode

随便打开一个项目文件,在窗口中选中文本,会发现控制台一直在输出 fromWebViewIframe: ...... ,我们第一步通讯通了,下面在vue项目中加一下消息接收和发送。

(2) web项目修改,增加事件监听

打开index.html,增加message的监听,收到消息时插入到container中

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><link rel="icon" type="image/svg+xml" href="/vite.svg" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Vite + Vue + TS</title></head><body><div id="app"></div><script type="module" src="/src/main.ts"></script><script type="module">window.addEventListener("message", (event) => {const message = event.data;switch (message.command) {case "vscodeSendMesToWeb":const div = document.getElementById("container");div.innerHTML = message.data;break;}});</script></body>
</html>

我们试一下,在拓展开发宿主中选中文本,会实时展示在页面上!

图片

image.png

下面我们发送消息试一下 简单修改一下 HellowWord.vue 组件,增加一个sendMessage 方法

<script setup lang="ts">
import { ref } from "vue";defineProps<{ msg: string }>();const count = ref(0);const sendMessage = () => {window.parent.postMessage({command: "WebSendMesToVscode",data: "this message is from vue3",},"*");
};
</script><template><h1>{{ msg }}</h1><div class="card"><button type="button" @click="sendMessage">click</button><p>Edit<code>components/HelloWorld.vue</code> to test HMR</p></div><p>Check out<a href="https://vuejs.org/guide/quick-start.html#local" target="_blank">create-vue</a>, the official Vue + Vite starter</p><p>Install<a href="https://github.com/vuejs/language-tools" target="_blank">Volar</a>in your IDE for a better DX</p><p class="read-the-docs">Click on the Vite and Vue logos to learn more</p>
</template><style scoped>
.read-the-docs {color: #888;
}
</style>

我们点击一下按钮,会发现在当前文件光标处插入了一条信息。this message is from vue3!

到此我们的小插件展示出来了,也实现了数据互通。下面我们实现一个简单对话UI,并接入百度文心一言大模型,做一个自己的插件小助手,如果他能记住我们之前问过的代码,并帮我们举一反三,并提醒我们查漏补缺就好了。

四:接入大模型对话能力,实现ChatUI

1. 大模型接入准备

我分别注册了智谱清言(chatGLM)与文心一言(ERNIE-Bot),发现两者都有基础的免费额度,前者相对于后者代码能力貌似更强一些,我们这里做一个简单类似于代码错题本的对话助手,就接入文心一言吧

首先我们要去官网[5],注册一下开发者账号,并且实名认证 整个过程很简单,然后我们看一下api 文档[6]

图片

下面我把主要步骤说一下 首先我们要创建一个自己的应用,获取到Secret KeyAPI Key

进入下面页面,点击创建应用,输入应用名称和应用描述直接确定即可,然后会有一个应用生成,里面就有我们的Secret KeyAPI Key

图片

我们要拿这两个key,去获取 access_token 和 refresh_token, 用于JWT鉴权,有两种方式,其一我们可以在网页中访问一下拿到一次性30天的access_token用于临时测试,其二最好在项目http请求前自动用refresh_token去获取access_token

下面我们访问一下这个地址,当然你要把双key换成你自己的应用的~!https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=你的key&client_secret=你的key

直接用浏览器访问一下呢,然后就在请求里拿到了access_token (不能有小可爱找不到吧~) 拿到token了我们来这里测试一下 测试地址[7]

图片

填入标出的这两项,第二项示例如下

[{"role": "user","content": "介绍一下自己"},
]

可以看到接口调用结果

图片

image.png

2. nodejs调用api

首先找一个舒服的文件夹,新建一个node项目,我们这里选用express框架,可以参考我这里的命令行

图片

image.png

npm init 后会生成一个package.json,然后我们安装一下常用包
npm install express sequelize mysql2 axios body-parser cors --save 之后就可以在vscode中打开我们的项目了,我们先新建一个server.js,作为我们的入口文件,再建一个chat.js 作为我们的大模型调用文件

两个文件代码如下,具体解析见注释,可以直接复制过去,然后在控制台执行node server.js 直接启动服务~

//server.js
const Conversation = require("./chat.js");
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");const app = express();
// 暂时允许所有跨域请求
let corsOptions = {origin: "*",
};
app.use(cors(corsOptions));
// content-type:application/json
app.use(bodyParser.json());
// content-type:application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));
// 对话类
const conversation = new Conversation();
// 定义/chat路由处理POST请求
app.post("/chat", async (req, res) => {const { messages = "" } = req.body || {};if (typeof messages !== "string") {return res.status(400).send({ error: "Invalid messages type" });}try {// 调用ask方法获取大模型结果const response = await conversation.ask(messages);return res.status(200).send({ message: response });} catch (error) {return res.status(500).send({ error: error.messages });}
});
// 设置监听端口
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {console.log(`服务器运行端口: ${PORT}.`);
});
chat.js
// 访问模型服务
const axios = require("axios");
// 这里就是你的accessToken,我改了两个数,所以你得替换成自己的喽~
const accessToken ="24.88635a1444105db00bb6684c0598a9a3.2542000.1741590285.281335-42231960";
const ERNIEB4 ="https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions_pro";
const ERNIEB ="https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions";class Conversation {constructor() {// 上下文数据存在这里,文心的调用是需要把所有的历史对话数据全部传过去,所以上下文窗口大小得注意this.messages = [];}async ask(prompt) {// 问句push进去this.messages.push({ role: "user", content: prompt });console.log("message" + this.messages[0]);try {const res = await axios.post(ERNIEB,{ messages: this.messages },{ params: { access_token: accessToken } });const { data } = res;console.log(data);// 答案也放进去this.messages.push({ role: "assistant", content: data.result });return data.result;} catch (error) {console.log("调用模型失败" + error);}}
}
// 导出函数
module.exports = Conversation;

所以我们的服务起了吗?网页试一下8080呗,通了就可以

图片

image.png

下面我们在前端代码中加一下接口调用,就大功告成啦!

想必看到这里你也累了,我们去调戏一下 Sydney

图片

image.png

看来一时半会我们还是不可替代的 o_O

3. 前端接口调试

言归正传,我们来增加接口调用吧,顺便画一个看得过去的UI界面

先装一下 npm install @ant-design/icons-vue
然后把App.vue删一下

// app.vue
<script setup lang="ts">
import ChatUI from "./components/chatUI.vue";
</script><template><div class="container"><ChatUI /></div>
</template><style scoped>
.container {width: 100%;height: 100%;
}
</style>

无需多言,**chatUI.vue代码**奉上(主要界面gpt画的,我加了接口调用)\

// chatUI.vue
<template><div class="chat-container"><div class="messages"><divv-for="(item, index) in chatList":key="index":class="['message', item.type]"><div class="bubble">{{ item.content }}</div><div class="avatar"><component:is="item.type === 'question' ? UserOutlined : RobotOutlined"/></div></div></div><div class="input-area"><a-inputv-model:value="inputValue"placeholder="Type a message..."@pressEnter="handleSend"/><a-button type="primary" @click="handleSend">send</a-button></div></div>
</template><script setup lang="ts">
import axios from "axios";
import { ref } from "vue";
import { UserOutlined, RobotOutlined } from "@ant-design/icons-vue";
const inputValue = ref("");
let chatList = ref<any[]>([]);const handleSend = () => {const question = inputValue.value.trim();if (question) {getAnswer(question);chatList.value.push({ type: "question", content: question });inputValue.value = ""; // 清空输入框}
};
function getAnswer(question: string) {const URL = "http://localhost:8080/chat";const payload = {messages: question,};sendPost(URL,payload,{},(res: any) => {console.log(res.data.message);chatList.value.push({ type: "answer", content: res.data.message });},(err: any) => {console.log(err);});
}//post方法
function sendPost(url: string,data: any,headers = {},funcSuccess: any,funcError: any
) {const headerTem = {"content-Type": "application/json;charset=UTF-8",};if (JSON.stringify(headers) != "{}") {Object.assign(headerTem, headers);}axios.post(url, data, {headers: headerTem,}).then(function (res) {console.log("sendPost res info :", res);funcSuccess(res);}).catch((err) => {console.log("sendPost err info :" + err);if (funcError) {funcError(err);}});
}
</script><style scoped>
.chat-container {min-width: 300px;height: 100%;display: flex;flex-direction: column;/* background-color: #1e1e1e; */border: 1px solid #999;border-radius: 8px;
}.messages {height: 650px;overflow-y: auto;padding: 10px;display: flex;flex-direction: column;gap: 10px;
}
.bubble {color: #333;text-align: right;margin-right: 8px;
}
.input-area {display: flex;
}
.message {display: flex;align-items: center;
}.question {justify-content: flex-end;
}.answer {justify-content: flex-start;
}
</style>

这个就是简单的调用接口,我就不注释了,我们试一下接口
我们在vscode中看一下当前效果

图片

image.png

还可以吧,也不能要求AI太高,哈哈,我们问几个问题试试

图片

image.png

啊?文心一言还挺强,紧跟时事哦

所以你的接口通了吗?通了的话点个赞吧,好人一生平安~
没通的话原因有点多,代码是没问题的,其他的可以评论区讨论下

至此我们的聊天小插件算是开发完成了,我们学习了如何创建一个vscode插件,随后搭建了一个vue3项目展示在了侧边栏里,然后我们用nodejs接入了文心一言api,前端调用接口简单实现了对话功能,希望你看完这篇文章有所收获,有所感想!

五:注册开发者账号并发布插件

1. 推荐教程

插件开发手册[8]

根据教程注册账号,拿到自己的Token,通过vsce publish 1.0.x 来更新版本

2. 增加插件商店图标

插件商店的图标是通过读取package.json中的icon来展示的,该字段与publisher同级

"icon": "images/icon.png",

3. 前端资源的缓存策略会影响插件web页面的实时更新

因为插件实时访问的前端服务,当我们更新前端资源时,当然希望插件能同步更新,此时要注意前端资源的缓存策略,最好是配置为 cache-control:no-store no-cache

六:实战能力探讨(会持续更新,欢迎探讨)

1. 行内提示功能的设计与实现(InlineCompletionItemProvider[9])

先说一个思路,就是用InlineCompletionItemProvider实现行内提示

2. SSH 远程打开文件能力(使用 remote-ssh 插件提供的命令)

先说一个思路,就是通过在控制台执行 remote-ssh 的命令 :code --reuse-window vscode-remote://ssh-remote+${hostname}${path} 来实现打开远程ssh地址的文件,需要安装remote-ssh插件

3. Json 文件可视化编辑(JsonToHtml)

先说一个思路,就是监听用户打开文件夹时的事件,然后再窗口中打开一个新的webview,试用了一些jsonToHtml的包不如自己手动格式化,将bool格式化为checkbox等.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/189431.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

音视频基础知识

图像&#xff08;YUV RGB&#xff09; ​​​​​​​​​​​​​​这个讲的比较好 RGB颜色编码 图像显示主要是由像素组成&#xff0c;每个像素点的颜色组成都是采用RGB格式&#xff0c;RGB就是红、绿、蓝&#xff0c;RGB分别取不同的值&#xff0c;展示不同的颜色。 YUV…

FD-Align论文阅读

FD-Align: Feature Discrimination Alignment for Fine-tuning Pre-Trained Models in Few-Shot Learning&#xff08;NeurIPS 2023&#xff09; 主要工作是针对微调的和之前的prompt tuining&#xff0c;adapter系列对比 Motivation&#xff1a; 通过模型对虚假关联性的鲁棒…

爬虫项目(12):正则、多线程抓取腾讯动漫,Flask展示数据

文章目录 书籍推荐正则抓取腾讯动漫数据Flask展示数据 书籍推荐 如果你对Python网络爬虫感兴趣&#xff0c;强烈推荐你阅读《Python网络爬虫入门到实战》。这本书详细介绍了Python网络爬虫的基础知识和高级技巧&#xff0c;是每位爬虫开发者的必读之作。详细介绍见&#x1f44…

55. 右旋字符串(第八期模拟笔试)

55. 右旋字符串&#xff08;第八期模拟笔试&#xff09; 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;参考代码&#xff1a;错误经验吸取 原题链接&#xff1a; 55. 右旋字符串&#xff08;第八期模拟笔试&#xff09; https://kamacoder.com/problempage…

HTTP协议详解-下(Tomcat)

如何构造 HTTP 请求 对于 GET 请求 地址栏直接输入点击收藏夹html 里的 link script img a…form 标签 通过 form 标签构造GET请求 <body><!-- 表单标签, 允许用户和服务器之间交互数据 --><!-- 提交的数据报以键值对的结果来组织 --><form action&quo…

elastic-job 完结篇

一 elastic-job 1.1 案例场景分析 1.设置4个分片&#xff0c;10秒执行一次。 分片弹性扩容缩容机制测试&#xff1a; 测试1&#xff1a;测试窗口1不关闭&#xff0c;再次运行main方法查看控制台日志&#xff0c;注意修改application.properties中的 server.port&#xf…

C++语言的广泛应用领域

目录 1. 系统级编程 2. 游戏开发 3. 嵌入式系统 4. 大数据处理 5. 金融和量化分析 6. 人工智能和机器学习 7. 网络和通信 结语 C是一种多范式编程语言&#xff0c;具有高性能、中级抽象能力和面向对象的特性。由Bjarne Stroustrup于1979年首次设计并实现&#xff0c;C在…

qframework 架构 (作者:凉鞋)使用笔记

一些准则&#xff1a; 根据VIEW->SYSTEM->MODEL的分层架构 初始架构&#xff1a; app. using FrameworkDesign;namespace ShootingEditor2D&#xff08;项目的命名空间&#xff09; {public class ShootingEditor2D &#xff08;游戏名称&#xff09;: Architecture&l…

UE5蓝图接口使用方法

在内容区右键创建蓝图接口 命名自定义&#xff08;可以用好识别的&#xff09; 双击打开后关闭左边窗口 右键函数 -- 重命名 -- 名称自定义&#xff08;用好记的&#xff09; 点击下边输入后面的 号创建一个变量 点击编译并保存 在一个蓝图类里面 -- 点击类设置 在右侧已实现的…

clouldcompare工具使用

文章目录 1.界面1.1 布局1.3 视觉显示方向1.4 放大镜1.5 建立旋转中心2.快速入门2.1 剪裁2.2 多点云拼接 1.界面 1.1 布局 参考&#xff1a;https://blog.csdn.net/lovely_yoshino/article/details/129595201 1.3 视觉显示方向 1.4 放大镜 1.5 建立旋转中心 2.快速入门 2.1 …

2023年【起重机械指挥】考试试卷及起重机械指挥操作证考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年起重机械指挥考试试卷为正在备考起重机械指挥操作证的学员准备的理论考试专题&#xff0c;每个月更新的起重机械指挥操作证考试祝您顺利通过起重机械指挥考试。 1、【多选题】《中华人民共和国特种设备安全法》…

Linux的目录的权限

目录 目录的权限 目录的权限 1、可执行权限: 如果目录没有可执行权限, 则无法cd到目录中. 2、可读权限: 如果目录没有可读权限, 则无法用ls等命令查看目录中的文件内容. 3、可写权限: 如果目录没有可写权限, 则无法在目录中创建文件, 也无法在目录中删除文件. 上面三个权限是…

Mybatis-Plus使用Wrapper自定义SQL

文章目录 准备工作Mybatis-Plus使用Wrapper自定义SQL注意事项目录结构如下所示domain层Controller层Service层ServiceImplMapper层UserMapper.xml 结果如下所示&#xff1a;单表查询条件构造器单表查询&#xff0c;Mybatis-Plus使用Wrapper自定义SQL联表查询不用&#xff0c;My…

删除杀软回调 bypass EDR 研究

01 — 杀软或EDR内核回调简介 Windows x64 系统中&#xff0c;由于 PatchGuard 的限制&#xff0c;杀软或EDR正常情况下&#xff0c;几乎不能通过 hook 的方式&#xff0c;完成其对恶意软件的监控和查杀。那怎么办呢&#xff1f;别急&#xff0c;微软为我们提供了其他的方法&a…

基于单片机设计的智能风扇(红外线无线控制开关调速定时)

一、项目介绍 在炎热的夏季&#xff0c;风扇成为人们室内生活中必不可少的电器产品。然而&#xff0c;传统的风扇控制方式存在一些不便之处&#xff0c;比如需要手动操作开关、无法远程控制和调速&#xff0c;以及缺乏定时功能等。为了解决这些问题&#xff0c;设计了一款基于…

【数据结构】树与二叉树(十二):二叉树的递归创建(算法CBT)

文章目录 5.2.1 二叉树二叉树性质引理5.1&#xff1a;二叉树中层数为i的结点至多有 2 i 2^i 2i个&#xff0c;其中 i ≥ 0 i \geq 0 i≥0。引理5.2&#xff1a;高度为k的二叉树中至多有 2 k 1 − 1 2^{k1}-1 2k1−1个结点&#xff0c;其中 k ≥ 0 k \geq 0 k≥0。引理5.3&…

基于nginx在视频播放器与服务器之间反向代理流程

1 服务器部署 由于我手里只有内网服务器&#xff0c;可以使用&#xff0c;因此在部署nginx代理服务器&#xff0c;使之在播放器和服务器之间实现反向代理并且缓存内容之前&#xff0c;需要做内网穿透&#xff0c;获得可与外界进行通信的地址。 如果想进行内网穿透&#xff0c;…

我的一点记录 —— 256天

机缘 之所以开始坚持写博客&#xff0c;是希望可以借此对所学的知识进行一个巩固&#xff0c;并方便日后的复习。在CSDN这个平台&#xff0c;我也确实学到了很多有质量的内容&#xff0c;同时也希望自己可以向外输出高质量且有水平的相关知识。256天&#xff0c;蛮快的&#x…

基于vue的cron表达式组件——vue-crontab插件

前言&#xff1a; vue 的 cron 组件&#xff0c;支持解析/反解析 cron 表达式&#xff0c;生成最近五次的符合条件时间&#xff0c;依赖 vue2 和 element-ui 效果图&#xff1a; 一、下载安装依赖插件 npm install vcrontab 二、引用方式 //全局引入 import vcrontab f…

SQL Server 2022 安装步骤——SQL Server设置身份验证教程

目录 前言: 安装详细步骤: 第一步: 第二步: 第三步: 第四步: SQL Server 连接的方式: Window验证: SQL Server验证: 两者之间区别: 总结: SQL Server身份验证登录配置教程:​ 第一步: 第二步: 第三步: 番外篇: 前言: 本文讲解&#xff0c;如何安装SQL Server安…