首页 > 编程语言 >通过Java-Netty实现一个简单的HTML实时聊天——demo

通过Java-Netty实现一个简单的HTML实时聊天——demo

时间:2023-11-29 16:13:25浏览次数:41  
标签:netty ch Java Netty demo io new import channel

demo效果

初步准备

想要实现聊天就需要用到WebSocket,他是专门用于http进行实时聊天的的协议。因为主要核心在后端开发,所以我去白嫖了个超级简单的界面(就是不会!)

我编写demo时系统环境为Win-11,Java-8

环境依赖

只需要一个netty即可实现需要的功能

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

其余依赖

如果你是一点不会可能会有几个函数会出现问题,那我也贴出来

<!--日志-->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
</dependency>
<!--lombok-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<!--工具包-->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.20</version>
</dependency>

前端代码

就是一个简单的发送消息然后显示返回消息的界面,然后通过websocket来发送和接收,没有其他任何元素。

<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<head>
    <title>实时聊天</title>
</head>
<body>
<div id="chat">
    <div id="messages"></div>
    <input type="text" id="messageInput" placeholder="输入消息...">
    <button onclick="sendMessage()">发送</button>
</div>
<script>
    let ws;
    function connect() {
        //你的websocket
        ws = new WebSocket('ws://localhost:32001/daimouren');

        ws.onmessage = function(event) {
            let message = event.data;
            document.getElementById('messages').innerHTML += '<div>' + message + '</div>';
        };

        ws.onerror = function(event) {
            console.error("WebSocket error observed:", event);
        };
    }

    function sendMessage() {
        let message = document.getElementById('messageInput').value;
        ws.send(message);
        document.getElementById('messageInput').value = '';
    }

    window.onload = connect;
</script>
</body>
</html>

后端代码

后端代码也是非常简单,Netty已经对websocket实现进行了封装。此处就是简单的一个实现对应的功能的demo。核心的逻辑就是这些,之后改协议,绑定数据库等操作我就懒得写了。主要就是demo

package com.daimouren.netty.communicate;

import ch.qos.logback.core.util.TimeUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.HttpUtil;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.*;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

/**
 * HTTP页面实时交流功能(服务端)
 * @author daimouren
 * @since 2023/11/29
 */
@Slf4j
public class CommunicateServerDemo {

    private static final List<Channel> CONNECT_LIST = new ArrayList<>();

    public static void main(String[] args) {
        ServerBootstrap server = new ServerBootstrap();
        NioEventLoopGroup group = new NioEventLoopGroup();
        NioEventLoopGroup event = new NioEventLoopGroup();
        server.group(group,event); //监听事件处理
        server.channel(NioServerSocketChannel.class);
        server.childHandler(new ChannelInitializer<NioSocketChannel>() {
            @Override
            protected void initChannel(NioSocketChannel ch) {
                //打印的日志
                ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO));
                //http协议处理器
                ch.pipeline().addLast(new HttpServerCodec());
                //半包黏包处理器,这个处理器专门用于http非常适合。请求为最大请求长度
                ch.pipeline().addLast(new HttpObjectAggregator(65536));
                //websocket的处理器。参数为请求路径
                ch.pipeline().addLast(new WebSocketServerProtocolHandler("/daimouren"));
                //websocket核心逻辑处理器
                ch.pipeline().addLast(new SimpleChannelInboundHandler<TextWebSocketFrame>() {
                    @Override
                    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
                        //接收消息
                        String text = msg.text();
                        //创建发送消息体
                        TextWebSocketFrame backText = new TextWebSocketFrame((text));
                        //发送消息给除了自己的所有人
                        CONNECT_LIST.forEach(channel -> {
                            if (channel != ctx.channel()){
                                //发送消息
                                channel.writeAndFlush(backText);
                            }
                        });
                    }

                    @Override
                    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
                        //将连接添加到数组
                        CONNECT_LIST.add(ctx.channel());
                    }

                    @Override
                    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
                        //将连接提出数组
                        CONNECT_LIST.remove(ctx.channel());
                    }
                });
            }
        });
        try {
            # 端口绑定
            Channel channel = server.bind(32001).sync().channel();
            channel.closeFuture().sync();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            group.shutdownGracefully();
            event.shutdownGracefully();
        }
    }
}

