In the last lesson, I completed the back-end construction of netty and completed the simple http request response. Today, I will complete the group chat function with the front-end websocket. If you don't want to talk much, let's start with the picture above:
Front-end construction
- Do not use complex build tools to start static pages directly
zui style library used http://zui.sexy/?#/ , very good, there are many templates. I used the chat Template Transformation
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/zui/1.8.1/css/zui.min.css"> <link rel="stylesheet" href="zui-theme.css">
- Main part
<div class="container"> <h1>mike Multi person chat room, waiting for you to chat</h1> <div class="comments"> <section class="comments-list" id="chatlist"> <div class="comment"> <a href="###" class="avatar"> <i class="icon-user icon-2x"></i> </a> <div class="content"> <div><strong>Someone else</strong></div> <div class="text">Other people's chat content</div> </div> </div> <div class="comment"> <a href="###" class="avatar pull-right"> <i class="icon-user icon-2x"></i> </a> <div class="content pull-right"> <div><strong>I</strong></div> <div class="text">What I'm talking about</div> </div> </div> </section> <footer> <div class="reply-form" id="commentReplyForm1"> <form class="form"> <div class="form-group"> <div class="input-control has-label-left"> <input id="userName" type="text" class="form-control" placeholder=""> <label for="inputAccountExample2" class="input-control-label-left">Nickname?:</label> </div> </div> </form> <a href="###" class="avatar"><i class="icon-user icon-2x"></i></a> <form class="form"> <div class="form-group"> <textarea id="inputMsg" class="form-control new-comment-text" rows="2" value="" placeholder="Start chatting... input enter send message"></textarea> </div> </form> </div> </footer> </div> </div>
- Introduce dependency js
<!-- ZUI Javascript rely on jQuery --> <script src="https://cdnjs.cloudflare.com/ajax/libs/zui/1.8.1/lib/jquery/jquery.js"></script> <!-- ZUI Standard Version compressed JavaScript file --> <script src="https://cdnjs.cloudflare.com/ajax/libs/zui/1.8.1/js/zui.min.js"></script>
- js code and business code of websocket
<script type="text/javascript"> window.CHAT = { me: "", WS:{}, init: function () { if (window.WebSocket) { this.WS = new WebSocket("ws://A156B7L58CCNY4B:8090/ws"); this.WS.onmessage = function(event) { var data = event.data; console.log("Data received:" + data); //Show other people's chat messages console.log(CHAT.me); console.log(data.split(":")[0]); if(CHAT.me != data.split(":")[0]) { appendOtherchat(data); } }, this.WS.onclose = function(event) { console.log("Connection closure"); }, this.WS.onopen = function(evt) { console.log("Connection open ..."); }, this.WS.onerror = function(event) { console.log("connection failed...."); } } else { alert("Chat is not supported in your browser. Please change your browser"); } }, chat:function (msg) { this.WS.send(msg); } } CHAT.init(); function Trim(str) { return str.replace(/(^\s*)|(\s*$)/g, ""); } function appendMy (msg) { //Splicing your own chat content document.getElementById('chatlist').innerHTML+="<div class='comment'><a class='avatar pull-right'><i class='icon-user icon-2x'></i></a><div class='content pull-right'><div><strong>I</strong></div><div class='text'>"+msg+"</div></div></div>"; } function appendOtherchat(msg) { //Splicing other people's chat information to chat room var msgs = msg.split(":"); document.getElementById('chatlist').innerHTML+="<div class='comment'><a class='avatar'><i class='icon-user icon-2x'></i></a><div class='content'><div><strong>"+msgs[0]+"</strong></div><div class='text'>"+msgs[1]+"</div></div></div>"; } document.getElementById('inputMsg').addEventListener('keyup', function(event) { if (event.keyCode == "13") { //Enter to query var inputMsg = document.getElementById('inputMsg').value; if (inputMsg == null || Trim(inputMsg) == "" ) { alert("Please enter a chat message"); } else { var userName = document.getElementById('userName').value; if (userName == null || userName == '') { alert("Please enter a chat nickname"); } else { //Send message definition message format user name: [message] CHAT.chat(userName+":"+inputMsg); //Record my nickname CHAT.me = userName; appendMy(inputMsg); //Clear input after sending document.getElementById('inputMsg').focus(); document.getElementById('inputMsg').value=""; } } } }); </script>
If you have comments, you can't explain them
Back end service transformation
- ChatHandler transformation, judge websocket response
/** * Read the message sent by the client and forward it to the Channel of other clients. */ @Override protected void channelRead0(ChannelHandlerContext ctx, Object request) throws Exception { if (request instanceof FullHttpRequest) { //It's an http request FullHttpResponse response = new DefaultFullHttpResponse( HttpVersion.HTTP_1_1,HttpResponseStatus.OK , Unpooled.wrappedBuffer("Hello netty" .getBytes())); response.headers().set("Content-Type", "text/plain"); response.headers().set("Content-Length", response.content().readableBytes()); response.headers().set("connection", HttpHeaderValues.KEEP_ALIVE); ctx.channel().writeAndFlush(response); } else if (request instanceof TextWebSocketFrame) { // websocket request String userId = ctx.channel().id().asLongText(); System.out.println("Client received"+userId+":"+((TextWebSocketFrame)request).text()); //Send message to all clients channels.writeAndFlush(new TextWebSocketFrame(((TextWebSocketFrame)request).text())); //Send to a single client //ctx.channel().writeAndFlush(new TextWebSocketFrame(((TextWebSocketFrame)request).text())); } }
*ChatServerInitializer transformation, adding WebSocket
@Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); //websocket protocol itself is based on http protocol, so we also need to use http to decode the encoder pipeline.addLast(new HttpServerCodec()); //A processor written in blocks pipeline.addLast(new ChunkedWriteHandler()); //netty is based on segmented request. HttpObjectAggregator is used to segment and re aggregate the request. The parameter is the maximum length of aggregate bytes pipeline.addLast(new HttpObjectAggregator(1024*1024*1024)); //ws://server:port/context_path //ws://localhost:9999/ws //Parameter refers to content [u path pipeline.addLast(new WebSocketServerProtocolHandler("/ws",null,true,65535)); //Custom handler pipeline.addLast(new ChatHandler()); System.out.println("ChatClient:"+ch.remoteAddress() +"Connection"); }
Transformation completed
Start the back-end service, visit your front-end static page and chat with your friends. In fact, the back-end group chat is very simple, that is, the input message of a user is returned to all online clients, and the front-end is responsible for filtering and displaying. Do it yourself and do it for 10 minutes.
Realization function
- Enter a chat nickname to start a chat
- Chat message can only be sent if it is not empty
- Automatically clear the input after sending, and focus the input box
- Own messages are displayed on the left, others on the right
Don't forget to pay attention to me mike wants to do everything
Please pay attention.