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

美橙网站建设怎么做/百度seo一本通

美橙网站建设怎么做,百度seo一本通,毕业设计网站成品,网页设计作业怎么保存spring boot 实现直播聊天室(二) 技术方案: spring bootnettyrabbitmq 目录结构 引入依赖 <dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.96.Final</version> </dependency>Si…

spring boot 实现直播聊天室(二)

技术方案:

  • spring boot
  • netty
  • rabbitmq

目录结构

在这里插入图片描述

引入依赖

<dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.96.Final</version>
</dependency>

SimpleNettyWebsocketServer

netty server 启动类

@Slf4j
public class SimpleNettyWebsocketServer {private SimpleWsHandler simpleWsHandler;public SimpleNettyWebsocketServer(SimpleWsHandler simpleWsHandler) {this.simpleWsHandler = simpleWsHandler;}public void start(int port) throws InterruptedException {NioEventLoopGroup boss = new NioEventLoopGroup(1);NioEventLoopGroup work = new NioEventLoopGroup(2);try {ServerBootstrap bootstrap = new ServerBootstrap();bootstrap.group(boss, work).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<NioSocketChannel>() {@Overrideprotected void initChannel(NioSocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();//HTTP协议编解码器,用于处理HTTP请求和响应的编码和解码。其主要作用是将HTTP请求和响应消息转换为Netty的ByteBuf对象,并将其传递到下一个处理器进行处理。pipeline.addLast(new HttpServerCodec());//用于HTTP服务端,将来自客户端的HTTP请求和响应消息聚合成一个完整的消息,以便后续的处理。pipeline.addLast(new HttpObjectAggregator(65535));pipeline.addLast(new IdleStateHandler(30,0,0));//处理请求参数pipeline.addLast(new SimpleWsHttpHandler());pipeline.addLast(new WebSocketServerProtocolHandler("/n/ws"));pipeline.addLast(simpleWsHandler);}});Channel channel = bootstrap.bind(port).sync().channel();log.info("server start at port: {}", port);channel.closeFuture().sync();} finally {boss.shutdownGracefully();work.shutdownGracefully();}}
}

NettyUtil: 工具类

public class NettyUtil {public static AttributeKey<String> G_U = AttributeKey.valueOf("GU");/*** 设置上下文参数* @param channel* @param attributeKey* @param data* @param <T>*/public static <T> void setAttr(Channel channel, AttributeKey<T> attributeKey, T data) {Attribute<T> attr = channel.attr(attributeKey);if (attr != null) {attr.set(data);}}/*** 获取上下文参数 * @param channel* @param attributeKey* @return* @param <T>*/public static <T> T getAttr(Channel channel, AttributeKey<T> attributeKey) {return channel.attr(attributeKey).get();}/*** 根据 渠道获取 session* @param channel* @return*/public static NettySimpleSession getSession(Channel channel) {String attr = channel.attr(G_U).get();if (StrUtil.isNotBlank(attr)){String[] split = attr.split(",");String groupId = split[0];String username = split[1];return new NettySimpleSession(channel.id().toString(),groupId,username,channel);}return null;}
}

处理handler

SimpleWsHttpHandler

处理 websocket 协议升级时地址请求参数 ws://127.0.0.1:8881/n/ws?groupId=1&username=tom, 解析groupId 和 username ,并设置这个属性到上下文

/*** @Date: 2023/12/13 9:53* 提取参数*/
@Slf4j
public class SimpleWsHttpHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {if (msg instanceof  FullHttpRequest request){//ws://localhost:8080/n/ws?groupId=xx&username=tomString decode = URLDecoder.decode(request.uri(), StandardCharsets.UTF_8);log.info("raw request url: {}", decode);Map<String, String> queryMap = getParams(decode);String groupId = MapUtil.getStr(queryMap, "groupId", null);String username = MapUtil.getStr(queryMap, "username", null);if (StrUtil.isNotBlank(groupId) && StrUtil.isNotBlank(username)) {NettyUtil.setAttr(ctx.channel(), NettyUtil.G_U, groupId.concat(",").concat(username));}//去掉参数 ===>  ws://localhost:8080/n/wsrequest.setUri(request.uri().substring(0,request.uri().indexOf("?")));ctx.pipeline().remove(this);ctx.fireChannelRead(request);}else{ctx.fireChannelRead(msg);}}/*** 解析 queryString* @param uri* @return*/public static Map<String, String> getParams(String uri) {Map<String, String> params = new HashMap<>(10);int idx = uri.indexOf("?");if (idx != -1) {String[] paramsArr = uri.substring(idx + 1).split("&");for (String param : paramsArr) {idx = param.indexOf("=");params.put(param.substring(0, idx), param.substring(idx + 1));}}return params;}
}
SimpleWsHandler

处理消息

@Slf4j
@ChannelHandler.Sharable
public class SimpleWsHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {@Autowiredprivate PushService pushService;/*** 在新的 Channel 被添加到 ChannelPipeline 中时被调用。这通常发生在连接建立时,即 Channel 已经被成功绑定并注册到 EventLoop 中。* 在连接建立时被调用一次** @param ctx* @throws Exception*/@Overridepublic void handlerAdded(ChannelHandlerContext ctx) throws Exception {NettySimpleSession session = NettyUtil.getSession(ctx.channel());if (session == null) {log.info("handlerAdded channel id: {}", ctx.channel().id());} else {log.info("handlerAdded channel group-username: {}-{}", session.group(), session.identity());}}/*** 连接断开时,Netty 会自动触发 channelInactive 事件,并将该事件交给事件处理器进行处理* 在 channelInactive 事件的处理过程中,会调用 handlerRemoved 方法** @param ctx* @throws Exception*/@Overridepublic void handlerRemoved(ChannelHandlerContext ctx) throws Exception {NettySimpleSession session = NettyUtil.getSession(ctx.channel());if (session!=null){log.info("handlerRemoved channel group-username: {}-{}", session.group(), session.identity());}offline(ctx.channel());}@Overrideprotected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {//todo msg 可以是json字符串,这里仅仅只是纯文本NettySimpleSession session = NettyUtil.getSession(ctx.channel());if (session!=null){MessageDto messageDto = new MessageDto();messageDto.setSessionId(session.getId());messageDto.setGroup(session.group());messageDto.setFromUser(session.identity());messageDto.setContent(msg.text());pushService.pushGroupMessage(messageDto);}else {log.info("channelRead0 session is null channel id: {}-{}", ctx.channel().id(),msg.text());}}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {log.info("SimpleWsHandler 客户端异常断开 {}", cause.getMessage());//todo offlineoffline(ctx.channel());}@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {if (evt instanceof IdleStateEvent idleStateEvent) {if (idleStateEvent.state().equals(IdleStateEvent.READER_IDLE_STATE_EVENT)) {log.info("SimpleWsIdleHandler channelIdle 5 秒未收到客户端消息,强制关闭: {}", ctx.channel().id());//todo offlineoffline(ctx.channel());}} else if (evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) {String attr = NettyUtil.getAttr(ctx.channel(), NettyUtil.G_U);if (StrUtil.isBlank(attr)) {ctx.writeAndFlush("参数异常");offline(ctx.channel());} else {//todo 可以做用户认证等等//记录用户登陆sessionNettySimpleSession session = NettyUtil.getSession(ctx.channel());Assert.notNull(session, "session 不能为空");SessionRegistry.getInstance().addSession(session);}}super.userEventTriggered(ctx,evt);}/*** 用户下线,处理失效 session* @param channel*/public void offline(Channel channel){NettySimpleSession session = NettyUtil.getSession(channel);if (session!=null){SessionRegistry.getInstance().removeSession(session);}channel.close();}}

PushService

推送服务抽取

public interface PushService {/*** 组推送* @param messageDto*/void pushGroupMessage(MessageDto messageDto);}@Service
public class PushServiceImpl implements PushService {@Autowiredprivate MessageClient messagingClient;@Overridepublic void pushGroupMessage(MessageDto messageDto) {messagingClient.sendMessage(messageDto);}
}

NettySimpleSession

netty session 封装

public class NettySimpleSession extends AbstractWsSession {private Channel channel;public NettySimpleSession(String id, String group, String identity, Channel channel) {super(id, group, identity);this.channel = channel;}@Overridepublic void sendTextMessage(MessageDto messageDto) {String content = messageDto.getFromUser() + " say: " + messageDto.getContent();// 不能直接 write content, channel.writeAndFlush(content);// 要封装成 websocketFrame,不然不能编解码!!!channel.writeAndFlush(new TextWebSocketFrame(content));}
}

启动类

@Slf4j
@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}@Beanpublic SimpleWsHandler simpleWsHandler(){return new SimpleWsHandler();}@PostConstructpublic void init() {new Thread(() -> {log.info(">>>>>>>> start netty ws server....");try {new SimpleNettyWebsocketServer(simpleWsHandler()).start(8881);} catch (InterruptedException e) {log.info(">>>>>>>> SimpleNettyWebsocketServer start error", e);}}).start();}}

其他代码参考 spring boot 实现直播聊天室

测试

websocket 地址 ws://127.0.0.1:8881/n/ws?groupId=1&username=tom

在这里插入图片描述

good luck!

相关文章:

spring boot 实现直播聊天室(二)

spring boot 实现直播聊天室(二) 技术方案: spring bootnettyrabbitmq 目录结构 引入依赖 <dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.96.Final</version> </dependency>Si…...

alibaba fastjson GET List传参 和 接收解析

之前一直都是 get传的都是单字符串&#xff08;例如 xxxxxxxxx?name{name};name“woaini”;&#xff09;&#xff0c;并没有传list的. GET List传参 问题场景 String url"xxxxxxxx?id{id}"; HashMap<String,Object> param new HashMap<>(); param.pu…...

API自动化测试是什么?我们该如何做API自动化测试呢?

API测试已经成为测试工作中的常规任务之一。为了提高测试效率并减少重复的手工操作&#xff0c;API自动化测试变得越来越重要。本文总结了API自动化测试方面的经验和心得&#xff0c;旨在与读者分享。 掌握自动化技能已经成为高级测试工程师的必备技能。敏捷和持续测试改变了传…...

PyTorch 的 10 条内部用法

欢迎阅读这份有关 PyTorch 原理的简明指南[1]。无论您是初学者还是有一定经验&#xff0c;了解这些原则都可以让您的旅程更加顺利。让我们开始吧&#xff01; 1. 张量&#xff1a;构建模块 PyTorch 中的张量是多维数组。它们与 NumPy 的 ndarray 类似&#xff0c;但可以在 GPU …...

Django、Echarts异步请求、动态更新

前端页面 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>echarts示例</title> <script src"jquery.min.js"></script><script type "text/javascript" src "echarts.m…...

Mac部署Odoo环境-Odoo本地环境部署

Odoo本地环境部署 安装Python安装Homebrew安装依赖brew install libxmlsec1 Python运行环境Pycharm示例配置 Mac部署Odoo环境-Odoo本地环境部署 安装Python 新机&#xff0c;若系统没有预装Python&#xff0c;则安装需要版本的Python 点击查询Python官网下载 安装Homebrew 一…...

【✅面试编程题:如何用队列实现一个栈】

✅面试编程题&#xff1a;如何用队列实现一个栈 &#x1f4a1;典型回答 &#x1f4a1;典型回答 使用两个队列可以实现一个栈&#xff0c;一个队列用来存储栈中的元素&#xff0c;另一个队列用来在pop操作时暂存元素。 上才艺&#xff1a; import java.util.LinkedList; impo…...

Windows本地的RabbitMQ服务怎么在Docker for Windows的容器中使用

1. 进入管理界面 windows安装过程请访问&#xff1a;Windows安装RabbitMQ、添加PHP的AMQP扩展 浏览器访问&#xff1a;http://127.0.0.1:15672/ 2. 创建虚拟主机 上面访问的是 RabbitMQ 的管理界面&#xff0c;可以在这个界面上进行一些操作&#xff0c;比如创建虚拟主机、…...

YOLOv5改进 | 2023卷积篇 | AKConv轻量级架构下的高效检测(既轻量又提点)

一、本文介绍 本文给大家带来的改进内容是AKConv是一种创新的变核卷积&#xff0c;它旨在解决标准卷积操作中的固有缺陷&#xff08;采样形状是固定的&#xff09;&#xff0c;AKConv的核心思想在于它为卷积核提供了任意数量的参数和任意采样形状&#xff0c;能够使用任意数量…...

微信小程序:模态框(弹窗)的实现

效果 wxml <!--新增&#xff08;点击按钮&#xff09;--> <image classimg src"{{add}}" bindtapadd_mode></image> <!-- 弹窗 --> <view class"modal" wx:if"{{showModal}}"><view class"modal-conten…...

uniapp交互反馈api的使用示例

官方文档链接&#xff1a;uni.showToast(OBJECT) | uni-app官网 1.uni.showToast({}) 显示消息提示框。 常用属性&#xff1a; title:页面提示的内容 image&#xff1a;改变提示框默认的icon图标 duration&#xff1a;提示框在页面显示多少秒才让它消失 添加了image属性后。 注…...

XUbuntu22.04之HDMI显示器设置竖屏(一百九十八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…...

如何用 Cargo 管理 Rust 工程系列 甲

以下内容为本人的学习笔记&#xff0c;如需要转载&#xff0c;请声明原文链接 微信公众号「ENG八戒」https://mp.weixin.qq.com/s/ceMTUzRjDoiLwjn_KfZSrg 这几年 Rust 可谓是炙手可热的新兴编程语言了&#xff0c;而且被投票为最受程序员喜爱的语言。它很现代&#xff0c;专门…...

Windows下ping IP+端口的方法

有两种方法&#xff1a; 1. windows 开通 telnet 参考&#xff1a; https://zhuanlan.zhihu.com/p/570982111 2. 安装插件 参考&#xff1a;Windows下ping IP端口的方法 推荐使用第二种。...

【python】os.getcwd()函数详解和示例

os.getcwd() 是 Python 的一个内建函数&#xff0c;用于获取当前工作目录的路径。这个函数属于 os 模块&#xff0c;需要导入这个模块才能使用它。 import os data_rootos.path.abspath(os.path.join(os.getcwd(),"../.."))# get data root path data_root1os.path.…...

Linux(二十一)——virtualenv安装成功之后,依然提示未找到命令(-bash: virtualenv: 未找到命令)

Linux(二十一)——virtualenv安装成功之后&#xff0c;依然提示未找到命令&#xff08;-bash: virtualenv: 未找到命令&#xff09; 解决办法&#xff1a; 创建软连接 ln -s /usr/local/python3/bin/virtualenv /usr/bin/virtualenv...

RNN介绍及Pytorch源码解析

介绍一下RNN模型的结构以及源码&#xff0c;用作自己复习的材料。 RNN模型所对应的源码在&#xff1a;\PyTorch\Lib\site-packages\torch\nn\modules\RNN.py文件中。 RNN的模型图如下&#xff1a; 源码注释中写道&#xff0c;RNN的数学公式&#xff1a; 表示在时刻的隐藏状态…...

Qt 文字描边(基础篇)

项目中有时需要文字描边的功能 1.基础的绘制文字 使用drawtext处理 void MainWindow::paintEvent(QPaintEvent *event) {QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing, true);painter.setRenderHint(QPainter::SmoothPixmapTransform, true);painte…...

.360勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复

导言&#xff1a; 在数字化时代&#xff0c;.360勒索病毒如影随形&#xff0c;威胁个人和组织的数据安全。本文将深入介绍.360病毒的特征、威胁&#xff0c;以及如何有效地恢复被加密的数据文件&#xff0c;同时提供预防措施&#xff0c;助您更好地保护数字资产。如不幸感染这…...

Nginx(四层+七层代理)+Tomcat实现负载均衡、动静分离

一、Tomcat多实例部署 具体步骤请看我之前的博客 写文章-CSDN创作中心https://mp.csdn.net/mp_blog/creation/editor/134956765?spm1001.2014.3001.9457 1.1 访问测试多实例的部署 1.2 分别在三个tomcat服务上部署jsp的动态页面 mkdir /usr/local/tomcat/webapps/test vim …...

【前端】vscode 相关插件

一 插件&#xff1a; 01、ESLint 用来识别并检查ECMAScript/JavaScript 代码的工具 02、Prettier 用来格式化代码&#xff0c;如.js、.vue、css等都可以进行格式化 03、Vetur 用来识别并高亮vue语法 04、EditorConfig 用来设置vscode的编程行为 二、安装依赖 01、…...

【MySQL】MySQL库的增删查改

文章目录 1.库的操作1.1创建数据库1.2创建数据库案例 2.字符集和校验规则2.1查看系统默认字符集以及校验规则2.2查看数据库支持的字符集2.3查看数据库支持的字符集校验规则2.4校验规则对数据库的影响 3.操纵数据库3.1查看数据库3.2显示创建语句3.3修改数据库3.4数据库删除3.5备…...

基于基于深度学习的表情识别人脸打分系统

1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 研究背景与意义 随着人工智能技术的快速发展&#xff0c;深度学习在计算机视觉领域取得了巨大的突破。表情识别是计算机视觉领域的一个重要研究方向&#xff0c;它可以通过分析人…...

Linux|操作系统|Error: Could not create the Java Virtual Machine 报错的解决思路

现在都流行kubernetes这样的云原生了&#xff0c;因此&#xff0c;很多Java微服务也都集成到类似kubernetes这样的环境下了&#xff0c;毫无疑问的&#xff0c;kubernetes会省去很多环境问题&#xff0c;而最近在部署一个二进制Java项目的时候&#xff0c;遇到了Error: Could n…...

K8S学习指南-minikube的安装

简介 Minikube 是一个用于在本地开发环境中运行 Kubernetes 集群的工具。它允许开发人员在单个节点上体验 Kubernetes&#xff0c;无需配置复杂的生产环境。本指南将详细介绍在 Windows、CentOS 和 Ubuntu 系统上安装 Minikube 的步骤。 1. Windows 系统安装 1.1 &#xff1…...

恒创科技:有哪些免费的CDN加速服务

CDN加速技术已经成为提升网站性能和用户体验的重要手段之一。许多网站都使用CDN来加速内容传输&#xff0c;提高网站的响应速度和可用性。然而&#xff0c;对于许多小型企业和个人网站来说&#xff0c;使用CDN服务需要支付一定的费用。那么&#xff0c;有没有免费的CDN加速服务…...

Kibana搜索数据利器:KQL与Lucene

文章目录 一、搜索数据二、KQL查询1、字段搜索2、逻辑运算符3、通配符4、存在性检查5、括号 三、Lucene查询1、字段搜索2、逻辑运算符3、通配符4、范围搜索5、存在性检查6、括号 四、总结 一、搜索数据 默认情况下&#xff0c;您可以使用 Kibana 的标准查询语言&#xff0c;该…...

float32、int8、uint8、int32、uint32之间的区别

float32、int8、uint8、int32、uint32这些类型在数据表示范围、精度和存储大小等方面存在明显的差异。 float32&#xff1a;是一种单精度浮点数&#xff0c;占32位&#xff08;也就是4个字节&#xff09;&#xff0c;可以提供约7位有效数字的精度。这种数据类型通常用于需要高…...

百度搜索展现服务重构:进步与优化

作者 | 瞭东 导读 本文将简单介绍搜索展现服务发展过程&#xff0c;以及当前其面临的三大挑战&#xff1a;研发难度高、架构能力欠缺、可复用性低&#xff0c;最后提出核心解决思路和具体落地方案&#xff0c;期望大家能有所收货和借鉴。 全文4736字&#xff0c;预计阅读时间12…...

icmp协议、ip数据包 基础

icmp协议、ip数据包 ICMP 协议 1 定义与用途&#xff1a; ICMP&#xff08;Internet Control Message Protocol&#xff09;定义&#xff1a; ICMP 是 Internet Control Message Protocol&#xff08;互联网控制消息协议&#xff09;的缩写。它是 TCP/IP 网络模型中的一个核…...