网上好多例子都是群发的,本文实现一对一的发送,给指定客户端进行消息推送
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