Spring Boot实战之netty

网友投稿 337 2023-06-02


Spring Boot实战之netty

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

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

com.corundumstudio.socketio

netty-socketio

1.7.11

org.springframework.boot

spring-boot-starter-data-jpa

mysql

mysql-connector-java

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 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) 创建客户端文件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文件中

使用 以下代码进行连接

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

index.html 文件内容如下


3、本例测试时

testclient1 发送消息给 testclient2

testclient2 发送消息给 testclient1

testclient3发送消息给testclient1

运行结果如下


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java中JDBC连接数据库详解
下一篇:JavaWeb之Filter过滤器详解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~