当前位置: 首页 > article >正文

Spring AI 1.0.0 M6新特性MCP

Spring AI 1.0.0 M6新特性MCP

  • 前言
  • 一、MCP是什么?(Model Context Protocol)
  • 二、它的发展历程
  • 三、核心架构
  • 四、MCP Java SDK的核心能力
    • Java MCP实现遵循三层架构:
    • MCP客户端
    • MCP服务器
    • 总结MCP 的核心能力
    • 总结多种传输选项
  • 搭建服务端与客户端
    • 服务端
      • 引入maven依赖
      • 配置YML
      • 编写服务工具
      • 注册为ToolCallbackProvider
    • 客户端
      • 引入maven依赖
      • 配置YML
      • 编写controller


前言

在人工智能技术日新月异的今天,Spring AI作为Spring家族的新星,正以前所未有的速度发展与进化。从最初的简单应用到如今复杂多样的功能集成,Spring AI不断突破边界,为用户提供更加智能、高效的解决方案。而在这一系列的迭代升级中,1.0.0 M6版本无疑成为了一个备受瞩目的里程碑。本文将深入探讨这一新版本所带来的新特性MCP(Model Context Protocol),以及它如何为开发者和企业带来全新的机遇与挑战。通过详细的解析与实例展示,我们希望能够帮助您更好地理解并应用这些前沿技术,开启智能化新篇章。
是不是感觉很熟悉又陌生Cursor与Trae编辑器的人都清楚,为什么他能操作我本地的系统并执行代码下载依赖等问题?那么我们来讲解一下MCP


一、MCP是什么?(Model Context Protocol)

MCP,全称是Model Context Protocol(模型上下文协议),可以把它想象成一个让AI模型更顺畅工作的“桥梁”和“助手”。

连接数据源和工具:就像我们要做饭需要从不同地方买来食材和厨具一样,AI模型工作也需要很多不同的数据和工具。MCP就提供了一个统一的方式,让AI模型能轻松地连接到各种数据来源和使用各种工具,不需要每次都重新折腾怎么连接,让整个过程变得无缝又一致。

助力构建智能代理和复杂工作流程:咱们开发的时候,经常得基于大型语言模型(LLMs)来创建一些能自主干活的智能代理,还有很复杂的工作流程。这时候MCP就派上用场了,它能让这些开发工作变得更简单高效。因为大型语言模型常常要和好多数据、工具打交道,MCP就像个贴心小助手,提供了预建好的集成方式,你的LLM可以直接用;还能灵活地在不同LLM供应商和厂商之间切换;并且有标准的接口用于发现和使用工具。

二、它的发展历程

去年11月,Model Context Protocol发布了,而且在AI社区里反响特别好,这可是去年的大惊喜呢,大家都很期待它能带来新变化。

从去年11月开始,spring - ai - mcp这个实验性项目就启动了,之后一直在不断发展。Spring AI团队还和Anthropic公司的David Soria Parra等人一起合作,把这个实验性项目变成了正式的MCP Java SDK。

三、核心架构

了解MCP如何连接客户端、服务器和LLM

模型上下文协议(MCP)建立在一个灵活的、可扩展的体系结构上,可以实现LLM应用程序和集成之间的无缝通信。本文档涵盖了核心架构组件和概念。

MCP遵循客户端-服务器架构,其中:

启动连接的LLM应用程序 Claude Desktop或IDE
客户端在主机应用程序内与服务器保持1:1连接
服务器为客户端提供上下文、工具和提示

在这里插入图片描述

四、MCP Java SDK的核心能力

Java MCP实现遵循三层架构:

在这里插入图片描述

客户端/服务器层:McpClient处理客户端操作,而McpServer管理服务器端协议操作。两者都使用McpSession进行通信管理。
会话层(McpSession):通过DefaultMcpSession实现管理通信模式和状态。
传输层(McpTransport):处理JSON-RPC消息序列化和非序列化,支持多种传输实现。

MCP客户端

