Example of server push chat room based on TOMCAT7, Java and WebSocket _java

Source: Internet
Author: User
Tags extend json tomcat server

Objective

HTML5 WebSocket realizes the two-way communication between the server and the browser, the bidirectional communication makes the server message push development simpler, the most common is the instant communication and the high demand for the real-time information. Most of the previous server message tweets used "polling" and "long Connection" technologies, both of which have considerable overhead and are not particularly high in real time. WebSocket technology can only produce a small overhead and is particularly high in real time. Here's how to use websocket technology to develop chat rooms. In this instance, the TOMCAT7 server is used, each server is different for the websocket implementation, so this instance can only run on the Tomcat server, but now spring has introduced the WebSocket API, Can be compatible with the implementation of each server, you can access the relevant information to understand, here is not introduced, the following image is a chat room effect chart:

In this example, the realization of the real-time message push, but also realize the chat user's upper and lower line notice. Here's how to get started.

Background processing

TOMCAT implementation WebSocket mainly relies on the Org.apache.catalina.websocket.MessageInbound class, which is in the {tomcat_home}/lib/ Catalina.jar, so you need to introduce Catalina.jar and Tomcat-coyote.jar in your development, and the following code is the servlet that exposes the client's connection address:

 package Com.ibcio; 
Import Javax.servlet.annotation.WebServlet; 
 
Import Javax.servlet.http.HttpServletRequest; 
 
Import Org.apache.catalina.websocket.StreamInbound; @WebServlet (Urlpatterns = {"/message"})//If a request to receive a browser's ws://protocol must implement the Websocketservlet class Websocketmessageservlet extends Org.apache.catalina.websocket.WebSocketServlet {private static final long serialvers 
   
  Ionuid = 1L; 
   
  public static int online_user_count = 1; 
  Public String GetUser (HttpServletRequest request) {return (String) request.getsession (). getattribute ("user"); //Unlike the usual servlet, you need to implement Createwebsocketinbound, where you initialize the custom WebSocket Connection object @Override protected Streaminbound Createw Ebsocketinbound (String subprotocol,httpservletrequest request) {return new Websocketmessageinbound (This.getuser (req 
  uest)); } 
} 

This servlet is somewhat different from the normal servlet, inherits the Websocketservlet class, and overrides the Createwebsocketinbound method. The user attribute in the session in this class is set when the users enter the index.jsp, recording the nickname of the current user. Here is the code for your own implementation of the WebSocket connection object class Websocketmessageinbound class:

 Package Com.ibcio; 
Import java.io.IOException; 
Import Java.nio.ByteBuffer; 
 
Import Java.nio.CharBuffer; 
 
Import Net.sf.json.JSONObject; 
Import Org.apache.catalina.websocket.MessageInbound; 
 
