日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Java實戰之用springboot+netty實現簡單的一對一聊天

瀏覽:152日期:2022-08-13 16:05:31
一、引入pom

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd'> <modelVersion>4.0.0</modelVersion> <groupId>com.chat.info</groupId> <artifactId>chat-server</artifactId> <version>1.0-SNAPSHOT</version> <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.4.RELEASE</version><relativePath/> <!-- lookup parent from repository --> </parent> <properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><java.version>1.8</java.version> </properties> <dependencies><!-- web --><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.33.Final</version></dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId></dependency><!-- fastjson --><dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.56</version></dependency><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId></dependency> </dependencies> <build><plugins> <plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId> </plugin></plugins> </build></project>二、創建netty 服務端

package com.chat.server; import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.nio.NioServerSocketChannel;import lombok.extern.slf4j.Slf4j;import org.springframework.stereotype.Component; import javax.annotation.PostConstruct;import javax.annotation.PreDestroy; @Component@Slf4jpublic class ChatServer { private EventLoopGroup bossGroup; private EventLoopGroup workGroup; private void run() throws Exception {log.info('開始啟動聊天服務器');bossGroup = new NioEventLoopGroup(1);workGroup = new NioEventLoopGroup();try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup, workGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChatServerInitializer()); //啟動服務器 ChannelFuture channelFuture = serverBootstrap.bind(7000).sync(); log.info('開始啟動聊天服務器結束'); channelFuture.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workGroup.shutdownGracefully();} } /** * 初始化服務器 */ @PostConstruct() public void init() {new Thread(() -> { try {run(); } catch (Exception e) {e.printStackTrace(); }}).start(); } @PreDestroy public void destroy() throws InterruptedException {if (bossGroup != null) { bossGroup.shutdownGracefully().sync();}if (workGroup != null) { workGroup.shutdownGracefully().sync();} }}

package com.chat.server; import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelPipeline;import io.netty.channel.socket.SocketChannel;import io.netty.handler.codec.http.HttpObjectAggregator;import io.netty.handler.codec.http.HttpServerCodec;import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;import io.netty.handler.stream.ChunkedWriteHandler; public class ChatServerInitializer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel socketChannel) throws Exception {ChannelPipeline pipeline = socketChannel.pipeline();//使用http的編碼器和解碼器pipeline.addLast(new HttpServerCodec());//添加塊處理器pipeline.addLast(new ChunkedWriteHandler()); pipeline.addLast(new HttpObjectAggregator(8192)); pipeline.addLast(new WebSocketServerProtocolHandler('/chat'));//自定義handler,處理業務邏輯pipeline.addLast(new ChatServerHandler()); }}

package com.chat.server; import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.chat.config.ChatConfig;import io.netty.channel.Channel;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.SimpleChannelInboundHandler;import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;import io.netty.util.AttributeKey;import lombok.extern.slf4j.Slf4j; import java.time.LocalDateTime; @Slf4jpublic class ChatServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> { @Override protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception {//傳過來的是json字符串String text = textWebSocketFrame.text();JSONObject jsonObject = JSON.parseObject(text);//獲取到發送人的用戶idObject msg = jsonObject.get('msg');String userId = (String) jsonObject.get('userId');Channel channel = channelHandlerContext.channel();if (msg == null) { //說明是第一次登錄上來連接,還沒有開始進行聊天,將uid加到map里面 register(userId, channel);} else { //有消息了,開始聊天了 sendMsg(msg, userId);} } /** * 第一次登錄進來 * * @param userId * @param channel */ private void register(String userId, Channel channel) {if (!ChatConfig.concurrentHashMap.containsKey(userId)) { //沒有指定的userId ChatConfig.concurrentHashMap.put(userId, channel); // 將用戶ID作為自定義屬性加入到channel中,方便隨時channel中獲取用戶ID AttributeKey<String> key = AttributeKey.valueOf('userId'); channel.attr(key).setIfAbsent(userId);} } /** * 開發發送消息,進行聊天 * * @param msg * @param userId */ private void sendMsg(Object msg, String userId) {Channel channel1 = ChatConfig.concurrentHashMap.get(userId);if (channel1 != null) { channel1.writeAndFlush(new TextWebSocketFrame('服務器時間' + LocalDateTime.now() + ' ' + msg));} } /** * 一旦客戶端連接上來,該方法被執行 * * @param ctx * @throws Exception */ @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception {log.info('handlerAdded 被調用' + ctx.channel().id().asLongText()); } /** * 斷開連接,需要移除用戶 * * @param ctx * @throws Exception */ @Override public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {removeUserId(ctx); } /** * 移除用戶 * * @param ctx */ private void removeUserId(ChannelHandlerContext ctx) {Channel channel = ctx.channel();AttributeKey<String> key = AttributeKey.valueOf('userId');String userId = channel.attr(key).get();ChatConfig.concurrentHashMap.remove(userId);log.info('用戶下線,userId:{}', userId); } /** * 處理移除,關閉通道 * * @param ctx * @param cause * @throws Exception */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {ctx.close(); }}三、存儲用戶channel 的map

package com.chat.config; import io.netty.channel.Channel; import java.util.concurrent.ConcurrentHashMap; public class ChatConfig { public static ConcurrentHashMap<String, Channel> concurrentHashMap = new ConcurrentHashMap(); }四、客戶端html

<!DOCTYPE html><html lang='en' xmlns:th='http://www.thymeleaf.org'><head> <meta charset='UTF-8'> <title>Title</title> <script>var socket;//判斷當前瀏覽器是否支持websocketif (window.WebSocket) { //go on socket = new WebSocket('ws://localhost:7000/chat'); //相當于channelReado, ev 收到服務器端回送的消息 socket.onmessage = function (ev) {var rt = document.getElementById('responseText');rt.value = rt.value + 'n' + ev.data; } //相當于連接開啟(感知到連接開啟) socket.onopen = function (ev) {var rt = document.getElementById('responseText');rt.value = '連接開啟了..'var userId = document.getElementById('userId').value;var myObj = {userId: userId};var myJSON = JSON.stringify(myObj);socket.send(myJSON) } //相當于連接關閉(感知到連接關閉) socket.onclose = function (ev) {var rt = document.getElementById('responseText');rt.value = rt.value + 'n' + '連接關閉了..' }} else { alert('當前瀏覽器不支持websocket')} //發送消息到服務器function send(message) { if (!window.socket) { //先判斷socket是否創建好return; } if (socket.readyState == WebSocket.OPEN) {//通過socket 發送消息var sendId = document.getElementById('sendId').value;var myObj = {userId: sendId, msg: message};var messageJson = JSON.stringify(myObj);socket.send(messageJson) } else {alert('連接沒有開啟'); }} </script></head><body><h1 th:text='${userId}'></h1><input type='hidden' th:value='${userId}' id='userId'><input type='hidden' th:value='${sendId}' id='sendId'><form onsubmit='return false'> <textarea name='message' style='height: 300px; width: 300px'></textarea> <input type='button' value='發送' onclick='send(this.form.message.value)'> <textarea style='height: 300px; width: 300px'></textarea> <input type='button' value='清空內容' onclick='document.getElementById(’responseText’).value=’’'></form></body></html>五、controller 模擬用戶登錄以及要發送信息給誰

package com.chat.controller; import com.chat.config.ChatConfig;import io.netty.channel.Channel;import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestParam;@Controllerpublic class ChatController { @GetMapping('login') public String login(Model model, @RequestParam('userId') String userId, @RequestParam('sendId') String sendId) {model.addAttribute('userId', userId);model.addAttribute('sendId', sendId);return 'chat'; } @GetMapping('sendMsg') public String login(@RequestParam('sendId') String sendId) throws InterruptedException {while (true) { Channel channel = ChatConfig.concurrentHashMap.get(sendId); if (channel != null) {channel.writeAndFlush(new TextWebSocketFrame('test'));Thread.sleep(1000); }} } }六、測試

登錄成功要發消息給bbb

登錄成功要發消息給aaa

Java實戰之用springboot+netty實現簡單的一對一聊天

Java實戰之用springboot+netty實現簡單的一對一聊天

到此這篇關于Java實戰之用springboot+netty實現簡單的一對一聊天的文章就介紹到這了,更多相關springboot+netty實現一對一聊天內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
日韩精品a在线观看91| 女同性一区二区三区人了人一| 亚洲成av在线| 免费视频一区三区| 久久高清国产| 国产探花一区| 欧美精品aa| 国产精品视频首页| 日韩成人亚洲| 日韩精品91| 国产亚洲精品自拍| 欧美在线91| 国产suv精品一区二区四区视频 | 日韩高清不卡| 日韩理论视频| 樱桃视频成人在线观看| 不卡中文一二三区| 亚洲天堂黄色| 日韩高清一区| 久久av日韩| 狠狠躁少妇一区二区三区| 亚洲www啪成人一区二区| 蜜臀91精品一区二区三区| 99视频精品| 亚洲精品国产精品粉嫩| 国产精品66| 国产精品99一区二区| 蜜桃久久av一区| 老鸭窝一区二区久久精品| 五月天av在线| 国产精品社区| 麻豆精品蜜桃视频网站| 精品国产一区二区三区噜噜噜| 欧美在线观看视频一区| 久久国内精品自在自线400部| 成人午夜亚洲| 日本在线观看不卡视频| 久久精品国产www456c0m| 国产精品夜夜夜| 亚洲欧洲一区| 日韩一区电影| 国产精品va视频| 视频一区欧美精品| 99久久婷婷| 国产福利资源一区| 蜜臀国产一区二区三区在线播放| 精品理论电影在线| 亚洲免费网址| 中文字幕人成乱码在线观看| 久久国产欧美日韩精品| 六月婷婷一区| 中文一区一区三区高中清不卡免费| 日韩在线a电影| 欧美a级一区| 最近高清中文在线字幕在线观看1| 国产欧美另类| 国产欧美自拍| 欧美一区自拍| 五月天激情综合网| 蜜桃精品在线| 日韩网站中文字幕| 精品久久一区| 日韩不卡在线观看日韩不卡视频| 亚洲网站视频| 国产91在线播放精品| 国际精品欧美精品| 国产精品99久久精品| 精品国产欧美日韩| 亚洲天堂av影院| 韩国精品主播一区二区在线观看 | 日韩和欧美一区二区| 亚洲大片在线| 国产精成人品2018| 国产欧美一区二区精品久久久| 日韩精品视频网| 国产日韩欧美三级| 国产第一亚洲| 国产真实久久| 中文一区一区三区免费在线观 | 国产欧美大片| 精品国产精品国产偷麻豆| 久久亚洲资源中文字| 成人日韩av| 亚洲精品**中文毛片| 亚洲欧洲另类| 国产精品v日韩精品v欧美精品网站| 精品久久91| av中文资源在线资源免费观看| 国产精品字幕| 日韩中文字幕亚洲一区二区va在线| 免费日韩一区二区| 欧美a一区二区| 久久激情中文| 水野朝阳av一区二区三区| 日韩精品一级| 精品捆绑调教一区二区三区| 国产一区二区三区网| 亚洲女同中文字幕| 亚洲一区二区动漫| 精品一区二区三区亚洲| 最近高清中文在线字幕在线观看1| 国内激情久久| 日韩一区中文| 超级白嫩亚洲国产第一| 久久夜色精品| 日韩欧美不卡| 国产精品久久亚洲不卡| 黄色亚洲免费| 中文字幕在线官网| 欧美日韩91| 日韩中文字幕亚洲一区二区va在线 | 激情丁香综合| 国产日韩在线观看视频| 日韩电影免费网址| 免费一级片91| 98精品久久久久久久| 亚洲欧美网站在线观看| 久久精品毛片| 中文字幕日韩亚洲| 国产精品成人a在线观看| 日本午夜精品一区二区三区电影 | 黄色欧美在线| 亚洲欧美日韩国产| 国产成人精品999在线观看| 蜜臀av一区二区在线免费观看| 日本免费一区二区三区四区| 亚洲青青久久| 国产亚洲精品自拍| 亚洲黄色免费看| 久久久久久久久丰满| 日韩国产一区二区三区| 香蕉久久99| 九一成人免费视频| 国产精品视区| 日韩专区欧美专区| 日本精品一区二区三区在线观看视频| 噜噜噜久久亚洲精品国产品小说| 日韩在线精品| 狠狠色狠狠色综合日日tαg| 久久亚洲不卡| 欧美国产另类| 国产网站在线| 国产亚洲在线观看| 亚洲综合三区| 国产日产高清欧美一区二区三区 | 亚洲精品裸体| 国产精品手机在线播放| 麻豆精品视频在线观看| 日本黄色精品| a国产在线视频| 久久精品影视| 亚洲欧美成人综合| 日韩精品三级| 精品女同一区二区三区在线观看| 91亚洲自偷观看高清| 黄色亚洲大片免费在线观看| 在线视频亚洲欧美中文| 久久99精品久久久野外观看| 成人国产精选| 美女黄网久久| 久久中文字幕一区二区三区| 欧美中文字幕一区二区| 日本不卡视频在线| 欧美好骚综合网| 亚洲专区在线| 麻豆精品新av中文字幕| 黄色在线一区| 欧美日韩网址| 亚洲高清二区| 久久精品国产一区二区| 欧美日韩国产精品一区二区亚洲| 国产日韩高清一区二区三区在线| 国产精品亚洲一区二区三区在线观看| 黄色精品网站| 日韩国产一区二区| 欧美一级久久| 日韩中文视频| 国产日韩欧美一区二区三区| 国产精品毛片在线看| 国产精品xxx在线观看| 99国产精品久久久久久久成人热| 亚洲日本国产| 日韩和的一区二在线| 麻豆精品国产91久久久久久| 久久免费大视频| 高清精品久久| 美女性感视频久久| 亚洲精品高潮| 丝袜美腿一区二区三区| 国产高潮在线| 老司机免费视频一区二区| 石原莉奈一区二区三区在线观看| 成人在线视频免费看| 日韩和欧美一区二区三区| 精品日韩视频| 久久精品国产99国产精品| 国产探花在线精品| 亚洲欧美专区| 免费日韩av片| 欧美另类专区|