MCP客户端是模型上下文协议(MCP)架构中的关键组件,负责建立和管理与MCP服务器的连接。它实现了协议的客户端,处理:

  • 协议版本协商以确保与服务器的兼容性
  • 能力协商以确定可用功能
  • 消息传输和JSON-RPC通信
  • 工具发现和执行
  • 资源获取和管理
  • 提示系统交互

在这里插入图片描述

MCP服务器

MCP服务器是模型上下文协议(MCP)体系结构中的基础组件,为客户端提供工具、资源和功能。它实现了协议的服务器端,负责:

  • 服务器端协议操作实现
  • 工具暴露和发现
  • 使用基于URI的访问进行资源管理
  • 迅速提供和处理模板
  • 与客户进行能力协商
  • 结构化日志和通知
  • 并发客户端连接管理
  • 同步和异步API支持
  • 传输实现:

用于基于进程的通信的基于stdio的传输
基于Servlet的SSE服务器传输

  • WebFlux SSE服务器传输用于响应式HTTP流
  • 用于基于servlet的HTTP流的WebMVC SSE服务器传输

在这里插入图片描述

总结MCP 的核心能力

  • 同步和异步客户端/服务器实现: 这个功能可以让不同的操作在不同时间、以不同方式去执行,有时候需要同步操作,有时候异步操作更方便,它都能支持。
  • 协议版本兼容性协商: 就好比我们要和不同版本软件打交道一样,它能商量好大家用哪个版本的协议来交流,确保沟通无障碍。
  • 工具发现和执行以及变更通知: 它能像侦探一样去发现有哪些工具可以用,然后安排它们去干活,而且如果有了什么变化,还会及时通知大家。
  • 带URI模板的资源管理: 可以很方便地管理资源,就像把东西分门别类放在不同的文件夹里,通过URI模板能快速找到和管理它们。
  • Roots列表管理和通知: 这个就像是管理一个清单,知道哪些是重要的“根”元素,并且如果有变化会及时告知。
  • 提示处理和管理: 能更好地处理和管理给AI模型的提示信息,让模型更准确地理解和回应我们的需求。
  • AI模型交互的采样支持: 在和AI模型互动的时候,还可以进行采样,就像是从一大群人里抽一部分代表出来了解情况一样,让互动更有针对性。

总结多种传输选项

  • 基于Stdio的进程通信传输:这是比较基础的一种传输方式,就像两个人面对面说话一样直接,适合基于进程的通信。
  • 基于Java HttpClient的SSE客户端传输:利用Java里的HttpClient,通过服务器发送事件(SSE)这种方式来进行数据传输,就像一个网络实时广播,客户端能实时收到消息。-
  • 基于Servlet的SSE服务器传输:这是在服务器端的Servlet基础上进行的SSE传输,让服务器能主动把数据推送给客户端,就像老师在黑板上实时写最新的消息,学生能马上看到。
  • Spring特定的传输方式:

对于反应式HTTP流媒体,有WebFlux SSE传输,就像水流一样,数据源源不断地实时流动,适合反应式的编程场景。
对于基于Servlet的HTTP流媒体,有WebMVC SSE传输,这也是在Servlet基础上实现的实时数据推送,方便在传统的Web应用里使用。

搭建服务端与客户端

本文只用JAVA进行演示我这里使用的是webflux STDIO服务器传输

服务端

引入maven依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.4.3</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.qijc</groupId><artifactId>ai-springboot-mcp-server</artifactId><version>0.0.1-SNAPSHOT</version><name>ai-springboot-mcp-server</name><description>ai-springboot-mcp-server</description><properties><java.version>17</java.version><spring-ai.version>1.0.0-M6</spring-ai.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-mcp-server-webflux-spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-bom</artifactId><version>${spring-ai.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

配置YML

spring:output:ansi:enabled: neverapplication:name: ai-springboot-mcp-servermain:banner-mode: offai:mcp:server:name: ai-springboot-mcp-serverversion: 0.0.1# 服务端配置
logging:level:root: OFF  # 关闭所有日志输出到控制台file:name: server.log  # 将日志重定向到文件

编写服务工具

package com.qijc.service;import org.springframework.ai.tool.annotation.Tool;
import org.springframework.stereotype.Service;import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;@Service
public class DateService {public static class AddressRequest {private String address;public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}}public static class DateResponse {private String result;public DateResponse(String result) {this.result = result;}public String getResult() {return result;}public void setResult(String result) {this.result = result;}}@Tool(description = "获取指定地点的当前时间")public DateResponse getAddressDate(AddressRequest request) {String result = String.format("%s的当前时间是%s",request.getAddress(),LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));return new DateResponse(result);}
}

