当前位置: 移动技术网 > IT编程>开发语言>Java > Spring Boot实战之netty-socketio实现简单聊天室(给指定用户推送消息)

Spring Boot实战之netty-socketio实现简单聊天室(给指定用户推送消息)

2019年07月22日  | 移动技术网IT编程  | 我要评论
网上好多例子都是群发的,本文实现一对一的发送,给指定客户端进行消息推送 1、本文使用到netty-socketio开源库,以及mysql,所以首先在pom.xml中添加相

网上好多例子都是群发的,本文实现一对一的发送,给指定客户端进行消息推送

1、本文使用到netty-socketio开源库,以及mysql,所以首先在pom.xml中添加相应的依赖库

<dependency> 
    <groupid>com.corundumstudio.socketio</groupid> 
    <artifactid>netty-socketio</artifactid> 
    <version>1.7.11</version> 
</dependency> 
<dependency> 
    <groupid>org.springframework.boot</groupid> 
  <artifactid>spring-boot-starter-data-jpa</artifactid> 
</dependency> 
<dependency> 
  <groupid>mysql</groupid> 
  <artifactid>mysql-connector-java</artifactid> 
</dependency> 

2、修改application.properties, 添加端口及主机数据库连接等相关配置,

wss.server.port=8081 
wss.server.host=localhost 
 
spring.datasource.url = jdbc:mysql://127.0.0.1:3306/springlearn 
spring.datasource.username = root 
spring.datasource.password = root 
spring.datasource.driverclassname = com.mysql.jdbc.driver 
 
# specify the dbms 
spring.jpa.database = mysql 
# show or not log for each sql query 
spring.jpa.show-sql = true 
# hibernate ddl auto (create, create-drop, update) 
spring.jpa.hibernate.ddl-auto = update 
# naming strategy 
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.improvednamingstrategy 
# stripped before adding them to the entity manager) 
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.mysql5dialect 

3、修改application文件,添加nettysocket的相关配置信息

package com.xiaofangtech.sunt; 
 
import org.springframework.beans.factory.annotation.value; 
import org.springframework.boot.springapplication; 
import org.springframework.boot.autoconfigure.springbootapplication; 
import org.springframework.context.annotation.bean; 
 
import com.corundumstudio.socketio.authorizationlistener; 
import com.corundumstudio.socketio.configuration; 
import com.corundumstudio.socketio.handshakedata; 
import com.corundumstudio.socketio.socketioserver; 
import com.corundumstudio.socketio.annotation.springannotationscanner; 
 
@springbootapplication 
public class nettysocketspringapplication { 
 
  @value("${wss.server.host}") 
  private string host; 
 
  @value("${wss.server.port}") 
  private integer port; 
   
  @bean 
  public socketioserver socketioserver()  
  { 
    configuration config = new configuration(); 
    config.sethostname(host); 
    config.setport(port); 
     
    //该处可以用来进行身份验证 
    config.setauthorizationlistener(new authorizationlistener() { 
      @override 
      public boolean isauthorized(handshakedata data) { 
        //http://localhost:8081?username=test&password=test 
        //例如果使用上面的链接进行connect,可以使用如下代码获取用户密码信息,本文不做身份验证 
//       string username = data.getsingleurlparam("username"); 
//       string password = data.getsingleurlparam("password"); 
        return true; 
      } 
    }); 
     
    final socketioserver server = new socketioserver(config); 
    return server; 
  } 
   
  @bean 
  public springannotationscanner springannotationscanner(socketioserver socketserver) { 
    return new springannotationscanner(socketserver); 
  } 
   
  public static void main(string[] args) { 
    springapplication.run(nettysocketspringapplication.class, args); 
  } 
} 

4、添加消息结构类messageinfo.java

package com.xiaofangtech.sunt.message; 
 
public class messageinfo { 
  //源客户端id 
  private string sourceclientid; 
  //目标客户端id 
  private string targetclientid; 
  //消息类型 
  private string msgtype; 
  //消息内容 
  private string msgcontent; 
   
  public string getsourceclientid() { 
    return sourceclientid; 
  } 
  public void setsourceclientid(string sourceclientid) { 
    this.sourceclientid = sourceclientid; 
  } 
  public string gettargetclientid() { 
    return targetclientid; 
  } 
  public void settargetclientid(string targetclientid) { 
    this.targetclientid = targetclientid; 
  } 
  public string getmsgtype() { 
    return msgtype; 
  } 
  public void setmsgtype(string msgtype) { 
    this.msgtype = msgtype; 
  } 
  public string getmsgcontent() { 
    return msgcontent; 
  } 
  public void setmsgcontent(string msgcontent) { 
    this.msgcontent = msgcontent; 
  } 
} 