标签:netty,ch,Java,Netty,demo,io,new,import,channel
From: https://www.cnblogs.com/daimourentop/p/17865097.html

相关文章

  • 使用javascript求最小生成树
    在JavaScript中,求取最小生成树(Minimum Spanning Tree, MST)最常用的算法是Prim算法和Kruskal算法。这里我将提供一个基于Kruskal算法的JavaScript实现。首先,定义一个用于存储图的数据结构,这里使用JavaScript的类来实现:class Graph {      constructor(vertices) {   ......
  • Spring Boot 2 正式停止维护。。再见了,Java 8!!
    大家好,我是栈长。没错,就在昨天,SpringBoot2.x停止维护了。。SpringBoot最后一个2.x的版本2.7.x已经停止维护,3.0.x也停止维护了,商业支持的版本也只有2.6.x了,2.5.x以下的版本彻底退出历史舞台。。从路线图可以看到每个版本的终止时间,包括最新的SpringBoot3.2.0,也......
  • 阿里巴巴Java开发手册中的DO、DTO、BO、AO、VO、POJO定义
    常用文件夹分层pojovo:与前端交互的所有对象,包括接参和返回query:查询的筛选条件,前端传参和后端内部传参通用dto:后端内部传参专用分层缘由分层领域模型规约:DO:数据对象,与数据库看表结构对应。DTO:数据传输对象,业务层向外传输对象BO:业务对象,由业务层输出的业务逻......
  • jmeter发送java请求
    本文描述jmeter如何发送java请求1.编写java请求,将加密、签名等封装,对外只暴露需要传的业务参数,jemter发送java请求时直接传入业务参数即可添加依赖:12345<dependency>    <groupId>org.apache.jmeter</groupId>    <artifactId>ApacheJMeter_java</art......
  • JAVA生产解析DXF;DXF-LIB
    DXF-LIBDXF解析参考资料:DXF格式-中文参考手册项目地址GitHUB地址GitEE地址DXF文件解析组件这是一个可以解析dxf文件的jar包,目前支持解析的图形有点、圆、直线、ARC弧线、多线段、单行文本、多行文本、图元将其解析为几何数据和点线数据,存储在DxfResolverImpl的baseStru......
  • 使用 Charles 抓取 Java 应用内 HTTP/HTTPS 请求
    代码设置OkHttpClientclient=newOkHttpClient();System.setProperty("http.proxyHost","127.0.0.1");System.setProperty("https.proxyHost","127.0.0.1");System.setProperty("http.proxyPort"......
  • JavaScript高级程序设计的代理与捕获——工作中的实际意义。
    js红宝书写得很好,很多东西都给你一一解释了,但是有一点我很想吐槽:没有在写代码例子之前说明,相关东西有啥用,在实际工作中有啥现实意义等等,导致很多人理解了概念和看懂了枯燥的代码段后却无法有效运用到自己的工作当中。因为你不知道拿来用到什么地方或者说什么情况下才去用它!举个我......
  • JavaScript编码风格指南
    sidebar:autosidebarDepth:4JavaScript编码风格指南内容出处:NicholasC.Zakas《编写可维护的JavaScript》GoogleJavaScriptStyleGuidecrockfordJSLintESLint好狗电影导航源文件基础命名文件名必须全部小写,并且可以包含下划线(_)或短划线(-),但不包含......
  • Java开发者的Python快速实战指南:探索向量数据库之文本搜索
    前言如果说Python是跟随我的步伐学习的话,我觉得我在日常开发方面已经没有太大的问题了。然而,由于我没有Python开发经验,我思考着应该写些什么内容。我回想起学习Java时的学习路线,直接操作数据库是其中一项重要内容,无论使用哪种编程语言,与数据库的交互都是不可避免的。然而,直接操作......
  • 《Effective Java》阅读笔记-第三章
    EffectiveJava阅读笔记第三章对于所有对象都通用的方法第10条重写equals时请遵守通用约定重写equals方法很简单,但是很容易出现错误,最直接避免这种错误的方式就是不重写equals,当出现任意一下情况的时候,就不需要重写equals:类的每个实例在逻辑上就是唯一的没比要......