注册为ToolCallbackProvider

package com.qijc;import com.qijc.service.DateService;import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.tool.function.FunctionToolCallback;
import org.springframework.ai.tool.method.MethodToolCallbackProvider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;@SpringBootApplication
public class AiSpringbootMcpServerApplication {public static void main(String[] args) {SpringApplication.run(AiSpringbootMcpServerApplication.class, args);}@Beanpublic ToolCallbackProvider addressDateTools(DateService dateService) {return MethodToolCallbackProvider.builder().toolObjects(dateService).build();}}

进行将server服务器进行打包,在下面直接引用jar包即可

客户端

引入maven依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.4.3</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.qijc</groupId><artifactId>ai-springboot-mcp-client</artifactId><version>0.0.1-SNAPSHOT</version><name>ai-springboot-mcp-client</name><description>ai-springboot-mcp-client</description><url/><licenses><license/></licenses><developers><developer/></developers><scm><connection/><developerConnection/><tag/><url/></scm><properties><java.version>17</java.version><spring-ai.version>1.0.0-M6</spring-ai.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-mcp-client-webflux-spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-openai-spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-bom</artifactId><version>${spring-ai.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><repositories><repository><name>Central Portal Snapshots</name><id>central-portal-snapshots</id><url>https://central.sonatype.com/repository/maven-snapshots/</url><releases><enabled>false</enabled></releases><snapshots><enabled>true</enabled></snapshots></repository><repository><id>spring-milestones</id><name>Spring Milestones</name><url>https://repo.spring.io/milestone</url><snapshots><enabled>false</enabled></snapshots></repository><repository><id>spring-snapshots</id><name>Spring Snapshots</name><url>https://repo.spring.io/snapshot</url><releases><enabled>false</enabled></releases></repository></repositories><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

配置YML

spring:application:name: ai-springboot-mcp-client#main:#  web-application-type: noneai:mcp:client:stdio:connections:ai-springboot-mcp-server:command: javaargs:- -Dspring.ai.mcp.server.stdio=true- -Dspring.main.web-application-type=none- -Dspring.main.banner-mode=off- -jar- C:\Users\qijch\ai-project\spring-ai-project\ai-springboot-mcp-server\target\ai-springboot-mcp-server-0.0.1-SNAPSHOT.jaropenai:api-key: sk-xxxxxxbase-url: https://dashscope.aliyuncs.com/compatible-mode/chat:options:model: qwen-plusembedding:api-key: sk-xxxxxxbase-url: https://dashscope.aliyuncs.com/compatible-mode/options:model: text-embedding-v2server:port: 8090

编写controller

package com.qijc.controller;import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.model.function.FunctionCallback;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.Arrays;
import java.util.List;/**** @projectName spring-ai-project* @packageName com.qijc.controller* @author qjc* @description TODO* @Email qjc1024@aliyun.com* @date 2025-03-10 15:57**/
@RestController
public class McpController {@Autowiredprivate OpenAiChatModel openAiChatModel;@Autowiredprivate ToolCallbackProvider tools;@GetMapping("/functionCallback")public ResponseEntity<String> functionCallback(@RequestParam String message) {try {SystemMessage systemMessage = new SystemMessage("你是一个助手,请用中文回答。");UserMessage userMessage = new UserMessage(message);FunctionCallback[] toolCallbacks = tools.getToolCallbacks();Prompt prompt = new Prompt(List.of(systemMessage, userMessage));String response = ChatClient.builder(openAiChatModel).defaultAdvisors(new MessageChatMemoryAdvisor(new InMemoryChatMemory())).defaultTools(toolCallbacks).build().prompt(prompt).call().content();return ResponseEntity.ok(response);} catch (Exception e) {return ResponseEntity.status(500).body("服务器错误: " + e.getMessage() + "\n" + Arrays.toString(e.getStackTrace()));}}
}

我们只需要引入 ToolCallbackProvider 即可使用访问

http://localhost:8090/functionCallback?message=中国的首都是哪里,现在时间是多少

在这里插入图片描述
那我们就完成了服务端用来解耦,这样我们就可以进行开发Tools,不同的语言也是支持的服务端不管是js或python 也是支持的

相关文章:

Spring AI 1.0.0 M6新特性MCP

Spring AI 1.0.0 M6新特性MCP 前言一、MCP是什么&#xff1f;&#xff08;Model Context Protocol&#xff09;二、它的发展历程三、核心架构四、MCP Java SDK的核心能力Java MCP实现遵循三层架构&#xff1a;MCP客户端MCP服务器总结MCP 的核心能力总结多种传输选项 搭建服务端…...

【时时三省】(C语言基础)赋值表达式和赋值语句和变量赋初值

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 赋值表达式和赋值语句 在C程序中&#xff0c;赋值语句是用得最多的语句。实际上&#xff0c;C语言的赋值语句属于表达式语句&#xff0c;由一个赋值表达式加一个分号组成。其他一些高级语言…...

Room数据库的使用

一、room的引用导入 1、在app的gradle中引入 plugins {//这个ksp 一定要对应相关的 kotlin 版本&#xff0c;不然会一直报错i的---id("com.google.devtools.ksp") version "1.9.0-1.0.13" apply false } 2、在model的gradle中引入 plugins {id("com.g…...

【性能测试入门_01性能测试jmeter基础实操场景详解】

一、应用项目如何部署在服务器上 可以将项目进行打jar包 双击install&#xff0c;控制台就会打印打包的过程 最终打的包&#xff0c;会存放在打印的那个路径下 这个jar包&#xff0c;就是开发人员开发好&#xff0c;直接可以部署的 可以通过命令&#xff0c;在终端直接启动这…...

SpringBoot加载配置文件的优先级

在 SpringBoot 应用中&#xff0c;配置文件的加载顺序&#xff08;优先级&#xff09;决定了不同来源的配置属性如何覆盖彼此&#xff0c;但是&#xff0c;在实践中&#xff0c;也会经常遇到。下面文章将分析 SpringBoot 配置文件加载的优先级&#xff0c;从高到低排列。 文章目…...

跨越时空的对话:图灵与GPT-4聊AI的前世今生

&#xff08;背景&#xff1a;虚拟咖啡厅&#xff0c;图灵身着1950年代西装&#xff0c;端着一杯热茶&#xff0c;GPT-4以全息投影形态坐在对面&#xff09; 图灵&#xff08;喝了口茶&#xff09;&#xff1a;“听说你能写诗&#xff1f;我当年在布莱切利园破解Enigma时&…...

如何通过 Seatunnel 实现 MySQL 到 OceanBase的数据迁移同步

1. 准备传输工具 本方案采用 Apache Seatunnel&#xff08;简称seatunnel&#xff09;进行MySQL 到 OceanBase 的数据迁移和同步&#xff0c;出于对方案轻量性的考量&#xff0c;我们采用其内置的Zeta引擎来实现&#xff0c;包括全量同步、离线增量同步&#xff0c;以及CDC方案…...

C++20 新特性总结

简要总结 C20 引入了四项非常大的更新, 分别是: 概念(Concepts). 用来简化模板编程, 强化表达能力. 并且使得出错原因更容易查找.模块(Modules). 这是代码组织方面非常大的更新. 提供了新的方式来组织代码, 并且可以减少编译时间.范围库(Ranges and Views). 轻量级的, 非拥有…...

软件设计模式之简单工厂模式

目录 一.类图&#xff08;手机生产&#xff09; 二.代码实现 Iphone类&#xff1a; Vivo类&#xff1a; Mobile类&#xff1a; MobileFactory类&#xff1a; Client类&#xff1a; 一.类图&#xff08;手机生产&#xff09; 补充&#xff1a;MobileFactory也可以直接指向…...

内网激活JRebel插件(无网络环境)

1.官网下载安装包,JRebel and XRebel JRebel and XRebel - IntelliJ IDEs Plugin | Marketplace 2.以IInstall Plugin from Disk的方式读取 3.运行JrebelServer.jar 终端输入&#xff1a; java -jar JrebelServer.jar -p 8080 (默认8080端口)服务会自动打开浏览器至 http:/…...

LiveGBS流媒体平台GB/T28181常见问题-视频流安全控制HTTP接口鉴权勾选流地址鉴权后401Unauthorized如何播放调用接口流地址校验

LiveGBS流媒体平台GB/T28181常见问题频流安全控制HTTP接口鉴权勾选流地址鉴权后401Unauthorized如何播放调用接口流地址校验&#xff1f; 1、安全控制1.1、HTTP接口鉴权1.2、流地址鉴权 2、401 Unauthorized2.1、携带token调用接口2.1.1、获取鉴权token2.1.2、调用其它接口2.1.…...

Java 大视界 -- 区块链赋能 Java 大数据:数据可信与价值流转(84)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…...

接口自动化入门 —— Http的请求头,请求体,响应码解析!

在接口自动化测试中&#xff0c;HTTP请求头、请求体和响应码是核心组成部分。理解它们的作用、格式和解析方法对于进行有效的接口测试至关重要。以下是详细解析&#xff1a; 1. HTTP 请求头&#xff08;Request Header&#xff09; 1.1 作用 请求头是客户端向服务器发送的附加…...

upload-labs(1-20)详解(专业版)

目录 第1关 第2关 第3关 第4题 第5题 第6题 第7题 第8题 第9题 第10题 第11题 第12题 第13题 第1关 查看源码 在第一关是一个前端js的一个后缀识别&#xff1a;当不为jpg、png、gif时候出现弹窗 检查源码 将return checkFile() 改为 return ture 就可以将php顺利…...

Linux 生成静态库

文章目录 前提小知识生成和使用.a库操作步骤 在应用程序中&#xff0c;有一些公共的代码需要反复使用的&#xff0c;可以把这些代码制作成“库文件”&#xff1b;在链接的步骤中&#xff0c;可以让链接器在“库文件”提取到我们需要使用到的代码&#xff0c;复制到生成的可执行…...

ARMV8的64位指令

一、介绍 ARMv8 体系结构最大的改变是增加了一个新的 64 位的指令集&#xff0c;这是早前 ARM 指令集 的有益补充和增强。它可以处理 64 位宽的寄存器和数据并且使用 64 位的指针来访问内存。这 个新的指令集称为 A64 指令集&#xff0c;运行在 AArch64 状态。 ARMv8 兼容旧的…...

【git】 贮藏 stash

贮藏是我在sourcetree上看到的名词。之前只是浅浅的用来收藏一下修改的文件&#xff0c;没有完整的使用过。今天有幸使用了一次就来展开说说。 使用原因就不赘述了&#xff0c;错误的操作少提为好&#xff0c;操作步骤如下&#xff1a; 查看贮藏列表git stash list #输出&…...

ctf-web: php原生类利用 -- GHCTF Popppppp

源代码 <?php error_reporting(0); class CherryBlossom { public $fruit1; public $fruit2; public function __construct($a) {$this->fruit1 $a; } function __destruct() { echo $this->fruit1; } public function __toString() { $newFunc …...

PawSQL for TDSQL:腾讯云TDSQL数据库性能优化全攻略

TDSQL 作为腾讯云推出的分布式数据库&#xff0c;凭借其高扩展性、高可用性和高性能等优势&#xff0c;广泛应用于金融、互联网、政务等领域。随着业务的不断增长和数据量的爆炸式增长&#xff0c;如何优化 TDSQL 数据库的性能&#xff0c;成为众多企业和开发者面临的挑战。本文…...

202250311-WINDOWS本地4G显存Docker运行vLLM

前置&#xff1a; 需要去huggingface注册账号获取token&#xff1a;HUGGING_FACE_HUB_TOKEN 运行vLLM docker run --name LocalvLLM_qwen1.5B_Int4 --runtime nvidia --gpus all -v D:/vLLM/.cache/huggingface:/root/.cache/huggingface --env "HUGGING_FAC…...

Scala 中生成一个RDD的方法

在 Scala 中&#xff0c;生成 RDD&#xff08;弹性分布式数据集&#xff09;的主要方法是通过 SparkContext&#xff08;或 SparkSession&#xff09;提供的 API。以下是生成 RDD 的常见方法&#xff1a; 1. 从本地集合创建 RDD 使用 parallelize 方法将本地集合&#xff08;如…...

T-SQL 语言基础:表运算符与联接

目录 介绍表运算符概述交叉联接内联接外联接联接实例总结引用 1. 介绍 在这篇博客中&#xff0c;主要涉及 T-SQL 中的表运算符与联接。联接操作是 SQL 查询中最常用的操作之一&#xff0c;它允许我们在多个表之间进行数据关联。通过了解不同类型的联接及其应用场景&#xff…...

Electron打包工具对比

在 Electron 生态中&#xff0c;打包工具的选择直接影响开发效率、配置复杂度和最终应用的性能。以下是主流的 Electron 打包工具及其优劣分析&#xff0c;结合你的 Vue 项目需求&#xff0c;我会在最后给出推荐方案&#xff1a; 一、主流 Electron 打包工具对比 1. Electron …...

jumpserver 网络安全 网络安全 authenticity

1.1 计算机安全的概念 1.1.1 计算机安全最核心的三个关键目标(CIA)&#xff1a; 保密性(Confidentiality)--①数据保密性&#xff08;确保隐私或秘密不向非授权者泄密或使用&#xff09;&#xff1b; ②隐私性&#xff08;确保个人能够控制或确定其自身相关的信息&#xff09…...

Spring Cloud之远程调用OpenFeign参数传递

目录 OpenFeign参数传递 传递单个参数 传递多个参数 传递对象 传递JSON OpenFeign参数传递 传递单个参数 服务提供方product-service RequestMapping("/product") RestController public class ProductController {Autowiredprivate ProductService productSe…...

详解SQL权限与授予与收回对数据操作权限的操作

授予与收回对数据操作权限 一、GRANT 操作用法示例 二、REVOKE 操作用法示例 三、权限1. 数据库级别权限常见权限&#xff1a; 2. 对象级别权限作用对象&#xff1a;常见权限&#xff1a;对表或视图&#xff1a;对序列&#xff08;Sequence&#xff09;&#xff1a;对存储过程和…...

网络安全之文件上传漏洞

一&#xff0c;文件上传漏洞的原因&#xff1a; 文件上传漏洞的存在主要是因为开发者未对用户上传的文件进行充分的安全验证&#xff0c;导致攻击者可以上传恶意文件&#xff08;如 WebShell、恶意脚本等&#xff09;到服务器&#xff0c;进而控制服务器或实施进一步攻击。 常…...

Fast DDS Security--仿问控制

Fast DDS中提供了两种级别的仿问控制&#xff1a; 1 Domain Governance: 定义域级别的安全策略&#xff08;全局规则&#xff09;. 2 DomainParticipant Permissions &#xff1a; 定义参与者的具体权限&#xff08;个体规则&#xff09; 先说一下Domain Governance&#xf…...

【13】单片机编程核心技巧:乘法运算

【13】单片机编程核心技巧&#xff1a;乘法运算 七律 乘法 乘法运算寄存间&#xff0c;溢出玄机隐字边。 连乘自增简写妙&#xff0c;移位替代速如仙。 中间变量扩疆土&#xff0c;长整型存避险关。 单片机中精算术&#xff0c;毫厘不爽展奇观。 摘要 乘法运算是单片机编程…...

为什么大模型网站使用 SSE 而不是 WebSocket?

在大模型网站&#xff08;如 ChatGPT、Claude、Gemini 等&#xff09;中&#xff0c;前端通常使用 EventSource&#xff08;Server-Sent Events, SSE&#xff09; 来与后端对接&#xff0c;而不是 WebSocket。这是因为 SSE 更适合类似流式文本生成的场景。下面我们详细对比 SSE…...