5、添加客户端信息,用来存放客户端的sessionid

package com.xiaofangtech.sunt.bean; 
 
import java.util.date; 
 
import javax.persistence.entity; 
import javax.persistence.id; 
import javax.persistence.table; 
import javax.validation.constraints.notnull; 
 
@entity 
@table(name="t_clientinfo") 
public class clientinfo { 
  @id 
  @notnull 
  private string clientid; 
  private short connected; 
  private long mostsignbits; 
  private long leastsignbits; 
  private date lastconnecteddate; 
  public string getclientid() { 
    return clientid; 
  } 
  public void setclientid(string clientid) { 
    this.clientid = clientid; 
  } 
  public short getconnected() { 
    return connected; 
  } 
  public void setconnected(short connected) { 
    this.connected = connected; 
  } 
  public long getmostsignbits() { 
    return mostsignbits; 
  } 
  public void setmostsignbits(long mostsignbits) { 
    this.mostsignbits = mostsignbits; 
  } 
  public long getleastsignbits() { 
    return leastsignbits; 
  } 
  public void setleastsignbits(long leastsignbits) { 
    this.leastsignbits = leastsignbits; 
  } 
  public date getlastconnecteddate() { 
    return lastconnecteddate; 
  } 
  public void setlastconnecteddate(date lastconnecteddate) { 
    this.lastconnecteddate = lastconnecteddate; 
  } 
   
} 

6、添加查询数据库接口clientinforepository.java

package com.xiaofangtech.sunt.repository; 
 
import org.springframework.data.repository.crudrepository; 
 
import com.xiaofangtech.sunt.bean.clientinfo; 
 
public interface clientinforepository extends crudrepository<clientinfo, string>{ 
  clientinfo findclientbyclientid(string clientid); 
} 

7、添加消息处理类messageeventhandler.java

package com.xiaofangtech.sunt.message; 
 
import java.util.date; 
import java.util.uuid; 
 
import org.springframework.beans.factory.annotation.autowired; 
import org.springframework.stereotype.component; 
 
import com.corundumstudio.socketio.ackrequest; 
import com.corundumstudio.socketio.socketioclient; 
import com.corundumstudio.socketio.socketioserver; 
import com.corundumstudio.socketio.annotation.onconnect; 
import com.corundumstudio.socketio.annotation.ondisconnect; 
import com.corundumstudio.socketio.annotation.onevent; 
import com.xiaofangtech.sunt.bean.clientinfo; 
import com.xiaofangtech.sunt.repository.clientinforepository; 
 
@component 
public class messageeventhandler  
{ 
  private final socketioserver server; 
   
  @autowired 
  private clientinforepository clientinforepository; 
   
  @autowired 
  public messageeventhandler(socketioserver server)  
  { 
    this.server = server; 
  } 
  //添加connect事件,当客户端发起连接时调用,本文中将clientid与sessionid存入数据库 
  //方便后面发送消息时查找到对应的目标client, 
  @onconnect 
  public void onconnect(socketioclient client) 
  { 
    string clientid = client.gethandshakedata().getsingleurlparam("clientid"); 
    clientinfo clientinfo = clientinforepository.findclientbyclientid(clientid); 
    if (clientinfo != null) 
    { 
      date nowtime = new date(system.currenttimemillis()); 
      clientinfo.setconnected((short)1); 
      clientinfo.setmostsignbits(client.getsessionid().getmostsignificantbits()); 
      clientinfo.setleastsignbits(client.getsessionid().getleastsignificantbits()); 
      clientinfo.setlastconnecteddate(nowtime); 
      clientinforepository.save(clientinfo); 
    } 
  } 
   
  //添加@ondisconnect事件,客户端断开连接时调用,刷新客户端信息 
  @ondisconnect 
  public void ondisconnect(socketioclient client) 
  { 
    string clientid = client.gethandshakedata().getsingleurlparam("clientid"); 
    clientinfo clientinfo = clientinforepository.findclientbyclientid(clientid); 
    if (clientinfo != null) 
    { 
      clientinfo.setconnected((short)0); 
      clientinfo.setmostsignbits(null); 
      clientinfo.setleastsignbits(null); 
      clientinforepository.save(clientinfo); 
    } 
  } 
   
