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

SpringBoot整合websockt实现消息对话

文章目录

  • 前言
  • websockt
    • 什么是websockt?
    • websockt和Socket区别
    • 代码部分
    • 实战应用

前言

websockt

什么是websockt?

WebSocket是一种在Web应用程序中实现实时双向通信的技术。Web应用程序通常是基于HTTP协议的,HTTP是一种请求/响应式的协议,客户端发起请求,服务器响应请求并发送响应,客户端收到响应后关闭连接。这意味着,如果客户端需要不断地从服务器获取更新,它必须定期发送请求以检查更新,这将导致大量的网络流量和不必要的服务器负载。

WebSocket通过在客户端和服务器之间创建持久化连接,允许双向实时通信。这意味着服务器可以主动向客户端推送更新,而不必等待客户端不停地请求。WebSocket连接始于HTTP握手,然后升级到WebSocket协议。在升级过程中,客户端和服务器之间的数据传输方式从HTTP变成了WebSocket协议,这样可以降低传输数据的延迟和提高传输数据的可靠性。

在WebSocket协议中,数据是以帧的形式传输的,帧包括数据头和数据体两个部分。数据头指示数据类型,数据传输的方向等信息,数据体则包括实际传输的数据。WebSocket支持文本类型和二进制类型的数据。文本类型的数据使用UTF-8编码,而二进制类型的数据可以包括任何二进制数据,如图像、音频、视频等。

WebSockets是非常适合实时通信的技术。它可以用于在线游戏、在线聊天、推送通知、实时监控等,并且比传统的轮询技术更加高效和可靠。对于现代Web应用程序而言,WebSockets已经成为不可或缺的技术之一。

websockt和Socket区别

区别WebSocketSocket
应用层协议基于HTTP协议,升级为WebSocket协议没有明确的应用层协议,常用于传输TCP或UDP数据
传输数据类型支持文本和二进制类型的数据通常用于传输二进制数据,如图片、视频等
客户端和服务器通信支持实时双向通信支持双向通信,但通常需要进行轮询或长连接
传输效率比传统的轮询技术更加高效和可靠,不会频繁请求服务器传输效率较低,需要进行轮询或者长连接来保持连接,会频繁请求服务器
应用场景适用于实时通信,如在线游戏、在线聊天、推送通知、实时监控等适用于需要传输大量二进制数据的场景,如文件传输、图片处理等

代码部分

引入maven依赖

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

说明:默认版本为1.5.10RELEASE,可自定义版本,加入“<version">"”标签即可
常量类

package com.dmsdbj.itoo.utils;
public class Constant {//webSocket相关配置//链接地址public static String WEBSOCKETPATHPERFIX = "/ws-push";public static String WEBSOCKETPATH = "/endpointWisely";//消息代理路径public static String WEBSOCKETBROADCASTPATH = "/topic";//前端发送给服务端请求地址public static final String FORETOSERVERPATH = "/welcome";//服务端生产地址,客户端订阅此地址以接收服务端生产的消息public static final String PRODUCERPATH = "/topic/getResponse";//点对点消息推送地址前缀public static final String P2PPUSHBASEPATH = "/user";//点对点消息推送地址后缀,最后的地址为/user/用户识别码/msgpublic static final String P2PPUSHPATH = "/msg";
}

接收前端消息实体

package com.dmsdbj.itoo.vo;
public class WiselyMessage {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}
}

后台发送消息实体

package com.dmsdbj.itoo.vo;public class WiselyResponse {private String responseMessage;public WiselyResponse(String responseMessage){this.responseMessage = responseMessage;}public String getResponseMessage() {return responseMessage;}public void setResponseMessage(String responseMessage) {this.responseMessage = responseMessage;}
}

配置websocket