Import Org.apache.catalina.websocket.WsOutbound; 
 
  public class Websocketmessageinbound extends Messageinbound {//current connected user name private final String user; 
  Public Websocketmessageinbound (String user) {this.user = user; 
  Public String GetUser () {return this.user; A triggered event that establishes a connection @Override protected void OnOpen (Wsoutbound outbound) {//Triggers connection event to add a connection to the connection pool Jsonobject 
    result = new Jsonobject (); 
    Result.element ("type", "User_join"); 
    Result.element ("User", This.user); 
     
    Push the message Websocketmessageinboundpool.sendmessage (Result.tostring ()) to all online users on the current user line; 
    result = new Jsonobject (); 
    Result.element ("type", "Get_online_user"); 
    Result.element ("List", Websocketmessageinboundpool.getonlineuser ()); To add the current connection object to a connection pool 
    Websocketmessageinboundpool.addmessageinbound (this); 
  Sends a list of current online users to the current connection Websocketmessageinboundpool.sendmessagetouser (This.user, result.tostring ()); @Override protected void onClose (int status) {//Trigger Shutdown event To remove connection in connection pool Websocketmessageinboundpool.removem 
    Essageinbound (this); 
    Jsonobject result = new Jsonobject (); 
    Result.element ("type", "User_leave"); 
    Result.element ("User", This.user); 
  Send the current user exit message to the online user websocketmessageinboundpool.sendmessage (result.tostring ()); @Override protected void Onbinarymessage (Bytebuffer message) throws IOException {throw new Unsupportedoper 
  Ationexception ("Binary Message not supported."); When the client sends a message to the server, it triggers an event @Override protected void Ontextmessage (Charbuffer message) throws IOException {//to all 
  Online users Send Message Websocketmessageinboundpool.sendmessage (message.tostring ()); 
 } 
}

The main implementation of the code in the OnOpen, OnClose, Ontextmessage methods, respectively, dealing with users online, offline, send messages. In this class there is a Websocketmessageinboundpool connection pool class, which is used to manage the connection of the user currently online, and the following is the code for this class:

Package Com.ibcio; 
Import java.io.IOException; 
Import Java.nio.CharBuffer; 
Import Java.util.HashMap; 
Import Java.util.Map; 
 
Import Java.util.Set;  public class Websocketmessageinboundpool {//Save connected MAP container private static final Map<string,websocketmessageinbound 
   
  > Connections = new hashmap<string,websocketmessageinbound> (); Add connection to connection pool public static void Addmessageinbound (Websocketmessageinbound inbound) {//Add Connection System.out.println ( 
    "User:" + inbound.getuser () + "Join ..."); 
  Connections.put (Inbound.getuser (), inbound); 
  //Get all online users public static set<string> Getonlineuser () {return connections.keyset (); public static void Removemessageinbound (Websocketmessageinbound inbound) {//removing connection System.out.println ("us 
    ER: "+ inbound.getuser () +" exit; "); 
  Connections.remove (Inbound.getuser ()); public static void Sendmessagetouser (String user,string message) {try {//Send to a specific userData System.out.println ("Send message to User: + user +", message content: "+ message"); 
      Websocketmessageinbound inbound = connections.get (user); 
      if (inbound!= null) {Inbound.getwsoutbound (). Writetextmessage (charbuffer.wrap (message)); 
    } catch (IOException e) {e.printstacktrace ();  }///Send message to all users public static void SendMessage (String message) {try {set<string> keyset = 
      Connections.keyset (); 
        for (String key:keyset) {Websocketmessageinbound inbound = Connections.get (key); 
          if (inbound!= null) {System.out.println ("send" to User: "+ key +", message content: "+ message); 
        Inbound.getwsoutbound (). Writetextmessage (charbuffer.wrap (message)); 
    A catch (IOException e) {e.printstacktrace ()); 
 } 
  } 
}

Front Show

The above code is the chat room backstage code, mainly consists of 3 objects, Servlet, connection object, connection pool, the following is the front of the code, the main front code is to connect with the server, display the user list and information list, the display of the foreground using the ext frame, Not familiar with Ext students can initially understand the next ext, the following is index.jsp code:

<%@ page language= "java" pageencoding= "UTF-8" import= "Com.ibcio.WebSocketMessageServlet"%> <% String user = 
  (String) Session.getattribute ("User"); 
    if (user = = null) {//generate Nickname user = "Visitor" + websocketmessageservlet.online_user_count; 
    Websocketmessageservlet.online_user_count + +; 
  Session.setattribute ("user", user); 
} pagecontext.setattribute ("User", user); %>  

The

page display is controlled primarily in websocket.js, and the following is WEBSOCKET.JSD code:

Used to show the user's chat information ext.define (' Messagecontainer ', {extend: ' Ext.view.View ', Trackover:true, MultiSelect: 
 
  False, Itemcls: ' L-im-message ', Itemselector: ' Div.l-im-message ', overitemcls: ' L-im-message-over ', 
 
  Selecteditemcls: ' l-im-message-selected ', style: {overflow: ' auto ', backgroundcolor: ' #fff '}, TPL: [' <div class= ' l-im-message-warn ' > chat please do not believe in remittances, winning information, strange phone calls. Please comply with relevant laws and regulations. </div> ', ' <tpl for= '. > ', ' <div class= ' l-im-message ' > ', ' <div class= ' l-im-message-header L-im-message-header-{source} '  
      >{from} {timestamp}</div> ', ' <div class= ' l-im-message-body ' >{content}</div> ', ' </div> ', 
    ' </tpl> ', messages: [], Initcomponent:function () {var me = this; Me.messagemodel = Ext.define (' Leetop.im.MessageModel ', {extend: ' Ext.data.Model ', fields: [' From ' 
   , ' timestamp ', ' content ', ' source ']     }); 
        Me.store = ext.create (' Ext.data.Store ', {model: ' Leetop.im.MessageModel ', data:me.messages 
    }); 
  Me.callparent (); 
    Receive:function (message) {var me = This is displayed in the page with the information pushed by the server 
    message[' timestamp '] = Ext.Date.format (new Date (message[' timestamp ')), ' h:i:s '); 
    if (Message.from = = user) {Message.source = ' self '; 
    }else{message.source = ' remote '; 
    } me.store.add (message); 
    if (me.el.dom) {me.el.dom.scrollTop = Me.el.dom.scrollHeight; 
 } 
  } 
});

This code is primarily a container for displaying messages, and the following is the code that starts after the page load completes:

  Ext.onready (function () {///create user input box var input = ext.create (' Ext.form.field.HtmlEditor ', {reg 
            Ion: ' South ', height:120, Enablefont:false, Enablesourceedit:false, Enablealignments:false, listeners: {initialize:function () {Ext.ev  Entmanager.on (Me.input.getDoc (), {keyup:function (e) {if (E.ctrlkey = = = 
                          True && E.keycode = {E.preventdefault (); 
                          E.stoppropagation (); 
                        Send (); 
              } 
                      } 
                    }); 
      } 
            } 
          }); 
 
      Create message display container var output = ext.create (' Messagecontainer ', {region: ' center '}); var dialog = ext.create (' Ext.panel.Panel ', {region:' Center ', layout: ' Border ', items: [Input, Output], buttons: [{ 
      Text: ' Send ', handler:send}]}; 
 
      var websocket; The initial speech websocket function Initwebsocket () {if (window). 
          WebSocket) {WebSocket = new WebSocket (encodeURI (' ws://localhost:8080/websocket/message ')); 
          Websocket.onopen = function () {//Connection succeeded Win.settitle (title + ' (connected) '); 
          } websocket.onerror = function () {//Connection failed Win.settitle (title + ' (connection occurred incorrectly) '); 
          } websocket.onclose = function () {//Connection disconnected Win.settitle (title + ' (disconnected) '); Websocket.onmessage = function (message) {var messages = Json.parse (mes 
            Sage.data); Receive messages sent by user if (Message.type = = ' message ') {Output.receive (message); else if (Message.type = = ' Get_online_user ') {//Get online user list var root = Onlineuser.getrootnode 
              (); 
                  Ext.each (message.list,function (user) {var node = Root.createnode ({id:user, 
                Text:user, Iconcls: ' User ', leaf:true}); 
              Root.appendchild (node); 
            }); 
                else if (Message.type = = ' User_join ') {//user online var root = Onlineuser.getrootnode (); 
                var user = Message.user; var node = Root.createnode ({id:user, text:user, iconcls: ' U 
                Ser ', leaf:true}); 
            Root.appendchild (node); else if (Message.type = = ' User_leave ') {//user offline var root = Onlineuser.getroOtnode (); 
                var user = Message.user; 
                var node = root.findchild (' id ', user); 
            Root.removechild (node); 
 
      } 
          } 
        } 
      }; Online user tree var onlineuser = ext.create (' Ext.tree.Panel ', {title: ' Online user ', Rootvisible:fal 
            SE, Region: ' East ', width:150, Lines:false, Usearrows:true, Autoscroll:true, Split:true, iconcls: ' User-online ', store:Ext.cre Ate (' Ext.data.TreeStore ', {root: {text: ' Online user ', expanded 
      : True, Children: []}}); 
      var title = ' Welcome: ' + user; Show window var win = ext.create (' Ext.window.Window ', {title:title + ' (not connected) ', layout: ' Bo 
 Rder ', iconcls: ' User-win ',           minwidth:650, minheight:460, width:650, Animatetarget: ' WebSocket _button ', height:460, items: [Dialog,onlineuser], Border:false, l 
              Isteners: {render:function () {initwebsocket (); 
 
      } 
            } 
          }); 
 
      Win.show (); 
        Send Message function Send () {var messages = {}; if (websocket!= null) {if (Input.getvalue ()) {ext.apply (message, {From:us 
                  Er, Content:input.getValue (), Timestamp:new Date (). GetTime (), 
            Type: ' message '}); 
            Websocket.send (json.stringify (message)); 
            output.receive (message); 
          Input.setvalue ("); 
        } else {Ext.Msg.alert (' hint ', ' you've dropped the line, can't send a message! '); 
 } 
      } 
    });

The code above is to automatically connect to the server after the page finishes loading and to create a display interface code.

Attention

Two points to note, after the deployment is complete, the Catalina.jar and Tomcat-coyote.jar in the Lib directory in the Tomcat application directory will be deleted, such as the project's Lib directory in D:\workspace\WebSocket\ Webroot\web-inf\lib, while the deployed application Lib directory is in D:\tools\apache-tomcat-7.0.32\webapps\WebSocket\WEB-INF\lib, Delete the deployment directory of the Lib directory can be even two jars, otherwise it will package could not initialize class Com.ibcio.WebSocketMessageServlet error, remember.

If you still can't establish the connection, download the latest Tomcat, forget that the version of Tomcatcreatewebsocketinbound is not the request parameter, now this code has this parameter, 7.0.3XX version is with this parameter, remember.

Summarize

Using WebSocket Development Server push is very convenient, this is a simple application, in fact, can also be combined with WEBRTC video chat and voice chat.

Instance Downloads

Download Address: Demo

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.