网上好多例子都是群发的,本文实现一对一的发送,给指定客户端进行消息推送
1、本文使用到netty-socketio开源库,以及mysql,所以首先在pom.xml中添加相应的依赖库
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<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, 添加端口及主机数据库连接等相关配置,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
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的相关配置信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
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
1
2
3
4
5
6
7
8
9
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
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) 创建客户端文件index.html,index2.html,index3.html分别代表testclient1 testclient2 testclient3三个用户
本文直接修改的https://github.com/mrniko/netty-socketio-demo/tree/master/client 中的index.html文件
其中clientid为发送者id, targetclientid为目标方id,本文简单的将发送方和接收方写死在html文件中
使用 以下代码进行连接
1
|
io.connect( 'http://localhost:8081?clientid=' +clientid); |
index.html 文件内容如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
<!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
运行结果如下
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:http://blog.csdn.net/sun_t89/article/details/52060946