  //消息接收入口,当接收到消息后,查找发送目标客户端,并且向该客户端发送消息,且给自己发送消息 
  @onevent(value = "messageevent") 
  public void onevent(socketioclient client, ackrequest request, messageinfo data)  
  { 
    string targetclientid = data.gettargetclientid(); 
    clientinfo clientinfo = clientinforepository.findclientbyclientid(targetclientid); 
    if (clientinfo != null && clientinfo.getconnected() != 0) 
    { 
      uuid uuid = new uuid(clientinfo.getmostsignbits(), clientinfo.getleastsignbits()); 
      system.out.println(uuid.tostring()); 
      messageinfo senddata = new messageinfo(); 
      senddata.setsourceclientid(data.getsourceclientid()); 
      senddata.settargetclientid(data.gettargetclientid()); 
      senddata.setmsgtype("chat"); 
      senddata.setmsgcontent(data.getmsgcontent()); 
      client.sendevent("messageevent", senddata); 
      server.getclient(uuid).sendevent("messageevent", senddata); 
    } 
     
  } 
} 

8、添加serverrunner.java

package com.xiaofangtech.sunt.message; 
 
import org.springframework.beans.factory.annotation.autowired; 
import org.springframework.boot.commandlinerunner; 
import org.springframework.stereotype.component; 
 
import com.corundumstudio.socketio.socketioserver; 
 
@component 
public class serverrunner implements commandlinerunner { 
  private final socketioserver server; 
 
  @autowired 
  public serverrunner(socketioserver server) { 
    this.server = server; 
  } 
 
  @override 
  public void run(string... args) throws exception { 
    server.start(); 
  } 
} 

9、工程结构

10、运行测试

1) 添加基础数据,数据库中预置3个客户端testclient1,testclient2,testclient3

2) 创建客户端文件,index2.html,index3.html分别代表testclient1 testclient2 testclient3三个用户

本文直接修改的https://github.com/mrniko/netty-socketio-demo/tree/master/client 中的文件

其中clientid为发送者id, targetclientid为目标方id,本文简单的将发送方和接收方写死在html文件中

使用 以下代码进行连接

io.connect('http://localhost:8081?clientid='+clientid); 

文件内容如下

<!doctype html> 
<html> 
<head> 
 
    <meta charset="utf-8" /> 
 
    <title>demo chat</title> 
 
    <link href="bootstrap.css" rel="external nofollow" rel="stylesheet"> 
 
  <style> 
    body { 
      padding:20px; 
    } 
    #console { 
      height: 400px; 
      overflow: auto; 
    } 
    .username-msg {color:orange;} 
    .connect-msg {color:green;} 
    .disconnect-msg {color:red;} 
    .send-msg {color:#888} 
  </style> 
 
 
  <script src="js/socket.io/socket.io.js"></script> 
    <script src="js/moment.min.js"></script> 
    <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> 
 
  <script> 
 
    var clientid = 'testclient1'; 
    var targetclientid= 'testclient2'; 
     
    var socket = io.connect('http://localhost:8081?clientid='+clientid); 
 
    socket.on('connect', function() { 
      output('<span class="connect-msg">client has connected to the server!</span>'); 
    }); 
 
    socket.on('messageevent', function(data) { 
      output('<span class="username-msg">' + data.sourceclientid + ':</span> ' + data.msgcontent); 
    }); 
 
    socket.on('disconnect', function() { 
      output('<span class="disconnect-msg">the client has disconnected!</span>'); 
    }); 
 
        function senddisconnect() { 
            socket.disconnect(); 
        } 
 
    function sendmessage() { 
            var message = $('#msg').val(); 
            $('#msg').val(''); 
 
            var jsonobject = {sourceclientid: clientid, 
                     targetclientid: targetclientid, 
                     msgtype: 'chat', 
                     msgcontent: message}; 
            socket.emit('messageevent', jsonobject); 
    } 
 
    function output(message) { 
            var currenttime = "<span class='time'>" + moment().format('hh:mm:ss.sss') + "</span>"; 
            var element = $("<div>" + currenttime + " " + message + "</div>"); 
      $('#console').prepend(element); 
    } 
 
    $(document).keydown(function(e){ 
      if(e.keycode == 13) { 
        $('#send').click(); 
      } 
    }); 
  </script> 
</head> 
 
<body> 
 
  <h1>netty-socketio demo chat</h1> 
 
  <br/> 
 
  <div id="console" class="well"> 
  </div> 
 
    <form class="well form-inline" onsubmit="return false;"> 
      <input id="msg" class="input-xlarge" type="text" placeholder="type something..."/> 
      <button type="button" onclick="sendmessage()" class="btn" id="send">send</button> 
      <button type="button" onclick="senddisconnect()" class="btn">disconnect</button> 
    </form>  
</body>  
</html> 

3、本例测试时

testclient1 发送消息给 testclient2

testclient2 发送消息给 testclient1

testclient3发送消息给testclient1

运行结果如下


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如您对本文有疑问或者有任何想说的,请 点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网