package com.dmsdbj.itoo.config;import com.dmsdbj.itoo.utils.Constant;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
@Configuration
// @EnableWebSocketMessageBroker注解用于开启使用STOMP协议来传输基于代理(MessageBroker)的消息,这时候控制器(controller)
// 开始支持@MessageMapping,就像是使用@requestMapping一样。
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {@Overridepublic void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {//注册一个Stomp的节点(endpoint),并指定使用SockJS协议。stompEndpointRegistry.addEndpoint(Constant.WEBSOCKETPATH).withSockJS();}@Overridepublic void configureMessageBroker(MessageBrokerRegistry registry) {//服务端发送消息给客户端的域,多个用逗号隔开registry.enableSimpleBroker(Constant.WEBSOCKETBROADCASTPATH, Constant.P2PPUSHBASEPATH);//定义一对一推送的时候前缀registry.setUserDestinationPrefix(Constant.P2PPUSHBASEPATH);//定义websoket前缀registry.setApplicationDestinationPrefixes(Constant.WEBSOCKETPATHPERFIX);}
}

采用JPA方法进行操作数据库DAO层

package com.dmsdbj.itoo.repository;
import com.dmsdbj.itoo.entity.TbUser;
import org.springframework.data.jpa.repository.JpaRepository;
public interface TbUseRepository extends JpaRepository<TbUser,Long> {}

sql语句

CREATE TABLE `tb_user` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`username` varchar(50) DEFAULT NULL COMMENT '用户名',`password` varchar(32) DEFAULT NULL COMMENT '密码,加密存储',`phone` varchar(20) DEFAULT NULL COMMENT '注册手机号',`email` varchar(50) DEFAULT NULL COMMENT '注册邮箱',`created` datetime DEFAULT NULL,`updated` datetime DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY `username` (`username`) USING BTREE,UNIQUE KEY `phone` (`phone`) USING BTREE,UNIQUE KEY `email` (`email`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=18333611875 DEFAULT CHARSET=utf8 COMMENT='用户表';

TbUser实体类

package com.dmsdbj.itoo.entity;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.io.Serializable;
@Entity
@Data
public class TbUser implements Serializable {@Idprivate Long id;private String username;private String password;private String phone;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getPhone() {return phone;}public void setPhone(String phone) {this.phone = phone;}
}

Service实现类

@Service
public class TbUseServiceImpl implements TbUseService {@AutowiredTbUseRepository repository;/*** 从数据库查询用户,给订阅者发送消息* @return*/@Overridepublic List<Long> send2Users() {return repository.findAll().stream().map(s -> s.getId()).collect(Collectors.toList());}
}

Service接口类

public interface TbUseService {List<Long> send2Users();
}

Façade实现类

@Service
public class TbUseFacadeImpl implements TbUseFacade {@AutowiredTbUseService tbUseService;@Overridepublic List<Long> send2Users() {return tbUseService.send2Users();}
}

Façade接口类

public interface TbUseFacade {
List<Long> send2Users();
}

Controller类

@Controller
public class SendInfoController {@ReferenceTbUseFacade tbUseFacade;@Autowiredprivate SimpMessagingTemplate template;@ResourceWebSocketService webSocketService;@MessageMapping(Constant.FORETOSERVERPATH)//@MessageMapping和@RequestMapping功能类似,用于设置URL映射地址,浏览器向服务器发起请求,需要通过该地址。
//    @SendTo(Constant.PRODUCERPATH)//如果服务器接受到了消息,就会对订阅了@SendTo括号中的地址传送消息。public WiselyResponse say(WiselyMessage message) throws Exception {List<Long> userId = tbUseFacade.send2Users();userId.forEach(s->{template.convertAndSendToUser(s.toString(),Constant.P2PPUSHPATH, new WiselyResponse(message.getName()));});return null;}
}

前端页面
sendws.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8" /><title>Spring Boot+WebSocket+广播式</title></head>
<body onload="disconnect()">
<noscript><h2 style="color: #ff0000">貌似你的浏览器不支持websocket</h2></noscript>
<div><div><button id="connect" onclick="connect();">连接</button><button id="disconnect" disabled="disabled" onclick="disconnect();">断开连接</button></div><div id="conversationDiv"><label>输入要发送的消息</label><input type="text" id="name" /><button id="sendName" onclick="sendName();">发送</button><p id="response"></p><p id="response1"></p></div>
</div>
<!--<script th:src="@{sockjs.min.js}"></script>
<script th:src="@{stomp.min.js}"></script>
<script th:src="@{jquery.js}"></script>-->
<script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js"></script>
<script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script th:inline="javascript">var stompClient = null;//此值有服务端传递给前端,实现方式没有要求//var userId = [[${userId}]];var userId = 'd892bf12bf7d11e793b69c5c8e6f60fb';function setConnected(connected) {document.getElementById('connect').disabled = connected;document.getElementById('disconnect').disabled = !connected;document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden';$('#response').html();}function connect() {var socket = new SockJS('/endpointWisely'); //1连接SockJS的endpoint是“endpointWisely”,与后台代码中注册的endpoint要一样。stompClient = Stomp.over(socket);//2创建STOMP协议的webSocket客户端。stompClient.connect({}, function(frame) {//3连接webSocket的服务端。setConnected(true);console.log('开始进行连接Connected: ' + frame);});}function disconnect() {if (stompClient != null) {stompClient.disconnect();}setConnected(false);console.log("Disconnected");}function sendName() {var name = $('#name').val();console.log(name);//通过stompClient.send()向地址为"/welcome"的服务器地址发起请求,与@MessageMapping里的地址对应。因为我们配置了registry.setApplicationDestinationPrefixes(Constant.WEBSOCKETPATHPERFIX);所以需要增加前缀/ws-push/stompClient.send("/ws-push/welcome", {}, JSON.stringify({ 'name': name }));}
</script>
</body>
</html>

subws.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8" /><title>Spring Boot+WebSocket+广播式</title></head>
<body onload="disconnect()">
<noscript><h2 style="color: #ff0000">貌似你的浏览器不支持websocket</h2></noscript>
<div><div><button id="connect" onclick="connect();">连接</button><button id="disconnect" disabled="disabled" onclick="disconnect();">断开连接</button></div><div id="conversationDiv"><label>输入你的userId</label><input type="text" id="userId" /><button id="subMsg" onclick="subMsg();">订阅消息</button><p id="response"></p><p id="response1"></p></div>
</div>
<!--<script th:src="@{sockjs.min.js}"></script>
<script th:src="@{stomp.min.js}"></script>
<script th:src="@{jquery.js}"></script>-->
<script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js"></script>
<script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script th:inline="javascript">var stompClient = null;//此值有服务端传递给前端,实现方式没有要求//var userId = [[${userId}]];function setConnected(connected) {document.getElementById('connect').disabled = connected;document.getElementById('disconnect').disabled = !connected;document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden';$('#response').html();}function connect() {var socket = new SockJS('/endpointWisely'); //1连接SockJS的endpoint是“endpointWisely”,与后台代码中注册的endpoint要一样。stompClient = Stomp.over(socket);//2创建STOMP协议的webSocket客户端。stompClient.connect({}, function(frame) {//3连接webSocket的服务端。setConnected(true);console.log('开始进行连接Connected: ' + frame);//4通过stompClient.subscribe()订阅服务器的目标是'/topic/getResponse'发送过来的地址,与@SendTo中的地址对应。/*stompClient.subscribe('/topic/getResponse', function(respnose){showResponse(JSON.parse(respnose.body).responseMessage);});*/});}function subMsg() {var userId = $('#userId').val();console.log(userId);$.ajax({type: 'GET',url: '/user/insert?userId='+userId,//data: userId,success: function (data) {console.log(data);//4通过stompClient.subscribe()订阅服务器的目标是'/user/' + userId + '/msg'接收一对一的推送消息,其中userId由服务端传递过来,用于表示唯一的用户,通过此值将消息精确推送给一个用户stompClient.subscribe('/user/' + userId + '/msg', function(respnose){console.log(respnose);showResponse1(JSON.parse(respnose.body).responseMessage);});}});}function disconnect() {if (stompClient != null) {stompClient.disconnect();}setConnected(false);console.log("Disconnected");}function showResponse1(message) {var response = $("#response1");response.html(message);}
</script>
</body>
</html>

实战应用

①启动springboot-dubbo-service的主启动类“SpringbootDubboServiceApplication”
②启动springboot-dubbo-web的主启动类“SpringbootDubboWebApplication”
③访问
http://localhost:9000/sendws 发送消息方
http://localhost:9000/subws 订阅消息方
④分别进行连接操作
订阅方输入订阅方的连接账号userid,后期就可以接收发送端发送的消息
连接后的结果展示
在这里插入图片描述

相关文章:

SpringBoot整合websockt实现消息对话

文章目录 前言websockt什么是websockt&#xff1f;websockt和Socket区别代码部分实战应用 前言 websockt 什么是websockt&#xff1f; WebSocket是一种在Web应用程序中实现实时双向通信的技术。Web应用程序通常是基于HTTP协议的&#xff0c;HTTP是一种请求/响应式的协议&…...

MIME类型(Multipurpose Internet Mail Extensions,多用途互联网邮件扩展类型)MultipartFile 多媒体文件上传

目录 MIME媒体类型介绍MediaTypes 有哪些MultipartFile 类介绍MultipartFile 类 接收的文件是二进制嘛代码举例 上传的文件 实现接口 MultipartFile 类有哪些最终调用接口的方法时&#xff0c;会有哪个类实现 如何决定哪个类去实现呢 Spring 会根据运行环境自动选择合适的实现类…...

数据库(MySQL)的存储过程

一、存储过程介绍 存储过程是事先经过编译并存储在数据库中的一段SQL 语句的集合&#xff0c;调用存储过程可以简化应用开发人员的很多工作&#xff0c;减少数据在数据库和应用服务器之间的传输&#xff0c;对于提高数据处理的效率是有好处的。 存储过程思想上很简单&#xff0…...

Flutter:getX的学习

前言 学习教程&#xff1a;Getx教程_FlutterGetx系列实战教程 简介 getX是第三方的状态管理插件&#xff0c;不仅具有状态管理的功能&#xff0c;还具有路由管理、主题管理、国际化多语言管理、网络请求、数据验证等功能。相比其他状态管理组件&#xff0c;getX简单、功能强大…...

leetcode - 360周赛

一&#xff0c;2833. 距离原点最远的点 这道题的意思是&#xff0c;遇到 "L" 向左走&#xff0c;遇到 "R" 向右走&#xff0c;遇到 "_" 左右都可以走&#xff0c;那么要想找到距离原点最远的点&#xff0c;就是在找 | "L" "R&qu…...

Android 1.1 背景相关与系统架构分析

目录 1.1 背景相关与系统架构分析 分类 Android 基础入门教程 1.Android背景与当前的状况 2.Android系统特性与平台架构 系统特性&#xff1a; 平台架构图&#xff1a; 架构的简单理解&#xff1a; 3.本节小结&#xff1a; 1.1 背景相关与系统架构分析 分类 Android 基础…...

系统架构技能之设计模式-抽象工厂模式

一、上篇回顾 上篇我们主要讲述了简单工厂模式和工厂模式。并且分析了每种模式的应用场景和一些优缺点&#xff0c;我们现在来回顾一下&#xff1a; 简单工厂模式&#xff1a;一个工厂负责所有类型对象的创建&#xff0c;不支持无缝的新增新的类型对象的创建。 工厂模式&…...

clangd的使用,实现跳转提示

一、插件卸载c插件下载clangd 二、设置搜索clangd --compile-commands-dirbuild文件中compile_commands的绝对路径若没有找到compile_commands.json文件可以通过如下方式之后再便于即可生成 cmake项目&#xff1a; 在项目最顶层的.cmake文件中或者CMakeList文件中加入如下命令…...

2023应届生java面试搞笑之一:CAS口误说成开心锁-笑坏面试官

源于&#xff1a;XX网&#xff0c;如果冒犯&#xff0c;表示歉意 面试官&#xff1a;什么是CAS 我&#xff1a;这个简单&#xff0c;开心锁 面试官&#xff1a;WTF&#xff1f; 我&#xff1a;一脸自信&#xff0c;对&#xff0c;就是这个 面试官&#xff1a;哈哈大笑&#xff…...

nginx-concat

为了减少tcp请求数量&#xff0c;nginx从上有服务器获取多个静态资源&#xff08;css&#xff0c;js&#xff09;的时候&#xff0c;将多个静态资源合并成一个返回给客户端。 这种前面有两个问号的请求都是用了cancat合并功能。 先到官网下载安装包&#xff0c;拷贝到服务器编译…...

Java 大厂面试 —— 常见集合篇 List HashMap 红黑树

23Java面试专题 八股文面试全套真题&#xff08;含大厂高频面试真题&#xff09;多线程_软工菜鸡的博客-CSDN博客 常见集合篇-01-集合面试题-课程介绍 02-算法复杂度分析 2 List相关面试题 2.1 数组 2.1.1 数组概述 数组&#xff08;Array&#xff09;是一种用连续的内存空…...

剪枝基础与实战(5): 剪枝代码详解

对模型进行剪枝,我们只对有参数的层进行剪枝,我们基于BatchNorm2d对通道重要度 γ \gamma γ参数进行稀释训练。对BatchNorm2d及它的前后层也需要进行剪枝。主要针对有参数的层:Conv2d、BatchNorm2d、Linear。但是我们不会对Pool2d 层进行剪枝,因为Pool2d只用来做下采样,没…...

Acwing 897. 最长公共子序列 (每日一题)

最长公共子序列 题目描述 给定两个长度分别为 N 和 M 的字符串 A 和 B&#xff0c;求既是 A 的子序列又是 B 的子序列的字符串长度最长是多少。 输入格式 第一行包含两个整数 N和 M。 第二行包含一个长度为 N 的字符串&#xff0c;表示字符串 A。 第三行包含一个长度为 M …...

CSS中border-radius的来美化table的实战方案

border-radius是一种CSS属性&#xff0c;用于设置元素的边框的圆角程度。其具体的用法如下&#xff1a; 设置一个值&#xff1a;可以为元素设置一个单一的圆角半径&#xff0c;这个半径将应用于元素的四个角。例如&#xff1a; div {border-radius: 10px; }设置四个值&#x…...

移除链表元素_每日一题

“路虽远&#xff0c;行则将至” ❤️主页&#xff1a;小赛毛 ☕今日份刷题&#xff1a;移除链表元素 题目描述&#xff1a; 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例1&…...

spring boot + Consul 示例 (Kotlin版)

文章目录 1.docker 安装consul2.创建基于springboot的client2.1 依赖版本2.2 pom.xml2.3 启动类2.4 application.properties 3 搭建完成4. 总结 1.docker 安装consul docker-compose.yaml version: "3"services:consul:image: consul:1.4.4container_name: consule…...

Git企业开发控制理论和实操-从入门到深入(四)|Git的远程操作|Gitee

前言 那么这里博主先安利一些干货满满的专栏了&#xff01; 首先是博主的高质量博客的汇总&#xff0c;这个专栏里面的博客&#xff0c;都是博主最最用心写的一部分&#xff0c;干货满满&#xff0c;希望对大家有帮助。 高质量博客汇总 然后就是博主最近最花时间的一个专栏…...

SpringCloudAlibaba Gateway(二)详解-内置Predicate、Filter及自定义Predicate、Filter

Predicate(断言) ​ Predicate(断言)&#xff0c;用于进行判断&#xff0c;如果返回为真&#xff0c;才会路由到具体服务。SpirnngCloudGateway由路由断言工厂实现&#xff0c;直接配置即生效&#xff0c;当然也支持自定义路由断言工厂。 内置路由断言工厂实现 ​ SpringClo…...

调用chat-gpt

调用chat-gpt 依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifact…...

Element组件浅尝辄止6:Dialog 对话框组件

Dialog 对话框组件&#xff1a;在保留当前页面状态的情况下&#xff0c;告知用户并承载相关操作。 大白话就是弹窗组件&#xff0c;日常开发中比较常见 1.怎样使用&#xff1f; //触发方式 <el-button type"text" click"dialogVisible true">打开&…...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

多种风格导航菜单 HTML 实现(附源码)

下面我将为您展示 6 种不同风格的导航菜单实现&#xff0c;每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

腾讯云V3签名

想要接入腾讯云的Api&#xff0c;必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口&#xff0c;但总是卡在签名这一步&#xff0c;最后放弃选择SDK&#xff0c;这次终于自己代码实现。 可能腾讯云翻新了接口文档&#xff0c;现在阅读起来&#xff0c;清晰了很多&…...