diff --git a/README.md b/README.md index 0e527c3..1fb6b1f 100644 --- a/README.md +++ b/README.md @@ -1,126 +1,77 @@ -# InChat(当前版本1.6.0) +# tcp-wechat -> 当前主要更新分支,master将会再所有分支开放一定阶段后整改为maven包,提供给大家使用 +## 项目介绍 -## 分支介绍 im-api +针对小程序与单片机硬件执行Iot物联网通讯(TCP/IP)的一套完整Demo。 -腾讯IM(云通信)后端模仿项目,均以API形式对接,如果有前端想要对接的可以运行本分支,本分支预计终版为一个单服务并发30万用户的IM后台项目 +## 项目配置 -## 分支介绍 paho-mqtt +> 以下说明针对 tag V0.9.1 -基于小程序端或移动web端的paho.js与[java MQTT 客户端模拟](https://github.com/eclipse/paho.mqtt.java)的消息订阅与通信,小程序Iot的Demo,目前支持ws格式 +> application.xml -## 分支介绍 tcp-wechat +配置tcp端口:8092 -基于小程序端与单片机等硬件的TCP/IP的主要通信,Iot中心作为中转,本demo将完全实现具体功能,详情请看分支主页 +> com.myself.nettychat.tcptest.TCPTestClient -## 简介 +配置连接IP与端口,修改代码中的参数 -***(InChat)Iot Netty Chat*** +## 启动流程 -仿微信聊天应用,一步一步更新,基于SpringBoot-WebSocket通用框架,结合Netty进行聊天社交,并记录聊天日志, -异步存储,前端暂用SUI Mobile,添加实现TCP/IP后端通信端口(MQTT协议、可实时与单片机等TCP硬件通信)、加入图片处理流, -聊天实现文字与图片发送功能、API调用Netty长链接执行发送消息(在线数、用户列表) +1、启动项目,tcp监听成功 -## 基本架构图(1.5.2版) +2、运行com.myself.nettychat.tcptest.TCPTestClient (记得先改ip或端口,如果你有修改的话) -![Image text](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/nettychat/ggg1.png) +3、运行PostMan,请求下方的API 进行通信测试 -## 功能 +## Demo场景 ->实时聊天 ->异步CRUD处理消息日志 ->获取聊天历史 ->用户登录、记录登录用户聊天历史 ->防止二次登录 ->SUI Mobile仿微信样式 ->TCP/IP软硬件通信(8092) ->MQTT协议下的Iot物联网通信(8094) ->图片发送聊天功能 ->API调用Netty长链接执行发送消息(在线用户数、用户列表) ->下版(1.7.0):好友功能等 +小程序端选购售货机中的商品,点击购买(小程序API向Iot中心发送对应商品的开锁信息),Iot中心中转开锁信息给单片机,单片机接收信息打开对应的锁。 -## 版本迭代介绍 +通信机制:帧头+ID+数据类型+24把锁状态+crc校验+帧尾(可以按照需求进行定制) -* 1.0.0版本 +> com.myself.nettychat.config.TCPServerHandler (通信接收的处理类) -用户登录,聊天历史,随机用户名,异步数据写入:https://segmentfault.com/a/1190000016615063 -* 1.2.0版本 +## API(小程序调用接口) -修复聊天记录功能,实现重复信息录入,完善前端页面,回车监听等:https://segmentfault.com/a/1190000016637814 +> http://localhost:8080/susu/back/get_channel_size GET -* 1.3.0版本 - -用户注册登录功能,系统聊天绑定用户,禁止二次登录等,前端页面大改 - -* 1.4.1版本 - -本人主导SUI Mobile构建仿微信样式页面版,使用时开F12手机界面 - -* 1.5.2版本 - -TCP/IP软硬件通信-单片机等应用的TCP通信,Netty处理二进制图片发送聊天功能 - -* 1.5.8版本 - -MQTT协议软硬件通信等,Iot物联网 - -* 1.6.0版本 - -API调用Netty长链接执行发送消息(在线数、用户列表):https://segmentfault.com/a/1190000016603392 - - -## 配置 - ->application.yml 数据库配置、Netty参数配置 - ->TCP需先去com.myself.nettychat.tcptest包下执行CRC16myself获取发送数据, - ->再执行TCPTestClient发送数据,请勿随意更改发送格式(通信协议来的) - ->http://localhost:8080/susu/admin/loginsui 启动访问路径 - ->mqtt协议测试在mqttclient包下 - ->http://localhost:8080/susu/swagger-ui.html 查看API文档 - -## 效果图 - -![Image text](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/nettychat/001%20(5).png) -![Image text](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/nettychat/001%20(3).png) -![Image text](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/nettychat/001%20(4).png) -![Image text](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/nettychat/001%20(2).png) -![Image text](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/nettychat/001%20(1).png) -![Image text](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/nettychat/9.png) -![Image text](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/nettychat/10.png) -![Image text](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/nettychat/11.png) - -## 预留BUG +请求Iot中心,获取当前连接存活状态下的链接实例 ``` -io.netty.handler.codec.CorruptedFrameException: Max frame length of 65536 has been exceeded. -图片过大,需要在前端做图片上传压缩 - -Uncaught TypeError: msg.substring is not a function at WebSocket.socket.onmessage (newChat.js:38) -前端代码的一点问题,不影响项目正常运行 - -java.io.IOException: 远程主机强迫关闭了一个现有的连接。 -TCP客户端连接主动关闭,不影响,良性报错 +{ + "code": 200, + "msg": "成功", + "data": 1 +} ``` -## 下载地址 - -下载地址:https://github.com/UncleCatMySelf/SBToNettyChat/releases +> http://localhost:8080/susu/back/get_channel_id_list GET -## 交流与提问 +请求Iot中心,当前存活状态下的链接Id列表 -提问与Bug上报:https://github.com/UncleCatMySelf/SBToNettyChat/issues +``` +{ + "code": 200, + "msg": "成功", + "data": [ + "F5690137563CC8" + ] +} +``` -QQ群:628793702(仅供交流,不提供问题解答) +> http://localhost:8080/susu/back/send_to_channel POST -## 关于作者 +参数 +* channelId //第二个API获取到的链接Id +* lock //将要打开的第几把锁 1-24(看单片机接入的锁的数量) -个人公众号:UncleCatMySelf +``` +{ + "code": 200, + "msg": "成功", + "data": "【发送成功】" +} +``` -![Image text](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/%E5%85%AC%E4%BC%97%E5%8F%B7.png) diff --git a/h5/chat.html b/h5/chat.html index 91d15b2..48aeb1e 100644 --- a/h5/chat.html +++ b/h5/chat.html @@ -5,47 +5,47 @@ WebSocket Chat diff --git a/h5/home.html b/h5/home.html deleted file mode 100644 index 541e6b7..0000000 --- a/h5/home.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - 酥酥 - - - - - - - - - - -
-
-

酥酥

-
- -
- -
-
- - - - - \ No newline at end of file diff --git a/h5/index.html b/h5/index.html deleted file mode 100644 index 32e88ea..0000000 --- a/h5/index.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - 酥酥 - - - - - - - - - - -
-
- -
-

登录

-
-
-
-
    - -
  • -
    -
    -
    -
    账号
    -
    - -
    -
    -
    -
  • -
  • -
    -
    -
    -
    密码
    -
    - -
    -
    -
    -
  • -
-
-
-
- - -
-
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/h5/logoSmall.png b/h5/logoSmall.png deleted file mode 100644 index 08b5d51..0000000 Binary files a/h5/logoSmall.png and /dev/null differ diff --git a/pom.xml b/pom.xml index 458d0cf..a8d0223 100644 --- a/pom.xml +++ b/pom.xml @@ -29,9 +29,14 @@ org.springframework.boot spring-boot-starter-tomcat + - org.springframework.boot - spring-boot-starter-data-jpa + org.springframework + spring-aop + + + org.springframework + spring-aspects mysql diff --git a/sql/nettychat.sql b/sql/nettychat.sql deleted file mode 100644 index 452c711..0000000 --- a/sql/nettychat.sql +++ /dev/null @@ -1,71 +0,0 @@ -/* -Navicat MySQL Data Transfer - -Source Server : mypc -Source Server Version : 50717 -Source Host : localhost:3306 -Source Database : nettychat - -Target Server Type : MYSQL -Target Server Version : 50717 -File Encoding : 65001 - -Date: 2018-08-23 10:32:48 -*/ - -SET FOREIGN_KEY_CHECKS=0; - --- ---------------------------- --- Table structure for user --- ---------------------------- -DROP TABLE IF EXISTS `user`; -CREATE TABLE `user` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `user_name` varchar(255) DEFAULT NULL, - `pass_word` varchar(255) DEFAULT NULL, - `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4; - --- ---------------------------- --- Records of user --- ---------------------------- -INSERT INTO `user` VALUES ('2', 'Myself', '123456', '2018-08-14 19:47:49', '2018-08-14 19:47:49'); -INSERT INTO `user` VALUES ('3', 'Chen', '123456abc', '2018-08-20 16:31:49', '2018-08-20 16:31:49'); - --- ---------------------------- --- Table structure for user_msg --- ---------------------------- -DROP TABLE IF EXISTS `user_msg`; -CREATE TABLE `user_msg` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `name` varchar(255) DEFAULT NULL, - `msg` varchar(255) DEFAULT NULL, - `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=43 DEFAULT CHARSET=utf8mb4; - --- ---------------------------- --- Records of user_msg --- ---------------------------- -INSERT INTO `user_msg` VALUES ('8', 'Myself', '你好呀', '2018-08-20 17:26:58', '2018-08-20 17:26:58'); -INSERT INTO `user_msg` VALUES ('9', 'Myself', '你是谁?', '2018-08-20 17:27:13', '2018-08-20 17:27:13'); -INSERT INTO `user_msg` VALUES ('10', 'Myself', '在吗?', '2018-08-21 17:54:12', '2018-08-21 17:54:12'); -INSERT INTO `user_msg` VALUES ('11', 'Chen', '嗯呢', '2018-08-21 17:54:12', '2018-08-21 17:54:12'); -INSERT INTO `user_msg` VALUES ('13', 'Myself', 'yo', '2018-08-21 18:01:26', '2018-08-21 18:01:26'); -INSERT INTO `user_msg` VALUES ('14', 'Myself', '你好', '2018-08-22 16:24:22', '2018-08-22 16:24:22'); -INSERT INTO `user_msg` VALUES ('30', 'Myself', '你好呀!', '2018-08-22 17:03:42', '2018-08-22 17:03:42'); -INSERT INTO `user_msg` VALUES ('31', 'Myself', '我很好!', '2018-08-22 17:03:42', '2018-08-22 17:03:42'); -INSERT INTO `user_msg` VALUES ('32', 'Myself', '哈哈哈哈', '2018-08-22 17:11:56', '2018-08-22 17:11:56'); -INSERT INTO `user_msg` VALUES ('33', 'Myself', '哇哈哈哈哈', '2018-08-22 17:11:56', '2018-08-22 17:11:56'); -INSERT INTO `user_msg` VALUES ('34', 'Myself', 'asdf', '2018-08-22 17:22:19', '2018-08-22 17:22:19'); -INSERT INTO `user_msg` VALUES ('35', 'Myself', '厉害 厉害', '2018-08-22 17:23:20', '2018-08-22 17:23:20'); -INSERT INTO `user_msg` VALUES ('36', 'Myself', '哈哈', '2018-08-22 17:23:43', '2018-08-22 17:23:43'); -INSERT INTO `user_msg` VALUES ('37', 'Myself', '你好!', '2018-08-23 10:19:14', '2018-08-23 10:19:14'); -INSERT INTO `user_msg` VALUES ('38', 'Chen', '收到。', '2018-08-23 10:19:15', '2018-08-23 10:19:15'); -INSERT INTO `user_msg` VALUES ('39', 'Myself', '前端框架用Vue?', '2018-08-23 10:19:15', '2018-08-23 10:19:15'); -INSERT INTO `user_msg` VALUES ('40', 'Chen', '可以试试', '2018-08-23 10:19:15', '2018-08-23 10:19:15'); -INSERT INTO `user_msg` VALUES ('41', 'Myself', '下版再加一些新的功能', '2018-08-23 10:19:15', '2018-08-23 10:19:15'); -INSERT INTO `user_msg` VALUES ('42', 'Chen', 'okay', '2018-08-23 10:19:15', '2018-08-23 10:19:15'); diff --git a/src/main/java/com/myself/nettychat/DefaultAutoService.java b/src/main/java/com/myself/nettychat/DefaultAutoService.java deleted file mode 100644 index e4b4cc7..0000000 --- a/src/main/java/com/myself/nettychat/DefaultAutoService.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.myself.nettychat; - -import com.myself.nettychat.bootstrap.BaseAuthService; -import org.springframework.stereotype.Service; - - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 默认权限 - **/ -@Service -public class DefaultAutoService implements BaseAuthService { - - @Override - public boolean authorized(String username, String password) { - return true; - } -} diff --git a/src/main/java/com/myself/nettychat/NettychatApplication.java b/src/main/java/com/myself/nettychat/NettychatApplication.java index 9c679bd..76029f4 100644 --- a/src/main/java/com/myself/nettychat/NettychatApplication.java +++ b/src/main/java/com/myself/nettychat/NettychatApplication.java @@ -17,7 +17,6 @@ public class NettychatApplication { public static void main(String[] args) throws Exception{ -// SpringApplication.run(NettychatApplication.class, args); ConfigurableApplicationContext context = SpringApplication.run(NettychatApplication.class, args); NettyConfig nettyConfig = context.getBean(NettyConfig.class); NettyTcpConfig nettyTcpConfig = context.getBean(NettyTcpConfig.class); diff --git a/src/main/java/com/myself/nettychat/auto/InitServer.java b/src/main/java/com/myself/nettychat/auto/InitServer.java deleted file mode 100644 index 3729fc3..0000000 --- a/src/main/java/com/myself/nettychat/auto/InitServer.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.myself.nettychat.auto; - - -import com.myself.nettychat.bootstrap.BootstrapServer; -import com.myself.nettychat.bootstrap.NettyBootstrapServer; -import com.myself.nettychat.common.properties.InitNetty; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 初始化服务 - **/ -public class InitServer { - - private InitNetty serverBean; - - public InitServer(InitNetty serverBean) { - this.serverBean = serverBean; - } - - BootstrapServer bootstrapServer; - - public void open(){ - if(serverBean!=null){ - bootstrapServer = new NettyBootstrapServer(); - bootstrapServer.setServerBean(serverBean); - bootstrapServer.start(); - } - } - - - public void close(){ - if(bootstrapServer!=null){ - bootstrapServer.shutdown(); - } - } - -} diff --git a/src/main/java/com/myself/nettychat/auto/ServerAutoConfigure.java b/src/main/java/com/myself/nettychat/auto/ServerAutoConfigure.java deleted file mode 100644 index 961e458..0000000 --- a/src/main/java/com/myself/nettychat/auto/ServerAutoConfigure.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.myself.nettychat.auto; - -import com.myself.nettychat.bootstrap.scan.SacnScheduled; -import com.myself.nettychat.bootstrap.scan.ScanRunnable; -import com.myself.nettychat.common.enums.ProtocolEnum; -import com.myself.nettychat.common.properties.InitNetty; -import org.apache.commons.lang3.ObjectUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 自动化配置初始化服务 - **/ -@Configuration -@ConditionalOnClass -@EnableConfigurationProperties({InitNetty.class}) -public class ServerAutoConfigure { - - private static final int _BLACKLOG = 1024; - - private static final int CPU =Runtime.getRuntime().availableProcessors(); - - private static final int SEDU_DAY =10; - - private static final int TIMEOUT =120; - - private static final int BUF_SIZE=10*1024*1024; - - - public ServerAutoConfigure(){ - - } - - @Bean - @ConditionalOnMissingBean(name = "sacnScheduled") - public ScanRunnable initRunable(@Autowired InitNetty serverBean){ - long time =(serverBean==null || serverBean.getPeriod()<5)?10:serverBean.getPeriod(); - ScanRunnable sacnScheduled = new SacnScheduled(time); - Thread scanRunnable = new Thread(sacnScheduled); - scanRunnable.setDaemon(true); - scanRunnable.start(); - return sacnScheduled; - } - - - @Bean(initMethod = "open", destroyMethod = "close") - @ConditionalOnMissingBean - public InitServer initServer(InitNetty serverBean){ - if(!ObjectUtils.allNotNull(serverBean.getMqttport(),serverBean.getServerName())){ - throw new NullPointerException("not set port"); - } - if(serverBean.getBacklog()<1){ - serverBean.setBacklog(_BLACKLOG); - } - if(serverBean.getBossThread()<1){ - serverBean.setBossThread(CPU); - } - if(serverBean.getInitalDelay()<0){ - serverBean.setInitalDelay(SEDU_DAY); - } - if(serverBean.getPeriod()<1){ - serverBean.setPeriod(SEDU_DAY); - } - if(serverBean.getHeart()<1){ - serverBean.setHeart(TIMEOUT); - } - if(serverBean.getRevbuf()<1){ - serverBean.setRevbuf(BUF_SIZE); - } - if(serverBean.getWorkerThread()<1){ - serverBean.setWorkerThread(CPU*2); - } - if(serverBean.getProtocol()==null){ - serverBean.setProtocol(ProtocolEnum.MQTT); - } - return new InitServer(serverBean); - } - -} diff --git a/src/main/java/com/myself/nettychat/bootstrap/AbstractBootstrapServer.java b/src/main/java/com/myself/nettychat/bootstrap/AbstractBootstrapServer.java deleted file mode 100644 index a647848..0000000 --- a/src/main/java/com/myself/nettychat/bootstrap/AbstractBootstrapServer.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.myself.nettychat.bootstrap; - - -import com.myself.nettychat.bootstrap.coder.ByteBufToWebSocketFrameEncoder; -import com.myself.nettychat.bootstrap.coder.WebSocketFrameToByteBufDecoder; -import com.myself.nettychat.common.properties.InitNetty; -import com.myself.nettychat.common.ssl.SecureSocketSslContextFactory; -import com.myself.nettychat.common.utils.SpringBeanUtils; -import io.netty.channel.ChannelPipeline; -import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.codec.http.HttpServerCodec; -import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; -import io.netty.handler.codec.mqtt.MqttDecoder; -import io.netty.handler.codec.mqtt.MqttEncoder; -import io.netty.handler.ssl.SslHandler; -import io.netty.handler.timeout.IdleStateHandler; -import org.apache.commons.lang3.ObjectUtils; -import org.jboss.netty.util.internal.SystemPropertyUtil; - -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLEngine; -import java.security.KeyStore; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 抽象类,负责加载edec handler - **/ -public abstract class AbstractBootstrapServer implements BootstrapServer { - - private String PROTOCOL = "TLS"; - - private SSLContext SERVER_CONTEXT; - - private static final String MQTT_CSV_LIST = "mqtt, mqttv3.1, mqttv3.1.1"; - - - /** - * - * @param channelPipeline channelPipeline - * @param serverBean 服务配置参数 - */ - protected void initHandler(ChannelPipeline channelPipeline, InitNetty serverBean){ - if(serverBean.isSsl()){ - if(!ObjectUtils.allNotNull(serverBean.getJksCertificatePassword(),serverBean.getJksFile(),serverBean.getJksStorePassword())){ - throw new NullPointerException("SSL file and password is null"); - } - initSsl(serverBean); - SSLEngine engine = - SERVER_CONTEXT.createSSLEngine(); - engine.setUseClientMode(false); - channelPipeline.addLast("ssl", new SslHandler(engine)); - } - - intProtocolHandler(channelPipeline,serverBean); - channelPipeline.addLast(new IdleStateHandler(serverBean.getHeart(),0,0)); - channelPipeline.addLast( SpringBeanUtils.getBean(serverBean.getMqttHander())); - - } - - private void intProtocolHandler(ChannelPipeline channelPipeline,InitNetty serverBean){ - switch (serverBean.getProtocol()){ - case MQTT: - channelPipeline.addLast("encoder", MqttEncoder.INSTANCE); - channelPipeline.addLast("decoder", new MqttDecoder()); - break; - case MQTT_WS_MQTT: - channelPipeline.addLast("httpCode", new HttpServerCodec()); - channelPipeline.addLast("aggregator", new HttpObjectAggregator(65536)); - channelPipeline.addLast("webSocketHandler", - new WebSocketServerProtocolHandler("/", MQTT_CSV_LIST)); - channelPipeline.addLast("wsDecoder", new WebSocketFrameToByteBufDecoder()); - channelPipeline.addLast("wsEncoder", new ByteBufToWebSocketFrameEncoder()); - channelPipeline.addLast("decoder", new MqttDecoder()); - channelPipeline.addLast("encoder", MqttEncoder.INSTANCE); - break; - case MQTT_WS_PAHO: - channelPipeline.addLast("httpCode", new HttpServerCodec()); - channelPipeline.addLast("aggregator", new HttpObjectAggregator(65536)); - channelPipeline.addLast("webSocketHandler", - new WebSocketServerProtocolHandler("/mqtt", MQTT_CSV_LIST)); - channelPipeline.addLast("wsDecoder", new WebSocketFrameToByteBufDecoder()); - channelPipeline.addLast("wsEncoder", new ByteBufToWebSocketFrameEncoder()); - channelPipeline.addLast("decoder", new MqttDecoder()); - channelPipeline.addLast("encoder", MqttEncoder.INSTANCE); - break; - } - } - - private void initSsl(InitNetty serverBean){ - ExecutorService executorService = Executors.newCachedThreadPool(); - executorService.submit(() -> {}); - String algorithm = SystemPropertyUtil.get("ssl.KeyManagerFactory.algorithm"); - if (algorithm == null) { - algorithm = "SunX509"; - } - SSLContext serverContext; - try { - // - KeyStore ks = KeyStore.getInstance("JKS"); - ks.load( SecureSocketSslContextFactory.class.getResourceAsStream(serverBean.getJksFile()), - serverBean.getJksStorePassword().toCharArray()); - KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm); - kmf.init(ks,serverBean.getJksCertificatePassword().toCharArray()); - serverContext = SSLContext.getInstance(PROTOCOL); - serverContext.init(kmf.getKeyManagers(), null, null); - } catch (Exception e) { - throw new Error( - "Failed to initialize the server-side SSLContext", e); - } - SERVER_CONTEXT = serverContext; - } - -} diff --git a/src/main/java/com/myself/nettychat/bootstrap/BaseApi.java b/src/main/java/com/myself/nettychat/bootstrap/BaseApi.java deleted file mode 100644 index edd8720..0000000 --- a/src/main/java/com/myself/nettychat/bootstrap/BaseApi.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.myself.nettychat.bootstrap; - -import javax.validation.constraints.NotNull; -import java.util.Arrays; -import java.util.Optional; -import java.util.function.Consumer; -import java.util.function.Predicate; - - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 逻辑操作封装 - **/ -public interface BaseApi { - - default void doIfElse(T t, Predicate predicate, Consumer consumer){ - if(t!=null){ - if(predicate.test(t)){ - consumer.accept(t); - } - } - } - - - default void doIfElse(T t, Predicate predicate, Consumer consumer, Consumer consumer2){ - if(t!=null){ - if(predicate.test(t)){ - consumer.accept(t); - } - else{ - consumer2.accept(t); - } - } - } - default boolean doIf(T t, Predicate... predicates){ - if(t!=null){ - for(Predicate p:predicates){ - if(!p.test(t)){ - return false; - } - } - return true; - } - return false; - } - - default void doIfAnd(T t, Consumer consumer2, Predicate... predicates){ - boolean flag =true; - if(t!=null){ - for(Predicate p:predicates){ - if(!p.test(t)){ - flag= false; - break; - } - } - } - if(flag){ - consumer2.accept(t); - } - } - - default void doIfAnd1(@NotNull T t, @NotNull Consumer consumer2, @NotNull Predicate... predicates){ - Predicate one = predicates[0]; - int l; - if((l=predicates.length)>1){ - for(int i=1;i topics); - - void loginSuccess(Channel channel, String deviceId, MqttConnectMessage mqttConnectMessage); - - void publishSuccess(Channel channel, MqttPublishMessage mqttPublishMessage); - - void closeSuccess(String deviceId,boolean isDisconnect); - - void sendWillMsg(WillMeaasge willMeaasge); - - String getDeviceId(Channel channel); - - void unsubscribe(String deviceId, List topics1); - - void doPubrel(Channel channel, int mqttMessage); - - void doPubrec(Channel channel, int mqttMessage); - -} diff --git a/src/main/java/com/myself/nettychat/bootstrap/NettyBootstrapServer.java b/src/main/java/com/myself/nettychat/bootstrap/NettyBootstrapServer.java deleted file mode 100644 index 816eea7..0000000 --- a/src/main/java/com/myself/nettychat/bootstrap/NettyBootstrapServer.java +++ /dev/null @@ -1,134 +0,0 @@ -package com.myself.nettychat.bootstrap; - -import com.myself.nettychat.common.ip.IpUtils; -import com.myself.nettychat.common.properties.InitNetty; -import com.myself.nettychat.common.utils.RemotingUtil; -import lombok.Data; -import lombok.extern.slf4j.Slf4j; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.buffer.PooledByteBufAllocator; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.epoll.Epoll; -import io.netty.channel.epoll.EpollEventLoopGroup; -import io.netty.channel.epoll.EpollServerSocketChannel; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.SocketChannel; -import io.netty.channel.socket.nio.NioServerSocketChannel; - -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc mtqq netty启动服务类 - **/ -@Slf4j -@Data -public class NettyBootstrapServer extends AbstractBootstrapServer { - - private InitNetty serverBean; - - public InitNetty getServerBean() { - return serverBean; - } - - public void setServerBean(InitNetty serverBean) { - this.serverBean = serverBean; - } - - private EventLoopGroup bossGroup; - - private EventLoopGroup workGroup; - - ServerBootstrap bootstrap=null ;// 启动辅助类 - - /** - * 服务开启 - */ - public void start() { - initEventPool(); - bootstrap.group(bossGroup, workGroup) - .channel(useEpoll()?EpollServerSocketChannel.class:NioServerSocketChannel.class) - .option(ChannelOption.SO_REUSEADDR, serverBean.isReuseaddr()) - .option(ChannelOption.SO_BACKLOG, serverBean.getBacklog()) - .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT) - .option(ChannelOption.SO_RCVBUF, serverBean.getRevbuf()) - .childHandler(new ChannelInitializer() { - protected void initChannel(SocketChannel ch) throws Exception { - initHandler(ch.pipeline(),serverBean); - } - }) - .childOption(ChannelOption.TCP_NODELAY, serverBean.isNodelay()) - .childOption(ChannelOption.SO_KEEPALIVE, serverBean.isKeepalive()) - .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT); - bootstrap.bind(IpUtils.getHost(),serverBean.getMqttport()).addListener((ChannelFutureListener) channelFuture -> { - if (channelFuture.isSuccess()) - log.info("服务端启动成功【" + IpUtils.getHost() + ":" + serverBean.getMqttport() + "】"); - else - log.info("服务端启动失败【" + IpUtils.getHost() + ":" + serverBean.getMqttport() + "】"); - }); - } - /** - * 初始化EnentPool 参数 - */ - private void initEventPool(){ - bootstrap= new ServerBootstrap(); - if(useEpoll()){ - bossGroup = new EpollEventLoopGroup(serverBean.getBossThread(), new ThreadFactory() { - private AtomicInteger index = new AtomicInteger(0); - - public Thread newThread(Runnable r) { - return new Thread(r, "LINUX_BOSS_" + index.incrementAndGet()); - } - }); - workGroup = new EpollEventLoopGroup(serverBean.getWorkerThread(), new ThreadFactory() { - private AtomicInteger index = new AtomicInteger(0); - - public Thread newThread(Runnable r) { - return new Thread(r, "LINUX_WORK_" + index.incrementAndGet()); - } - }); - - } - else { - bossGroup = new NioEventLoopGroup(serverBean.getBossThread(), new ThreadFactory() { - private AtomicInteger index = new AtomicInteger(0); - - public Thread newThread(Runnable r) { - return new Thread(r, "BOSS_" + index.incrementAndGet()); - } - }); - workGroup = new NioEventLoopGroup(serverBean.getWorkerThread(), new ThreadFactory() { - private AtomicInteger index = new AtomicInteger(0); - - public Thread newThread(Runnable r) { - return new Thread(r, "WORK_" + index.incrementAndGet()); - } - }); - } - } - - /** - * 关闭资源 - */ - public void shutdown() { - if(workGroup!=null && bossGroup!=null ){ - try { - bossGroup.shutdownGracefully().sync();// 优雅关闭 - workGroup.shutdownGracefully().sync(); - } catch (InterruptedException e) { - log.info("服务端关闭资源失败【" + IpUtils.getHost() + ":" + serverBean.getMqttport() + "】"); - } - } - } - - private boolean useEpoll() { - return RemotingUtil.isLinuxPlatform() - && Epoll.isAvailable(); - } - -} diff --git a/src/main/java/com/myself/nettychat/bootstrap/bean/MqttChannel.java b/src/main/java/com/myself/nettychat/bootstrap/bean/MqttChannel.java deleted file mode 100644 index 9c830ce..0000000 --- a/src/main/java/com/myself/nettychat/bootstrap/bean/MqttChannel.java +++ /dev/null @@ -1,115 +0,0 @@ -package com.myself.nettychat.bootstrap.bean; - -import io.netty.channel.Channel; -import io.netty.util.AttributeKey; -import lombok.Builder; -import lombok.Data; - -import com.myself.nettychat.common.enums.SubStatus; -import com.myself.nettychat.common.enums.SessionStatus; - -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc channel 封装类 - **/ -@Builder -@Data -public class MqttChannel { - - private transient volatile Channel channel; - - - private String deviceId; - - - private boolean isWill; - - - private volatile SubStatus subStatus; // 是否订阅过主题 - - - private Set topic ; - - - - private volatile SessionStatus sessionStatus; // 在线 - 离线 - - - - private volatile boolean cleanSession; // 当为 true 时 channel close 时 从缓存中删除 此channel - - - - - private ConcurrentHashMap message ; // messageId - message(qos1) // 待确认消息 - - - private Set receive; - - public void addRecevice(int messageId){ - receive.add(messageId); - } - - public boolean checkRecevice(int messageId){ - return receive.contains(messageId); - } - - public boolean removeRecevice(int messageId){ - return receive.remove(messageId); - } - - - public void addSendMqttMessage(int messageId,SendMqttMessage msg){ - message.put(messageId,msg); - } - - - public SendMqttMessage getSendMqttMessage(int messageId){ - return message.get(messageId); - } - - - public void removeSendMqttMessage(int messageId){ - message.remove(messageId); - } - - - /** - * 判断当前channel 是否登录过 - * @return - */ - public boolean isLogin(){ - return Optional.ofNullable(this.channel).map(channel1 -> { - AttributeKey _login = AttributeKey.valueOf("login"); - return channel1.isActive() && channel1.hasAttr(_login); - }).orElse(false); - } - - /** - * 非正常关闭 - */ - public void close(){ - Optional.ofNullable(this.channel).ifPresent(channel1 -> channel1.close()); - } - - /** - * 通道是否活跃 - * @return - */ - public boolean isActive(){ - return channel!=null&&this.channel.isActive(); - } - - - - public boolean addTopic(Set topics){ - return topic.addAll(topics); - } - - -} diff --git a/src/main/java/com/myself/nettychat/bootstrap/bean/RetainMessage.java b/src/main/java/com/myself/nettychat/bootstrap/bean/RetainMessage.java deleted file mode 100644 index 814696a..0000000 --- a/src/main/java/com/myself/nettychat/bootstrap/bean/RetainMessage.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.myself.nettychat.bootstrap.bean; - -import io.netty.handler.codec.mqtt.MqttQoS; -import lombok.Builder; -import lombok.Data; - -@Builder -@Data -public class RetainMessage { - - private byte[] byteBuf; - - private MqttQoS qoS; - public String getString(){ - return new String(byteBuf); - } - -} diff --git a/src/main/java/com/myself/nettychat/bootstrap/bean/SendMqttMessage.java b/src/main/java/com/myself/nettychat/bootstrap/bean/SendMqttMessage.java deleted file mode 100644 index ac5faef..0000000 --- a/src/main/java/com/myself/nettychat/bootstrap/bean/SendMqttMessage.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.myself.nettychat.bootstrap.bean; - - -import io.netty.channel.Channel; -import io.netty.handler.codec.mqtt.MqttQoS; -import lombok.Builder; -import lombok.Data; - -import com.myself.nettychat.common.enums.ConfirmStatus; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc mqtts 消息 - **/ -@Builder -@Data -public class SendMqttMessage { - - - private int messageId; - - private Channel channel; - - private volatile ConfirmStatus confirmStatus; - - private long time; - - private byte[] byteBuf; - - private boolean isRetain; - - private MqttQoS qos; - - private String topic; - -} diff --git a/src/main/java/com/myself/nettychat/bootstrap/bean/SessionMessage.java b/src/main/java/com/myself/nettychat/bootstrap/bean/SessionMessage.java deleted file mode 100644 index 2613cd6..0000000 --- a/src/main/java/com/myself/nettychat/bootstrap/bean/SessionMessage.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.myself.nettychat.bootstrap.bean; - - -import io.netty.handler.codec.mqtt.MqttQoS; -import lombok.Builder; -import lombok.Data; - - -/** - * @author MySelf - * @create 2018/9/22 - * @desc Session会话数据保存 - **/ -@Builder -@Data -public class SessionMessage { - - private byte[] byteBuf; - - private MqttQoS qoS; - - private String topic; - - - public String getString(){ - return new String(byteBuf); - } - -} diff --git a/src/main/java/com/myself/nettychat/bootstrap/bean/WillMeaasge.java b/src/main/java/com/myself/nettychat/bootstrap/bean/WillMeaasge.java deleted file mode 100644 index 4022d28..0000000 --- a/src/main/java/com/myself/nettychat/bootstrap/bean/WillMeaasge.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.myself.nettychat.bootstrap.bean; - -import lombok.Builder; -import lombok.Data; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 遗嘱消息 - **/ -@Builder -@Data -public class WillMeaasge { - - private String willTopic; - - private String willMessage; - - private boolean isRetain; - - private int qos; - -} diff --git a/src/main/java/com/myself/nettychat/bootstrap/channel/AbstractChannelService.java b/src/main/java/com/myself/nettychat/bootstrap/channel/AbstractChannelService.java deleted file mode 100644 index c0e51f2..0000000 --- a/src/main/java/com/myself/nettychat/bootstrap/channel/AbstractChannelService.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.myself.nettychat.bootstrap.channel; - -import com.myself.nettychat.bootstrap.BaseApi; -import com.myself.nettychat.bootstrap.ChannelService; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.myself.nettychat.bootstrap.bean.MqttChannel; -import com.myself.nettychat.bootstrap.bean.RetainMessage; -import com.myself.nettychat.bootstrap.channel.cache.CacheMap; -import com.myself.nettychat.bootstrap.scan.ScanRunnable; -import io.netty.channel.Channel; -import io.netty.util.AttributeKey; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; - -import java.util.Collection; -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 抽象类 - **/ -@Slf4j -public abstract class AbstractChannelService extends PublishApiSevice implements ChannelService , BaseApi { - - protected AttributeKey _login = AttributeKey.valueOf("login"); - - protected AttributeKey _deviceId = AttributeKey.valueOf("deviceId"); - - protected static char SPLITOR = '/'; - - protected ExecutorService executorService =Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()*2); - - - protected static CacheMap cacheMap= new CacheMap<>(); - - - protected static ConcurrentHashMap mqttChannels = new ConcurrentHashMap<>(); // deviceId - mqChannel 登录 - - - protected static ConcurrentHashMap> retain = new ConcurrentHashMap<>(); // topic - 保留消息 - - - - protected static Cache> mqttChannelCache = CacheBuilder.newBuilder().maximumSize(100).build(); - - public AbstractChannelService(ScanRunnable scanRunnable) { - super(scanRunnable); - } - - - protected Collection getChannels(String topic,TopicFilter topicFilter){ - try { - return mqttChannelCache.get(topic, () -> topicFilter.filter(topic)); - } catch (Exception e) { - log.info(String.format("guava cache key topic【%s】 channel value== null ",topic)); - } - return null; - } - - - @FunctionalInterface - interface TopicFilter{ - Collection filter(String topic); - } - - protected boolean deleteChannel(String topic,MqttChannel mqttChannel){ - return Optional.ofNullable(topic).map(s -> { - mqttChannelCache.invalidate(s); - return cacheMap.delete(getTopic(s),mqttChannel); - }).orElse(false); - } - - protected boolean addChannel(String topic,MqttChannel mqttChannel) - { - return Optional.ofNullable(topic).map(s -> { - mqttChannelCache.invalidate(s); - return cacheMap.putData(getTopic(s),mqttChannel); - }).orElse(false); - } - - /** - * 获取channel - */ - public MqttChannel getMqttChannel(String deviceId){ - return Optional.ofNullable(deviceId).map(s -> mqttChannels.get(s)) - .orElse(null); - - } - - /** - * 获取channelId - */ - public String getDeviceId(Channel channel){ - return Optional.ofNullable(channel).map( channel1->channel1.attr(_deviceId).get()) - .orElse(null); - } - - - - protected String[] getTopic(String topic) { - return Optional.ofNullable(topic).map(s -> - StringUtils.split(topic,SPLITOR) - ).orElse(null); - } - -} diff --git a/src/main/java/com/myself/nettychat/bootstrap/channel/ClientSessionService.java b/src/main/java/com/myself/nettychat/bootstrap/channel/ClientSessionService.java deleted file mode 100644 index 9a23c8b..0000000 --- a/src/main/java/com/myself/nettychat/bootstrap/channel/ClientSessionService.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.myself.nettychat.bootstrap.channel; - -import com.myself.nettychat.bootstrap.bean.SessionMessage; -import org.springframework.stereotype.Service; - -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 会话保留处理 - **/ -@Service -public class ClientSessionService { - - private static ConcurrentHashMap> queueSession = new ConcurrentHashMap<>(); // 连接关闭后 保留此session 数据 deviceId - - - public void saveSessionMsg(String deviceId, SessionMessage sessionMessage) { - ConcurrentLinkedQueue sessionMessages = queueSession.getOrDefault(deviceId, new ConcurrentLinkedQueue<>()); - boolean flag; - do{ - flag = sessionMessages.add(sessionMessage); - } - while (!flag); - queueSession.put(deviceId,sessionMessages); - } - - public ConcurrentLinkedQueue getByteBuf(String deviceId){ - return Optional.ofNullable(deviceId).map(s -> queueSession.get(s)) - .orElse(null); - } - -} diff --git a/src/main/java/com/myself/nettychat/bootstrap/channel/MqttChannelService.java b/src/main/java/com/myself/nettychat/bootstrap/channel/MqttChannelService.java deleted file mode 100644 index fa5ec21..0000000 --- a/src/main/java/com/myself/nettychat/bootstrap/channel/MqttChannelService.java +++ /dev/null @@ -1,440 +0,0 @@ -package com.myself.nettychat.bootstrap.channel; - -import com.myself.nettychat.bootstrap.bean.*; -import com.myself.nettychat.bootstrap.scan.ScanRunnable; -import com.myself.nettychat.common.enums.ConfirmStatus; -import com.myself.nettychat.common.enums.SessionStatus; -import com.myself.nettychat.common.enums.SubStatus; -import com.myself.nettychat.common.exception.ConnectionException; -import com.myself.nettychat.common.utils.ByteBufUtil; -import io.netty.buffer.ByteBuf; -import io.netty.channel.Channel; -import io.netty.handler.codec.mqtt.*; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.springframework.util.CollectionUtils; - -import java.util.Collection; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.CopyOnWriteArraySet; - - -/** - * @author MySelf - * @create 2018/9/22 - * @desc Channel事件处理service - **/ -@Slf4j -@Component -public class MqttChannelService extends AbstractChannelService { - - @Autowired - private ClientSessionService clientSessionService; - - @Autowired - private WillService willService; - - private final ScanRunnable scanRunnable; - - public MqttChannelService(ScanRunnable scanRunnable) { - super(scanRunnable); - this.scanRunnable = scanRunnable; - } - - - /** - * 取消订阅 - */ - @Override - public void unsubscribe(String deviceId, List topics1) { - Optional.ofNullable(mqttChannels.get(deviceId)).ifPresent(mqttChannel -> { - topics1.forEach(topic -> { - deleteChannel(topic,mqttChannel); - }); - }); - } - - /** - * 登录成功后 回复 - */ - private void replyLogin(Channel channel, MqttConnectMessage mqttConnectMessage) { - MqttFixedHeader mqttFixedHeader1 = mqttConnectMessage.fixedHeader(); - MqttConnectVariableHeader mqttConnectVariableHeader = mqttConnectMessage.variableHeader(); - final MqttConnectPayload payload = mqttConnectMessage.payload(); - String deviceId = getDeviceId(channel); - MqttChannel build = MqttChannel.builder().channel(channel).cleanSession(mqttConnectVariableHeader.isCleanSession()) - .deviceId(payload.clientIdentifier()) - .sessionStatus(SessionStatus.OPEN) - .isWill(mqttConnectVariableHeader.isWillFlag()) - .subStatus(SubStatus.NO) - .topic(new CopyOnWriteArraySet<>()) - .message(new ConcurrentHashMap<>()) - .receive(new CopyOnWriteArraySet<>()) - .build(); - if (connectSuccess(deviceId, build)) { // 初始化存储mqttchannel - if (mqttConnectVariableHeader.isWillFlag()) { // 遗嘱消息标志 - boolean b = doIf(mqttConnectVariableHeader, mqttConnectVariableHeader1 -> (payload.willMessage() != null) - , mqttConnectVariableHeader1 -> (payload.willTopic() != null)); - if (!b) { - throw new ConnectionException("will message and will topic is not null"); - } - // 处理遗嘱消息 - final WillMeaasge buildWill = WillMeaasge.builder(). - qos(mqttConnectVariableHeader.willQos()) - .willMessage(deviceId) - .willTopic(payload.willTopic()) - .isRetain(mqttConnectVariableHeader.isWillRetain()) - .build(); - willService.save(payload.clientIdentifier(), buildWill); - } else { - willService.del(payload.clientIdentifier()); - boolean b = doIf(mqttConnectVariableHeader, mqttConnectVariableHeader1 -> (!mqttConnectVariableHeader1.isWillRetain()), - mqttConnectVariableHeader1 -> (mqttConnectVariableHeader1.willQos() == 0)); - if (!b) { - throw new ConnectionException("will retain should be null and will QOS equal 0"); - } - } - doIfElse(mqttConnectVariableHeader, mqttConnectVariableHeader1 -> (mqttConnectVariableHeader1.isCleanSession()), mqttConnectVariableHeader1 -> { - MqttConnectReturnCode connectReturnCode = MqttConnectReturnCode.CONNECTION_ACCEPTED; - MqttConnAckVariableHeader mqttConnAckVariableHeader = new MqttConnAckVariableHeader(connectReturnCode, false); - MqttFixedHeader mqttFixedHeader = new MqttFixedHeader( - MqttMessageType.CONNACK, mqttFixedHeader1.isDup(), MqttQoS.AT_MOST_ONCE, mqttFixedHeader1.isRetain(), 0x02); - MqttConnAckMessage connAck = new MqttConnAckMessage(mqttFixedHeader, mqttConnAckVariableHeader); - channel.writeAndFlush(connAck);// 清理会话 - }, mqttConnectVariableHeader1 -> { - MqttConnectReturnCode connectReturnCode = MqttConnectReturnCode.CONNECTION_ACCEPTED; - MqttConnAckVariableHeader mqttConnAckVariableHeader = new MqttConnAckVariableHeader(connectReturnCode, true); - MqttFixedHeader mqttFixedHeader = new MqttFixedHeader( - MqttMessageType.CONNACK, mqttFixedHeader1.isDup(), MqttQoS.AT_MOST_ONCE, mqttFixedHeader1.isRetain(), 0x02); - MqttConnAckMessage connAck = new MqttConnAckMessage(mqttFixedHeader, mqttConnAckVariableHeader); - channel.writeAndFlush(connAck);// 非清理会话 - - }); //发送 session 数据 - ConcurrentLinkedQueue sessionMessages = clientSessionService.getByteBuf(payload.clientIdentifier()); - doIfElse(sessionMessages, messages -> messages != null && !messages.isEmpty(), byteBufs -> { - SessionMessage sessionMessage; - while ((sessionMessage = byteBufs.poll()) != null) { - switch (sessionMessage.getQoS()) { - case EXACTLY_ONCE: - sendQosConfirmMsg(MqttQoS.EXACTLY_ONCE,getMqttChannel(deviceId), sessionMessage.getTopic(), sessionMessage.getByteBuf()); - break; - case AT_MOST_ONCE: - sendQos0Msg(channel, sessionMessage.getTopic(), sessionMessage.getByteBuf()); - break; - case AT_LEAST_ONCE: - sendQosConfirmMsg(MqttQoS.AT_LEAST_ONCE,getMqttChannel(deviceId), sessionMessage.getTopic(), sessionMessage.getByteBuf()); - break; - } - } - - }); - } - } - - - - /** - * qos2 第二步 - */ - @Override - public void doPubrel(Channel channel, int messageId) { - MqttChannel mqttChannel = getMqttChannel(getDeviceId(channel)); - doIfElse(mqttChannel,mqttChannel1 ->mqttChannel1.isLogin(),mqttChannel1 -> { - mqttChannel1.removeRecevice(messageId); - sendToPubComp(channel,messageId); - }); - } - - - - /** - * qos2 第三步 - */ - @Override - public void doPubrec(Channel channel, int mqttMessage) { - sendPubRel(channel,false,mqttMessage); - } - - /** - * 连接成功后 - * @param deviceId - * @param build - */ - @Override - public boolean connectSuccess(String deviceId, MqttChannel build) { - return Optional.ofNullable(mqttChannels.get(deviceId)) - .map(mqttChannel -> { - switch (mqttChannel.getSessionStatus()){ - case OPEN: - return false; - case CLOSE: - switch (mqttChannel.getSubStatus()){ - case YES: // 清除订阅 topic - deleteSubTopic(mqttChannel).stream() - .forEach(s -> cacheMap.putData(getTopic(s),build)); - break; - } - } - mqttChannels.put(deviceId,build); - return true; - }).orElseGet(() -> { - mqttChannels.put(deviceId,build); - return true; - }); - } - - - /** - * 订阅成功后 (发送保留消息) - */ - public void suscribeSuccess(String deviceId, Set topics){ - doIfElse(topics,topics1->!CollectionUtils.isEmpty(topics1),strings -> { - MqttChannel mqttChannel = mqttChannels.get(deviceId); - mqttChannel.setSubStatus(SubStatus.YES); // 设置订阅主题标识 - mqttChannel.addTopic(strings); - executorService.execute(() -> { - Optional.ofNullable(mqttChannel).ifPresent(mqttChannel1 -> { - if(mqttChannel1.isLogin()){ - strings.parallelStream().forEach(topic -> { - addChannel(topic,mqttChannel); - sendRetain(topic,mqttChannel); // 发送保留消息 - }); - } - }); - }); - }); - } - - - /** - *成功登陆 (发送会话消息) - * @param channel - * @param deviceId - * @param mqttConnectMessage - */ - @Override - public void loginSuccess(Channel channel, String deviceId, MqttConnectMessage mqttConnectMessage) { - channel.attr(_login).set(true); - channel.attr(_deviceId).set(deviceId); - replyLogin(channel, mqttConnectMessage); - } - - - /** - * 发布消息成功 () - * @param channel - * @param mqttPublishMessage - */ - @Override - public void publishSuccess(Channel channel, MqttPublishMessage mqttPublishMessage) { - MqttFixedHeader mqttFixedHeader = mqttPublishMessage.fixedHeader(); - MqttPublishVariableHeader mqttPublishVariableHeader = mqttPublishMessage.variableHeader(); - MqttChannel mqttChannel = getMqttChannel(getDeviceId(channel)); - ByteBuf payload = mqttPublishMessage.payload(); - byte[] bytes = ByteBufUtil.copyByteBuf(payload); // - int messageId = mqttPublishVariableHeader.messageId(); - executorService.execute(() -> { - if (channel.hasAttr(_login) && mqttChannel != null) { - boolean isRetain; - switch (mqttFixedHeader.qosLevel()) { - case AT_MOST_ONCE: // 至多一次 - break; - case AT_LEAST_ONCE: - sendPubBack(channel, messageId); - break; - case EXACTLY_ONCE: - sendPubRec(mqttChannel, messageId); - break; - } - if ((isRetain=mqttFixedHeader.isRetain()) && mqttFixedHeader.qosLevel() != MqttQoS.AT_MOST_ONCE) { //是保留消息 qos >0 - saveRetain(mqttPublishVariableHeader.topicName(), - RetainMessage.builder() - .byteBuf(bytes) - .qoS(mqttFixedHeader.qosLevel()) - .build(), false); - } else if (mqttFixedHeader.isRetain() && mqttFixedHeader.qosLevel() == MqttQoS.AT_MOST_ONCE) { // 是保留消息 qos=0 清除之前保留消息 保留现在 - saveRetain(mqttPublishVariableHeader.topicName(), - RetainMessage.builder() - .byteBuf(bytes) - .qoS(mqttFixedHeader.qosLevel()) - .build(), true); - } - if (!mqttChannel.checkRecevice(messageId)) { - push(mqttPublishVariableHeader.topicName(), mqttFixedHeader.qosLevel(), bytes,isRetain); - mqttChannel.addRecevice(messageId); - } - } - }); - - } - /** - * 推送消息给订阅者 - */ - private void push(String topic, MqttQoS qos, byte[] bytes, boolean isRetain){ - Collection subChannels = getChannels(topic, topic1 -> cacheMap.getData(getTopic(topic1))); - if(!CollectionUtils.isEmpty(subChannels)){ - subChannels.parallelStream().forEach(subChannel -> { - switch (subChannel.getSessionStatus()){ - case OPEN: // 在线 - if(subChannel.isActive()){ // 防止channel失效 但是离线状态没更改 - switch (qos){ - case AT_LEAST_ONCE: - sendQosConfirmMsg(MqttQoS.AT_LEAST_ONCE,subChannel,topic,bytes); - break; - case AT_MOST_ONCE: - sendQos0Msg(subChannel.getChannel(),topic,bytes); - break; - case EXACTLY_ONCE: - sendQosConfirmMsg(MqttQoS.EXACTLY_ONCE,subChannel,topic,bytes); - break; - } - } - else{ - if(!subChannel.isCleanSession() & !isRetain){ - clientSessionService.saveSessionMsg(subChannel.getDeviceId(), - SessionMessage.builder().byteBuf(bytes).qoS(qos).topic(topic).build() ); - break; - } - } - break; - case CLOSE: // 连接 设置了 clean session =false - clientSessionService.saveSessionMsg(subChannel.getDeviceId(), - SessionMessage.builder().byteBuf(bytes).qoS(qos).topic(topic).build() ); - break; - } - }); - } - } - - /** - * 关闭channel 操作 - * @param deviceId - */ - @Override - public void closeSuccess(String deviceId,boolean isDisconnect) { - if(StringUtils.isNotBlank(deviceId)){ - executorService.execute(() -> { - MqttChannel mqttChannel = mqttChannels.get(deviceId); - Optional.ofNullable(mqttChannel).ifPresent(mqttChannel1 -> { - mqttChannel1.setSessionStatus(SessionStatus.CLOSE); // 设置关闭 - mqttChannel1.close(); // 关闭channel - mqttChannel1.setChannel(null); - if(!mqttChannel1.isCleanSession()){ // 保持会话 - // 处理 qos1 未确认数据 - ConcurrentHashMap message = mqttChannel1.getMessage(); - Optional.ofNullable(message).ifPresent(integerConfirmMessageConcurrentHashMap -> { - integerConfirmMessageConcurrentHashMap.forEach((integer, confirmMessage) -> doIfElse(confirmMessage, sendMqttMessage ->sendMqttMessage.getConfirmStatus()== ConfirmStatus.PUB, sendMqttMessage ->{ - clientSessionService.saveSessionMsg(mqttChannel.getDeviceId(), SessionMessage.builder() - .byteBuf(sendMqttMessage.getByteBuf()) - .qoS(sendMqttMessage.getQos()) - .topic(sendMqttMessage.getTopic()) - .build()); // 把待确认数据转入session中 - } - )); - - }); - } - else{ // 删除sub topic-消息 - mqttChannels.remove(deviceId); // 移除channelId 不保持会话 直接删除 保持会话 旧的在重新connect时替换 - switch (mqttChannel1.getSubStatus()){ - case YES: - deleteSubTopic(mqttChannel1); - break; - } - } - if(mqttChannel1.isWill()){ // 发送遗言 - if(!isDisconnect){ // 不是disconnection操作 - willService.doSend(deviceId); - } - } - }); - }); - } - } - - /** - * 清除channel 订阅主题 - * @param mqttChannel - */ - public Set deleteSubTopic(MqttChannel mqttChannel){ - Set topics = mqttChannel.getTopic(); - topics.parallelStream().forEach(topic -> cacheMap.delete(getTopic(topic),mqttChannel)); - return topics; - } - - /** - * 发送 遗嘱消息(有的channel 已经关闭 但是保持了 session 此时加入session 数据中 ) - * @param willMeaasge 遗嘱消息 - */ - public void sendWillMsg(WillMeaasge willMeaasge){ - Collection mqttChannels = getChannels(willMeaasge.getWillTopic(), topic -> cacheMap.getData(getTopic(topic))); - if(!CollectionUtils.isEmpty(mqttChannels)){ - mqttChannels.forEach(mqttChannel -> { - switch (mqttChannel.getSessionStatus()){ - case CLOSE: - clientSessionService.saveSessionMsg(mqttChannel.getDeviceId(), - SessionMessage.builder() - .topic(willMeaasge.getWillTopic()) - .qoS(MqttQoS.valueOf(willMeaasge.getQos())) - .byteBuf(willMeaasge.getWillMessage().getBytes()).build()); - break; - case OPEN: - writeWillMsg(mqttChannel,willMeaasge); - break; - } - }); - } - } - - /** - * 保存保留消息 - * @param topic 主题 - * @param retainMessage 信息 - */ - private void saveRetain(String topic, RetainMessage retainMessage, boolean isClean){ - ConcurrentLinkedQueue retainMessages = retain.getOrDefault(topic, new ConcurrentLinkedQueue<>()); - if(!retainMessages.isEmpty() && isClean){ - retainMessages.clear(); - } - boolean flag; - do{ - flag = retainMessages.add(retainMessage); - } - while (!flag); - retain.put(topic, retainMessages); - } - - /** - * 发送保留消息 - */ - public void sendRetain(String topic,MqttChannel mqttChannel){ - retain.forEach((_topic, retainMessages) -> { - if(StringUtils.startsWith(_topic,topic)){ - Optional.ofNullable(retainMessages).ifPresent(pubMessages1 -> { - retainMessages.parallelStream().forEach(retainMessage -> { - log.info("【发送保留消息】"+mqttChannel.getChannel().remoteAddress()+":"+retainMessage.getString()+"【成功】"); - switch (retainMessage.getQoS()){ - case AT_MOST_ONCE: - sendQos0Msg(mqttChannel.getChannel(),_topic,retainMessage.getByteBuf()); - break; - case AT_LEAST_ONCE: - sendQosConfirmMsg(MqttQoS.AT_LEAST_ONCE,mqttChannel,_topic,retainMessage.getByteBuf()); - break; - case EXACTLY_ONCE: - sendQosConfirmMsg(MqttQoS.EXACTLY_ONCE,mqttChannel,_topic,retainMessage.getByteBuf()); - break; - } - }); - }); - } - }); - - } - -} diff --git a/src/main/java/com/myself/nettychat/bootstrap/channel/MqttHandlerService.java b/src/main/java/com/myself/nettychat/bootstrap/channel/MqttHandlerService.java deleted file mode 100644 index abc4d56..0000000 --- a/src/main/java/com/myself/nettychat/bootstrap/channel/MqttHandlerService.java +++ /dev/null @@ -1,223 +0,0 @@ -package com.myself.nettychat.bootstrap.channel; - -import com.myself.nettychat.bootstrap.BaseApi; -import com.myself.nettychat.bootstrap.BaseAuthService; -import com.myself.nettychat.bootstrap.ChannelService; -import com.myself.nettychat.bootstrap.bean.SendMqttMessage; -import com.myself.nettychat.common.enums.ConfirmStatus; -import com.myself.nettychat.common.mqtts.ServerMqttHandlerService; -import io.netty.channel.Channel; -import io.netty.handler.codec.mqtt.*; -import io.netty.handler.timeout.IdleStateEvent; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; - -@Slf4j -@Component -public class MqttHandlerService extends ServerMqttHandlerService implements BaseApi { - - @Autowired - ChannelService mqttChannelService; - - private final BaseAuthService baseAuthService; - - public MqttHandlerService(BaseAuthService baseAuthService) { - this.baseAuthService = baseAuthService; - } - - /** - * 登录 - * - */ - @Override - public boolean login(Channel channel, MqttConnectMessage mqttConnectMessage) { -// 校验规则 自定义校验规则 - MqttConnectPayload payload = mqttConnectMessage.payload(); - String deviceId = payload.clientIdentifier(); - if (StringUtils.isBlank(deviceId)) { - MqttConnectReturnCode connectReturnCode = MqttConnectReturnCode.CONNECTION_REFUSED_IDENTIFIER_REJECTED; - connectBack(channel,connectReturnCode); - return false; - } - - if(mqttConnectMessage.variableHeader().hasPassword() && mqttConnectMessage.variableHeader().hasUserName() - && !baseAuthService.authorized(payload.userName(),payload.password())){ - MqttConnectReturnCode connectReturnCode = MqttConnectReturnCode.CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD; - connectBack(channel,connectReturnCode); - return false; - } - return Optional.ofNullable(mqttChannelService.getMqttChannel(deviceId)) - .map(mqttChannel -> { - switch (mqttChannel.getSessionStatus()){ - case OPEN: - return false; - } - mqttChannelService.loginSuccess(channel, deviceId, mqttConnectMessage); - return true; - }).orElseGet(() -> { - mqttChannelService.loginSuccess(channel, deviceId, mqttConnectMessage); - return true; - }); - - } - - private void connectBack(Channel channel, MqttConnectReturnCode connectReturnCode){ - MqttConnAckVariableHeader mqttConnAckVariableHeader = new MqttConnAckVariableHeader(connectReturnCode, true); - MqttFixedHeader mqttFixedHeader = new MqttFixedHeader( - MqttMessageType.CONNACK,false, MqttQoS.AT_MOST_ONCE, false, 0x02); - MqttConnAckMessage connAck = new MqttConnAckMessage(mqttFixedHeader, mqttConnAckVariableHeader); - channel.writeAndFlush(connAck); - } - - - /** - * 发布 - */ - @Override - public void publish(Channel channel, MqttPublishMessage mqttPublishMessage) { - mqttChannelService.publishSuccess(channel, mqttPublishMessage); - } - - /** - * 订阅 - */ - @Override - public void subscribe(Channel channel, MqttSubscribeMessage mqttSubscribeMessage) { - Set topics = mqttSubscribeMessage.payload().topicSubscriptions().stream().map(mqttTopicSubscription -> - mqttTopicSubscription.topicName() - ).collect(Collectors.toSet()); - mqttChannelService.suscribeSuccess(mqttChannelService.getDeviceId(channel), topics); - subBack(channel, mqttSubscribeMessage, topics.size()); - } - - private void subBack(Channel channel, MqttSubscribeMessage mqttSubscribeMessage, int num) { - MqttFixedHeader mqttFixedHeader = new MqttFixedHeader(MqttMessageType.SUBACK, false, MqttQoS.AT_MOST_ONCE, false, 0); - MqttMessageIdVariableHeader variableHeader = MqttMessageIdVariableHeader.from(mqttSubscribeMessage.variableHeader().messageId()); - List grantedQoSLevels = new ArrayList<>(num); - for (int i = 0; i < num; i++) { - grantedQoSLevels.add(mqttSubscribeMessage.payload().topicSubscriptions().get(i).qualityOfService().value()); - } - MqttSubAckPayload payload = new MqttSubAckPayload(grantedQoSLevels); - MqttSubAckMessage mqttSubAckMessage = new MqttSubAckMessage(mqttFixedHeader, variableHeader, payload); - channel.writeAndFlush(mqttSubAckMessage); - } - - - /** - * 关闭通道 - */ - @Override - public void close(Channel channel) { - mqttChannelService.closeSuccess(mqttChannelService.getDeviceId(channel), false); - channel.close(); - } - - /** - * 回复pong消息 - */ - @Override - public void pong(Channel channel) { - if (channel.isOpen() && channel.isActive() && channel.isWritable()) { - log.info("收到来自:【" + channel.remoteAddress().toString() + "】心跳"); - MqttFixedHeader fixedHeader = new MqttFixedHeader(MqttMessageType.PINGRESP, false, MqttQoS.AT_MOST_ONCE, false, 0); - channel.writeAndFlush(new MqttMessage(fixedHeader)); - } - } - - /** - * 取消订阅 - */ - @Override - public void unsubscribe(Channel channel, MqttUnsubscribeMessage mqttMessage) { - List topics1 = mqttMessage.payload().topics(); - mqttChannelService.unsubscribe(mqttChannelService.getDeviceId(channel), topics1); - unSubBack(channel, mqttMessage.variableHeader().messageId()); - } - - /** - * 回复取消订阅 - */ - private void unSubBack(Channel channel, int messageId) { - MqttFixedHeader mqttFixedHeader = new MqttFixedHeader(MqttMessageType.UNSUBACK, false, MqttQoS.AT_MOST_ONCE, false, 0x02); - MqttMessageIdVariableHeader variableHeader = MqttMessageIdVariableHeader.from(messageId); - MqttUnsubAckMessage mqttUnsubAckMessage = new MqttUnsubAckMessage(mqttFixedHeader, variableHeader); - channel.writeAndFlush(mqttUnsubAckMessage); - } - - - /** - * 消息回复确认(qos1 级别 保证收到消息 但是可能会重复) - */ - @Override - public void puback(Channel channel, MqttMessage mqttMessage) { - MqttMessageIdVariableHeader messageIdVariableHeader = (MqttMessageIdVariableHeader) mqttMessage.variableHeader(); - int messageId = messageIdVariableHeader.messageId(); - mqttChannelService.getMqttChannel(mqttChannelService.getDeviceId(channel)).getSendMqttMessage(messageId).setConfirmStatus(ConfirmStatus.COMPLETE); // 复制为空 - } - - - /** - * disconnect 主动断线 - */ - @Override - public void disconnect(Channel channel) { - mqttChannelService.closeSuccess(mqttChannelService.getDeviceId(channel), true); - } - - - /** - * qos2 发布收到 - */ - @Override - public void pubrec(Channel channel, MqttMessage mqttMessage ) { - MqttMessageIdVariableHeader messageIdVariableHeader = (MqttMessageIdVariableHeader) mqttMessage.variableHeader(); - int messageId = messageIdVariableHeader.messageId(); - mqttChannelService.getMqttChannel(mqttChannelService.getDeviceId(channel)).getSendMqttMessage(messageId).setConfirmStatus(ConfirmStatus.PUBREL); // 复制为空 - mqttChannelService.doPubrec(channel, messageId); - } - - /** - * qos2 发布释放 - */ - @Override - public void pubrel(Channel channel, MqttMessage mqttMessage ) { - MqttMessageIdVariableHeader mqttMessageIdVariableHeader = (MqttMessageIdVariableHeader) mqttMessage.variableHeader(); - int messageId = mqttMessageIdVariableHeader.messageId(); - mqttChannelService.getMqttChannel(mqttChannelService.getDeviceId(channel)).getSendMqttMessage(messageId).setConfirmStatus(ConfirmStatus.COMPLETE); // 复制为空 - mqttChannelService.doPubrel(channel, messageId); - - } - - /** - * qos2 发布完成 - */ - @Override - public void pubcomp(Channel channel, MqttMessage mqttMessage ) { - MqttMessageIdVariableHeader mqttMessageIdVariableHeader = (MqttMessageIdVariableHeader) mqttMessage.variableHeader(); - int messageId = mqttMessageIdVariableHeader.messageId(); - SendMqttMessage sendMqttMessage = mqttChannelService.getMqttChannel(mqttChannelService.getDeviceId(channel)).getSendMqttMessage(messageId); - sendMqttMessage.setConfirmStatus(ConfirmStatus.COMPLETE); // 复制为空 - } - - @Override - public void doTimeOut(Channel channel, IdleStateEvent evt) { - log.info("【PingPongService:doTimeOut 心跳超时】" + channel.remoteAddress() + "【channel 关闭】"); - switch (evt.state()) { - case READER_IDLE: - close(channel); - case WRITER_IDLE: - close(channel); - case ALL_IDLE: - close(channel); - } - } - -} diff --git a/src/main/java/com/myself/nettychat/bootstrap/channel/PublishApiSevice.java b/src/main/java/com/myself/nettychat/bootstrap/channel/PublishApiSevice.java deleted file mode 100644 index 4af733f..0000000 --- a/src/main/java/com/myself/nettychat/bootstrap/channel/PublishApiSevice.java +++ /dev/null @@ -1,162 +0,0 @@ -package com.myself.nettychat.bootstrap.channel; - -import com.myself.nettychat.bootstrap.bean.MqttChannel; -import com.myself.nettychat.bootstrap.bean.SendMqttMessage; -import com.myself.nettychat.bootstrap.bean.WillMeaasge; -import com.myself.nettychat.bootstrap.scan.ScanRunnable; -import com.myself.nettychat.common.utils.MessageId; -import com.myself.nettychat.common.enums.ConfirmStatus; -import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; -import io.netty.handler.codec.mqtt.*; -import lombok.extern.slf4j.Slf4j; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 发送消息以及确认 - **/ -@Slf4j -public class PublishApiSevice { - - private final ScanRunnable scanRunnable; - - public PublishApiSevice(ScanRunnable scanRunnable) { - this.scanRunnable = scanRunnable; - } - - - /** - * 写入遗嘱消息 - */ - protected void writeWillMsg(MqttChannel mqttChannel, WillMeaasge willMeaasge) { -// dup保证消息可靠传输,默认为0,只占用一个字节,表示第一次发送。不能用于检测消息重复发送等 - switch (willMeaasge.getQos()){ - case 0: // qos0 - sendQos0Msg(mqttChannel.getChannel(),willMeaasge.getWillTopic(),willMeaasge.getWillMessage().getBytes()); - break; - case 1: // qos1 - sendQosConfirmMsg(MqttQoS.AT_LEAST_ONCE,mqttChannel,willMeaasge.getWillTopic(),willMeaasge.getWillMessage().getBytes()); - break; - case 2: // qos2 - sendQosConfirmMsg(MqttQoS.EXACTLY_ONCE,mqttChannel,willMeaasge.getWillTopic(),willMeaasge.getWillMessage().getBytes()); - break; - } - - - } - - protected void sendQosConfirmMsg(MqttQoS qos, MqttChannel mqttChannel, String topic, byte[] bytes) { - if(mqttChannel.isLogin()){ - int messageId = MessageId.messageId(); - switch (qos){ - case AT_LEAST_ONCE: - mqttChannel.addSendMqttMessage(messageId,sendQos1Msg(mqttChannel.getChannel(),topic,false,bytes,messageId)); - break; - case EXACTLY_ONCE: - mqttChannel.addSendMqttMessage(messageId,sendQos2Msg(mqttChannel.getChannel(),topic,false,bytes,messageId)); - break; - } - } - - } - - - /** - * 发送 qos1 类的消息 - */ - private SendMqttMessage sendQos1Msg(Channel channel, String topic, boolean isDup, byte[] byteBuf, int messageId){ - MqttFixedHeader mqttFixedHeader = new MqttFixedHeader(MqttMessageType.PUBLISH,isDup, MqttQoS.AT_LEAST_ONCE,false,0); - MqttPublishVariableHeader mqttPublishVariableHeader = new MqttPublishVariableHeader(topic,messageId ); - MqttPublishMessage mqttPublishMessage = new MqttPublishMessage(mqttFixedHeader,mqttPublishVariableHeader, Unpooled.wrappedBuffer(byteBuf)); - channel.writeAndFlush(mqttPublishMessage); - return addQueue(channel,messageId,topic,byteBuf,MqttQoS.AT_LEAST_ONCE, ConfirmStatus.PUB); - } - - - - /** - * 发送 qos0 类的消息 byte - */ - protected void sendQos0Msg(Channel channel, String topic, byte[] byteBuf){ - if(channel!=null){ - sendQos0Msg(channel,topic,byteBuf,0); - } - } - private void sendQos0Msg(Channel channel, String topic, byte[] byteBuf,int messageId){ - MqttFixedHeader mqttFixedHeader = new MqttFixedHeader(MqttMessageType.PUBLISH,false, MqttQoS.AT_MOST_ONCE,false,0); - MqttPublishVariableHeader mqttPublishVariableHeader = new MqttPublishVariableHeader(topic,messageId ); - MqttPublishMessage mqttPublishMessage = new MqttPublishMessage(mqttFixedHeader,mqttPublishVariableHeader,Unpooled.wrappedBuffer(byteBuf)); - channel.writeAndFlush(mqttPublishMessage); - } - - - - - private SendMqttMessage sendQos2Msg(Channel channel, String topic,boolean isDup, byte[] byteBuf, int messageId) { - MqttFixedHeader mqttFixedHeader = new MqttFixedHeader(MqttMessageType.PUBLISH,isDup, MqttQoS.EXACTLY_ONCE,false,0); - MqttPublishVariableHeader mqttPublishVariableHeader = new MqttPublishVariableHeader(topic,messageId ); - MqttPublishMessage mqttPublishMessage = new MqttPublishMessage(mqttFixedHeader,mqttPublishVariableHeader, Unpooled.wrappedBuffer(byteBuf)); - channel.writeAndFlush(mqttPublishMessage); - return addQueue(channel,messageId,topic,byteBuf,MqttQoS.EXACTLY_ONCE,ConfirmStatus.PUB); - } - - - /** - * 发送qos1 publish 确认消息 - */ - protected void sendPubBack(Channel channel,int messageId){ - MqttFixedHeader mqttFixedHeader = new MqttFixedHeader(MqttMessageType.PUBACK,false, MqttQoS.AT_MOST_ONCE,false,0x02); - MqttMessageIdVariableHeader from = MqttMessageIdVariableHeader.from(messageId); - MqttPubAckMessage mqttPubAckMessage = new MqttPubAckMessage(mqttFixedHeader,from); - channel.writeAndFlush(mqttPubAckMessage); - } - - - /** - * 发送qos2 publish 确认消息 第一步 - */ - protected void sendPubRec( MqttChannel mqttChannel,int messageId){ - MqttFixedHeader mqttFixedHeader = new MqttFixedHeader(MqttMessageType.PUBREC,false, MqttQoS.AT_LEAST_ONCE,false,0x02); - MqttMessageIdVariableHeader from = MqttMessageIdVariableHeader.from(messageId); - MqttPubAckMessage mqttPubAckMessage = new MqttPubAckMessage(mqttFixedHeader,from); - Channel channel = mqttChannel.getChannel(); - channel.writeAndFlush(mqttPubAckMessage); - SendMqttMessage sendMqttMessage = addQueue(channel, messageId, null, null, null, ConfirmStatus.PUBREC); - mqttChannel.addSendMqttMessage(messageId,sendMqttMessage); - } - - /** - * 发送qos2 publish 确认消息 第二步 - */ - protected void sendPubRel(Channel channel,boolean isDup,int messageId){ - MqttFixedHeader mqttFixedHeader = new MqttFixedHeader(MqttMessageType.PUBREL,isDup, MqttQoS.AT_LEAST_ONCE,false,0x02); - MqttMessageIdVariableHeader from = MqttMessageIdVariableHeader.from(messageId); - MqttPubAckMessage mqttPubAckMessage = new MqttPubAckMessage(mqttFixedHeader,from); - channel.writeAndFlush(mqttPubAckMessage); - } - - /** - * 发送qos2 publish 确认消息 第三步 - */ - protected void sendToPubComp(Channel channel,int messageId){ - MqttFixedHeader mqttFixedHeader = new MqttFixedHeader(MqttMessageType.PUBCOMP,false, MqttQoS.AT_MOST_ONCE,false,0x02); - MqttMessageIdVariableHeader from = MqttMessageIdVariableHeader.from(messageId); - MqttPubAckMessage mqttPubAckMessage = new MqttPubAckMessage(mqttFixedHeader,from); - channel.writeAndFlush(mqttPubAckMessage); - } - - private SendMqttMessage addQueue(Channel channel,int messageId,String topic,byte[] datas,MqttQoS mqttQoS,ConfirmStatus confirmStatus){ - SendMqttMessage build = SendMqttMessage.builder(). - channel(channel). - confirmStatus(confirmStatus). - messageId(messageId) - .topic(topic) - .qos(mqttQoS) - .byteBuf(datas) - .time(System.currentTimeMillis()).build(); - scanRunnable.addQueue(build); - return build; - } - -} diff --git a/src/main/java/com/myself/nettychat/bootstrap/channel/WillService.java b/src/main/java/com/myself/nettychat/bootstrap/channel/WillService.java deleted file mode 100644 index 3aa4213..0000000 --- a/src/main/java/com/myself/nettychat/bootstrap/channel/WillService.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.myself.nettychat.bootstrap.channel; - -import com.myself.nettychat.bootstrap.BaseApi; -import com.myself.nettychat.bootstrap.ChannelService; -import com.myself.nettychat.bootstrap.bean.WillMeaasge; -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.concurrent.ConcurrentHashMap; - -@Slf4j -@Component -@Data -@NoArgsConstructor -public class WillService implements BaseApi { - - @Autowired - ChannelService channelService; - - private static ConcurrentHashMap willMeaasges = new ConcurrentHashMap<>(); // deviceid -WillMeaasge - - - - /** - * 保存遗嘱消息 - */ - public void save(String deviceid, WillMeaasge build) { - willMeaasges.put(deviceid,build); // 替换旧的 - } - - - public void doSend( String deviceId) { // 客户端断开连接后 开启遗嘱消息发送 - if(StringUtils.isNotBlank(deviceId)&&(willMeaasges.get(deviceId))!=null){ - WillMeaasge willMeaasge = willMeaasges.get(deviceId); - channelService.sendWillMsg(willMeaasge); // 发送遗嘱消息 - if(!willMeaasge.isRetain()){ // 移除 - willMeaasges.remove(deviceId); - log.info("deviceId will message["+willMeaasge.getWillMessage()+"] is removed"); - } - } - } - - /** - * 删除遗嘱消息 - */ - public void del(String deviceid ) {willMeaasges.remove(deviceid);} - -} diff --git a/src/main/java/com/myself/nettychat/bootstrap/channel/cache/CacheMap.java b/src/main/java/com/myself/nettychat/bootstrap/channel/cache/CacheMap.java deleted file mode 100644 index 68f805e..0000000 --- a/src/main/java/com/myself/nettychat/bootstrap/channel/cache/CacheMap.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.myself.nettychat.bootstrap.channel.cache; - -import lombok.extern.slf4j.Slf4j; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArrayList; -/** - * @author MySelf - * @create 2018/9/22 - * @desc 缓存操作 - **/ -@Slf4j -public class CacheMap { - - private ConcurrentHashMap> datas = new ConcurrentHashMap<>(); - - public boolean putData(K[] topic, V v){ - if(topic.length==1){ - Node kvNode = buildOne(topic[0], v); - if(kvNode!=null && kvNode.topic.equals(topic[0])){ - return true; - } - } - else{ - Node kvNode = buildOne(topic[0], null); - for(int i=1;i kvNode = datas.get(ks[0]); - for(int i=1;i getData(K[] ks){ - if(ks.length==1){ - return datas.get(ks[0]).get(); - } - else{ - Node node = datas.get(ks[0]); - if(node!=null){ - List all = new ArrayList<>(); - all.addAll(node.get()); - for(int i=1;i buildOne(K k,V v){ - - Node node = this.datas.computeIfAbsent(k, key -> { - Node kObjectNode = new Node<>(k); - return kObjectNode; - }); - if(v!=null){ - node.put(v); - } - return node; - } - - - - class Node{ - - private final K topic; - - - private volatile ConcurrentHashMap> map =new ConcurrentHashMap<>() ; - - - List vs = new CopyOnWriteArrayList<>(); - - - public K getTopic() {return topic;} - - Node(K topic) { - this.topic = topic; - } - - public boolean delValue(V v){ - return vs.remove(v); - } - - public Node putNextValue(K k,V v){ - Node kvNode = map.computeIfAbsent(k, key -> { - Node node = new Node<>(k); - return node; - }); - if(v!=null){ - kvNode.put(v); - } - return kvNode; - } - - - public Node getNext(K k){ - return map.get(k); - } - - - public boolean put(V v){ - return vs.add(v); - } - - - public List get(){ - return vs; - } - } - -} diff --git a/src/main/java/com/myself/nettychat/bootstrap/coder/ByteBufToWebSocketFrameEncoder.java b/src/main/java/com/myself/nettychat/bootstrap/coder/ByteBufToWebSocketFrameEncoder.java deleted file mode 100644 index 6c34606..0000000 --- a/src/main/java/com/myself/nettychat/bootstrap/coder/ByteBufToWebSocketFrameEncoder.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.myself.nettychat.bootstrap.coder; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.MessageToMessageEncoder; -import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; - -import java.util.List; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 转换 - **/ -public class ByteBufToWebSocketFrameEncoder extends MessageToMessageEncoder { - - @Override - protected void encode(ChannelHandlerContext ctx, ByteBuf byteBuf, List out) throws Exception { - if (byteBuf == null) { - return; - } - BinaryWebSocketFrame result = new BinaryWebSocketFrame(); - result.content().writeBytes(byteBuf); - out.add(result); - } -} diff --git a/src/main/java/com/myself/nettychat/bootstrap/coder/WebSocketFrameToByteBufDecoder.java b/src/main/java/com/myself/nettychat/bootstrap/coder/WebSocketFrameToByteBufDecoder.java deleted file mode 100644 index 032d657..0000000 --- a/src/main/java/com/myself/nettychat/bootstrap/coder/WebSocketFrameToByteBufDecoder.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.myself.nettychat.bootstrap.coder; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.MessageToMessageDecoder; -import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; - -import java.util.List; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 转换 - **/ -public class WebSocketFrameToByteBufDecoder extends MessageToMessageDecoder { - - - @Override - protected void decode(ChannelHandlerContext ctx, BinaryWebSocketFrame wsFrame, List out) throws Exception { - ByteBuf buf = wsFrame.content(); - //避免计数器为0,报错 - buf.retain(); - out.add(buf); - } -} diff --git a/src/main/java/com/myself/nettychat/bootstrap/handler/DefaultMqttHandler.java b/src/main/java/com/myself/nettychat/bootstrap/handler/DefaultMqttHandler.java deleted file mode 100644 index 8c4fbee..0000000 --- a/src/main/java/com/myself/nettychat/bootstrap/handler/DefaultMqttHandler.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.myself.nettychat.bootstrap.handler; - -import com.myself.nettychat.bootstrap.ChannelService; -import com.myself.nettychat.bootstrap.bean.MqttChannel; -import com.myself.nettychat.common.mqtts.MqttHandlerIntf; -import com.myself.nettychat.common.mqtts.MqttHander; -import com.myself.nettychat.common.mqtts.ServerMqttHandlerService; -import com.myself.nettychat.common.exception.NoFindHandlerException; -import io.netty.channel.Channel; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.mqtt.*; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 默认MQTTHandler处理 - **/ -@Slf4j -@Component -@ChannelHandler.Sharable -public class DefaultMqttHandler extends MqttHander { - - private final MqttHandlerIntf mqttHandlerApi; - - @Autowired - ChannelService channelService; - - - public DefaultMqttHandler(MqttHandlerIntf mqttHandlerApi) { - super(mqttHandlerApi); - this.mqttHandlerApi = mqttHandlerApi; - } - - @Override - public void doMessage(ChannelHandlerContext channelHandlerContext, MqttMessage mqttMessage) { - Channel channel = channelHandlerContext.channel(); - ServerMqttHandlerService serverMqttHandlerService; - if(mqttHandlerApi instanceof ServerMqttHandlerService){ - serverMqttHandlerService =(ServerMqttHandlerService)mqttHandlerApi; - } - else{ - throw new NoFindHandlerException("server handler 不匹配"); - } - MqttFixedHeader mqttFixedHeader = mqttMessage.fixedHeader(); - if(mqttFixedHeader.messageType().equals(MqttMessageType.CONNECT)){ - if(!serverMqttHandlerService.login(channel, (MqttConnectMessage) mqttMessage)){ - channel.close(); - } - return ; - } - MqttChannel mqttChannel = channelService.getMqttChannel(channelService.getDeviceId(channel)); - if(mqttChannel!=null && mqttChannel.isLogin()){ - switch (mqttFixedHeader.messageType()){ - case PUBLISH: - serverMqttHandlerService.publish(channel, (MqttPublishMessage) mqttMessage); - break; - case SUBSCRIBE: - serverMqttHandlerService.subscribe(channel, (MqttSubscribeMessage) mqttMessage); - break; - case PINGREQ: - serverMqttHandlerService.pong(channel); - break; - case DISCONNECT: - serverMqttHandlerService.disconnect(channel); - break; - case UNSUBSCRIBE: - serverMqttHandlerService.unsubscribe(channel,(MqttUnsubscribeMessage)mqttMessage); - break; - case PUBACK: - mqttHandlerApi.puback(channel,mqttMessage); - break; - case PUBREC: - mqttHandlerApi.pubrec(channel,mqttMessage); - break; - case PUBREL: - mqttHandlerApi.pubrel(channel,mqttMessage); - break; - case PUBCOMP: - mqttHandlerApi.pubcomp(channel,mqttMessage); - break; - default: - break; - } - } - } - - - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - log.info("【DefaultMqttHandler:channelActive】"+ctx.channel().remoteAddress().toString()+"链接成功"); - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - log.error("exception",cause); - mqttHandlerApi.close(ctx.channel()); - } - -} diff --git a/src/main/java/com/myself/nettychat/bootstrap/scan/SacnScheduled.java b/src/main/java/com/myself/nettychat/bootstrap/scan/SacnScheduled.java deleted file mode 100644 index 15cc0ce..0000000 --- a/src/main/java/com/myself/nettychat/bootstrap/scan/SacnScheduled.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.myself.nettychat.bootstrap.scan; - -import com.myself.nettychat.bootstrap.bean.SendMqttMessage; -import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; -import io.netty.handler.codec.mqtt.*; -import lombok.extern.slf4j.Slf4j; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 扫描消息确认 - **/ -@Slf4j -public class SacnScheduled extends ScanRunnable { - - private final long time; - - public SacnScheduled(long time) { - this.time = time; - } - - private boolean checkTime(long time) { - return System.currentTimeMillis()-time>=10*1000; - } - - @Override - public void doInfo(SendMqttMessage poll) { - if(checkTime(poll.getTime()) && poll.getChannel().isActive()){ - poll.setTime(System.currentTimeMillis()); - switch (poll.getConfirmStatus()){ - case PUB: - pubMessage(poll.getChannel(),poll); - break; - case PUBREL: - sendAck(MqttMessageType.PUBREL,poll); - break; - case PUBREC: - sendAck(MqttMessageType.PUBREC,poll); - break; - } - } - } - - private void pubMessage(Channel channel, SendMqttMessage mqttMessage){ - MqttFixedHeader mqttFixedHeader = new MqttFixedHeader(MqttMessageType.PUBLISH,true, mqttMessage.getQos(),mqttMessage.isRetain(),0); - MqttPublishVariableHeader mqttPublishVariableHeader = new MqttPublishVariableHeader(mqttMessage.getTopic(),mqttMessage.getMessageId()); - MqttPublishMessage mqttPublishMessage = new MqttPublishMessage(mqttFixedHeader,mqttPublishVariableHeader, Unpooled.wrappedBuffer(mqttMessage.getByteBuf())); - channel.writeAndFlush(mqttPublishMessage); - } - - protected void sendAck(MqttMessageType type,SendMqttMessage mqttMessage){ - MqttFixedHeader mqttFixedHeader = new MqttFixedHeader(type,true, MqttQoS.AT_LEAST_ONCE,false,0x02); - MqttMessageIdVariableHeader from = MqttMessageIdVariableHeader.from(mqttMessage.getMessageId()); - MqttPubAckMessage mqttPubAckMessage = new MqttPubAckMessage(mqttFixedHeader,from); - mqttMessage.getChannel().writeAndFlush(mqttPubAckMessage); - } - -} diff --git a/src/main/java/com/myself/nettychat/bootstrap/scan/ScanRunnable.java b/src/main/java/com/myself/nettychat/bootstrap/scan/ScanRunnable.java deleted file mode 100644 index 4d4cc8c..0000000 --- a/src/main/java/com/myself/nettychat/bootstrap/scan/ScanRunnable.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.myself.nettychat.bootstrap.scan; - -import com.myself.nettychat.bootstrap.bean.SendMqttMessage; -import lombok.extern.slf4j.Slf4j; -import com.myself.nettychat.common.enums.ConfirmStatus; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 扫描未确认的消息 - **/ -@Slf4j -public abstract class ScanRunnable implements Runnable{ - - LinkedBlockingQueue queue =new LinkedBlockingQueue(); - - public boolean addQueue(SendMqttMessage t){ - return queue.add(t); - } - - public boolean addQueues(List ts){ - return queue.addAll(ts); - } - - - @Override - public void run() { - for(;;){ - try { - SendMqttMessage poll= queue.take(); - if(poll.getConfirmStatus()!= ConfirmStatus.COMPLETE){ - doInfo(poll); - queue.offer(poll); - } - } catch (InterruptedException e) { - log.error("scan InterruptedException",e); - } - } - } - public abstract void doInfo( SendMqttMessage poll); - -} diff --git a/src/main/java/com/myself/nettychat/common/enums/ConfirmStatus.java b/src/main/java/com/myself/nettychat/common/enums/ConfirmStatus.java deleted file mode 100644 index 968b807..0000000 --- a/src/main/java/com/myself/nettychat/common/enums/ConfirmStatus.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.myself.nettychat.common.enums; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 确认状态 - **/ -public enum ConfirmStatus { - PUB, - PUBREC, - PUBREL, - COMPLETE, -} diff --git a/src/main/java/com/myself/nettychat/common/enums/ProtocolEnum.java b/src/main/java/com/myself/nettychat/common/enums/ProtocolEnum.java deleted file mode 100644 index 19855ea..0000000 --- a/src/main/java/com/myself/nettychat/common/enums/ProtocolEnum.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.myself.nettychat.common.enums; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 协议 - **/ -public enum ProtocolEnum { - MQTT, - - MQTT_WS_MQTT, - - MQTT_WS_PAHO, -} diff --git a/src/main/java/com/myself/nettychat/common/enums/QosStatus.java b/src/main/java/com/myself/nettychat/common/enums/QosStatus.java deleted file mode 100644 index 0a3643a..0000000 --- a/src/main/java/com/myself/nettychat/common/enums/QosStatus.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.myself.nettychat.common.enums; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc Qos确认状态 - **/ -public enum QosStatus { - - PUBD, // 已发送 没收到RECD (发送) - - RECD, //publish 推送回复过(发送) - -} diff --git a/src/main/java/com/myself/nettychat/common/enums/SessionStatus.java b/src/main/java/com/myself/nettychat/common/enums/SessionStatus.java deleted file mode 100644 index 593d63f..0000000 --- a/src/main/java/com/myself/nettychat/common/enums/SessionStatus.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.myself.nettychat.common.enums; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc Channel 会话状态 - **/ -public enum SessionStatus { - - OPEN, - CLOSE - -} diff --git a/src/main/java/com/myself/nettychat/common/enums/SubStatus.java b/src/main/java/com/myself/nettychat/common/enums/SubStatus.java deleted file mode 100644 index 2ab833c..0000000 --- a/src/main/java/com/myself/nettychat/common/enums/SubStatus.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.myself.nettychat.common.enums; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 是否订阅过主题 - **/ -public enum SubStatus { - YES, - NO -} diff --git a/src/main/java/com/myself/nettychat/common/exception/ConnectionException.java b/src/main/java/com/myself/nettychat/common/exception/ConnectionException.java deleted file mode 100644 index 76d1cb2..0000000 --- a/src/main/java/com/myself/nettychat/common/exception/ConnectionException.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.myself.nettychat.common.exception; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 连接异常 - **/ -public class ConnectionException extends RuntimeException { - - public ConnectionException(String message) { - super(message); - } - -} diff --git a/src/main/java/com/myself/nettychat/common/exception/NoFindHandlerException.java b/src/main/java/com/myself/nettychat/common/exception/NoFindHandlerException.java deleted file mode 100644 index 1b1ed2a..0000000 --- a/src/main/java/com/myself/nettychat/common/exception/NoFindHandlerException.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.myself.nettychat.common.exception; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 找不到Handler异常 - **/ -public class NoFindHandlerException extends RuntimeException { - - public NoFindHandlerException(String message) { - super(message); - } - -} diff --git a/src/main/java/com/myself/nettychat/common/ip/IpUtils.java b/src/main/java/com/myself/nettychat/common/ip/IpUtils.java deleted file mode 100644 index 4ccfc3d..0000000 --- a/src/main/java/com/myself/nettychat/common/ip/IpUtils.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.myself.nettychat.common.ip; - -import java.net.Inet4Address; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.util.Enumeration; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc ip操作 - **/ -public class IpUtils { - - /*** - * 获取外网IP - * @return - */ - public static String internetIp() { - try { - - Enumeration networks = NetworkInterface.getNetworkInterfaces(); - InetAddress inetAddress = null; - Enumeration inetAddresses = null; - while (networks.hasMoreElements()) { - inetAddresses = networks.nextElement().getInetAddresses(); - while (inetAddresses.hasMoreElements()) { - inetAddress = inetAddresses.nextElement(); - if (inetAddress != null - && inetAddress instanceof Inet4Address - && !inetAddress.isSiteLocalAddress() - && !inetAddress.isLoopbackAddress() - && inetAddress.getHostAddress().indexOf(":") == -1) { - return inetAddress.getHostAddress(); - } - } - } - - return null; - - } catch (Exception e) { - - throw new RuntimeException(e); - } - } - - /** - * 获取内网IP - * - * @return - */ - public static String intranetIp() { - try { - return InetAddress.getLocalHost().getHostAddress(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - /** - * 获取服务启动host - * @return - */ - public static String getHost(){ - return internetIp()==null?intranetIp():internetIp(); - } - -} diff --git a/src/main/java/com/myself/nettychat/common/mqtts/ClientMqttHandlerService.java b/src/main/java/com/myself/nettychat/common/mqtts/ClientMqttHandlerService.java deleted file mode 100644 index 56f9fda..0000000 --- a/src/main/java/com/myself/nettychat/common/mqtts/ClientMqttHandlerService.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.myself.nettychat.common.mqtts; - -import io.netty.channel.Channel; -import io.netty.handler.codec.mqtt.*; -import io.netty.handler.timeout.IdleStateEvent; - - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 抽象出客户端的事件 - **/ -public abstract class ClientMqttHandlerService implements MqttHandlerIntf { - - @Override - public void doTimeOut(Channel channel, IdleStateEvent evt) { - heart(channel,evt); - } - - public abstract void heart(Channel channel, IdleStateEvent evt); - - public abstract void suback(Channel channel,MqttSubAckMessage mqttMessage) ; - - public abstract void pubBackMessage(Channel channel, int i); - - public abstract void unsubBack(Channel channel, MqttMessage mqttMessage); -} diff --git a/src/main/java/com/myself/nettychat/common/mqtts/MqttHander.java b/src/main/java/com/myself/nettychat/common/mqtts/MqttHander.java deleted file mode 100644 index 061dd77..0000000 --- a/src/main/java/com/myself/nettychat/common/mqtts/MqttHander.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.myself.nettychat.common.mqtts; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.handler.codec.mqtt.MqttFixedHeader; -import io.netty.handler.codec.mqtt.MqttMessage; -import io.netty.handler.timeout.IdleStateEvent; -import lombok.extern.slf4j.Slf4j; - -import java.util.Optional; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc mtqq协议处理器 - **/ -@Slf4j -public abstract class MqttHander extends SimpleChannelInboundHandler { - - MqttHandlerIntf mqttHandlerApi; - - public MqttHander(MqttHandlerIntf mqttHandlerIntf){ - this.mqttHandlerApi=mqttHandlerIntf; - } - - @Override - protected void channelRead0(ChannelHandlerContext channelHandlerContext, MqttMessage mqttMessage) throws Exception { - MqttFixedHeader mqttFixedHeader = mqttMessage.fixedHeader(); - Optional.ofNullable(mqttFixedHeader) - .ifPresent(mqttFixedHeader1 -> doMessage(channelHandlerContext,mqttMessage)); - } - - - public abstract void doMessage(ChannelHandlerContext channelHandlerContext, MqttMessage mqttMessage); - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - log.info("【DefaultMqttHandler:channelInactive】"+ctx.channel().localAddress().toString()+"关闭成功"); - mqttHandlerApi.close(ctx.channel()); - } - - @Override - public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { - if(evt instanceof IdleStateEvent){ - mqttHandlerApi.doTimeOut(ctx.channel(),(IdleStateEvent)evt); - } - super.userEventTriggered(ctx, evt); - } - -} diff --git a/src/main/java/com/myself/nettychat/common/mqtts/MqttHandlerIntf.java b/src/main/java/com/myself/nettychat/common/mqtts/MqttHandlerIntf.java deleted file mode 100644 index 4f274ee..0000000 --- a/src/main/java/com/myself/nettychat/common/mqtts/MqttHandlerIntf.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.myself.nettychat.common.mqtts; - -import io.netty.channel.Channel; -import io.netty.handler.codec.mqtt.MqttMessage; -import io.netty.handler.timeout.IdleStateEvent; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 自定义 对外暴露,消息处理API - **/ -public interface MqttHandlerIntf { - - void close(Channel channel); - - void puback(Channel channel, MqttMessage mqttMessage); - - void pubrec(Channel channel, MqttMessage mqttMessage); - - void pubrel(Channel channel, MqttMessage mqttMessage); - - void pubcomp(Channel channel, MqttMessage mqttMessage); - - void doTimeOut(Channel channel, IdleStateEvent evt); - -} diff --git a/src/main/java/com/myself/nettychat/common/mqtts/ServerMqttHandlerService.java b/src/main/java/com/myself/nettychat/common/mqtts/ServerMqttHandlerService.java deleted file mode 100644 index fd62ee5..0000000 --- a/src/main/java/com/myself/nettychat/common/mqtts/ServerMqttHandlerService.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.myself.nettychat.common.mqtts; - -import io.netty.channel.Channel; -import io.netty.handler.codec.mqtt.*; -import io.netty.handler.timeout.IdleStateEvent; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 抽象出服务端的事件 - **/ -public abstract class ServerMqttHandlerService implements MqttHandlerIntf { - - public abstract boolean login(Channel channel, MqttConnectMessage mqttConnectMessage); - - public abstract void publish(Channel channel, MqttPublishMessage mqttPublishMessage); - - public abstract void subscribe(Channel channel, MqttSubscribeMessage mqttSubscribeMessage); - - public abstract void pong(Channel channel); - - public abstract void unsubscribe(Channel channel, MqttUnsubscribeMessage mqttMessage); - - public abstract void disconnect(Channel channel); - - public abstract void doTimeOut(Channel channel, IdleStateEvent evt); - -} diff --git a/src/main/java/com/myself/nettychat/common/pool/DefaultThreadFactory.java b/src/main/java/com/myself/nettychat/common/pool/DefaultThreadFactory.java deleted file mode 100644 index b6c776f..0000000 --- a/src/main/java/com/myself/nettychat/common/pool/DefaultThreadFactory.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.myself.nettychat.common.pool; - -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 线程池 - **/ -public class DefaultThreadFactory implements ThreadFactory { - - private static final AtomicInteger poolNumber = new AtomicInteger(1); - private final ThreadGroup threadGroup; - private final AtomicInteger currentThreadNumber = new AtomicInteger(1); - private final String namePrefix; - private int priority = Thread.NORM_PRIORITY; - private boolean isDaemon = false; - - public DefaultThreadFactory(String prefix) { - this(prefix, false); - } - - public DefaultThreadFactory(String prefix, boolean isDaemon) { - this(prefix, isDaemon, Thread.NORM_PRIORITY); - } - - public DefaultThreadFactory(String prefix, boolean isDaemon, int priority) { - SecurityManager s = System.getSecurityManager(); - this.threadGroup = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); - this.namePrefix = prefix + "-" + poolNumber.getAndIncrement() + "-thread-"; - this.isDaemon = isDaemon; - this.priority = priority; - } - - @Override - public Thread newThread(Runnable r) { - Thread thread = new Thread(threadGroup, r, namePrefix + currentThreadNumber.getAndIncrement(), 0); - thread.setDaemon(isDaemon); - thread.setPriority(priority); - return thread; - } -} diff --git a/src/main/java/com/myself/nettychat/common/pool/ExecutorQueue.java b/src/main/java/com/myself/nettychat/common/pool/ExecutorQueue.java deleted file mode 100644 index 0217bc1..0000000 --- a/src/main/java/com/myself/nettychat/common/pool/ExecutorQueue.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.myself.nettychat.common.pool; - -import java.util.concurrent.LinkedTransferQueue; -import java.util.concurrent.RejectedExecutionException; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc LinkedTransferQueue 能保证更高性能,相比与LinkedBlockingQueue有明显提升 - * 不过LinkedTransferQueue的缺点是没有队列长度控制,需要在外层协助控制 - **/ -public class ExecutorQueue extends LinkedTransferQueue { - - private static final long serialVersionUID = -265236426751004839L; - - private StandardThreadExecutor threadPoolExecutor; - - public ExecutorQueue() { - super(); - } - - public void setStandardThreadExecutor(StandardThreadExecutor threadPoolExecutor) { - this.threadPoolExecutor = threadPoolExecutor; - } - - // 注:代码来源于 tomcat - public boolean force(Runnable o) { - if (threadPoolExecutor.isShutdown()) { - throw new RejectedExecutionException("Executor not running, can't force a command into the queue"); - } - // forces the item onto the queue, to be used if the task is rejected - return super.offer(o); - } - - // 注:tomcat的代码进行一些小变更 - public boolean offer(Runnable o) { - int poolSize = threadPoolExecutor.getPoolSize(); - - // we are maxed out on threads, simply queue the object - if (poolSize == threadPoolExecutor.getMaximumPoolSize()) { - return super.offer(o); - } - // we have idle threads, just add it to the queue - // note that we don't use getActiveCount(), see BZ 49730 - if (poolSize >= threadPoolExecutor.getSubmittedTasksCount()) { - return super.offer(o); - } - // if we have less threads than maximum force creation of a new - // thread - if (poolSize < threadPoolExecutor.getMaximumPoolSize()) { - return false; - } - // if we reached here, we need to add it to the queue - return super.offer(o); - } - -} diff --git a/src/main/java/com/myself/nettychat/common/pool/Scheduled.java b/src/main/java/com/myself/nettychat/common/pool/Scheduled.java deleted file mode 100644 index f3711ca..0000000 --- a/src/main/java/com/myself/nettychat/common/pool/Scheduled.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.myself.nettychat.common.pool; - -import java.util.concurrent.ScheduledFuture; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 接口 - **/ -@FunctionalInterface -public interface Scheduled { - - ScheduledFuture submit(Runnable runnable); - -} diff --git a/src/main/java/com/myself/nettychat/common/pool/StandardThreadExecutor.java b/src/main/java/com/myself/nettychat/common/pool/StandardThreadExecutor.java deleted file mode 100644 index 8172d49..0000000 --- a/src/main/java/com/myself/nettychat/common/pool/StandardThreadExecutor.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.myself.nettychat.common.pool; - -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 代码和思路主要来自于: - * tomcat: org.apache.catalina.core.StandardThreadExecutor - * - * java.util.concurrent.threadPoolExecutor execute执行策略: - * 优先offer到queue,queue满后再扩充线程到maxThread,如果已经到了maxThread就reject - * 比较适合于CPU密集型应用(比如runnable内部执行的操作都在JVM内部,memory copy, or compute等等) - * - * StandardThreadExecutor execute执行策略: - * 优先扩充线程到maxThread,再offer到queue,如果满了就reject - * 比较适合于业务处理需要远程资源的场景 - **/ -public class StandardThreadExecutor extends ThreadPoolExecutor { - - public static final int DEFAULT_MIN_THREADS = 20; - public static final int DEFAULT_MAX_THREADS = 200; - public static final int DEFAULT_MAX_IDLE_TIME = 60000; // 1 minutes - - protected AtomicInteger submittedTasksCount; // 正在处理的任务数 - private int maxSubmittedTaskCount; // 最大允许同时处理的任务数 - - public StandardThreadExecutor() { - this(DEFAULT_MIN_THREADS, DEFAULT_MAX_THREADS); - } - - public StandardThreadExecutor(int coreThread, int maxThreads) { - this(coreThread, maxThreads, maxThreads); - } - - public StandardThreadExecutor(int coreThread, int maxThreads, long keepAliveTime, TimeUnit unit) { - this(coreThread, maxThreads, keepAliveTime, unit, maxThreads); - } - - public StandardThreadExecutor(int coreThreads, int maxThreads, int queueCapacity) { - this(coreThreads, maxThreads, queueCapacity, Executors.defaultThreadFactory()); - } - - public StandardThreadExecutor(int coreThreads, int maxThreads, int queueCapacity, ThreadFactory threadFactory) { - this(coreThreads, maxThreads, DEFAULT_MAX_IDLE_TIME, TimeUnit.MILLISECONDS, queueCapacity, threadFactory); - } - - public StandardThreadExecutor(int coreThreads, int maxThreads, long keepAliveTime, TimeUnit unit, int queueCapacity) { - this(coreThreads, maxThreads, keepAliveTime, unit, queueCapacity, Executors.defaultThreadFactory()); - } - - public StandardThreadExecutor(int coreThreads, int maxThreads, long keepAliveTime, TimeUnit unit, - int queueCapacity, ThreadFactory threadFactory) { - this(coreThreads, maxThreads, keepAliveTime, unit, queueCapacity, threadFactory, new AbortPolicy()); - } - - public StandardThreadExecutor(int coreThreads, int maxThreads, long keepAliveTime, TimeUnit unit, - int queueCapacity, ThreadFactory threadFactory, RejectedExecutionHandler handler) { - super(coreThreads, maxThreads, keepAliveTime, unit, new ExecutorQueue(), threadFactory, handler); - ((ExecutorQueue) getQueue()).setStandardThreadExecutor(this); - - submittedTasksCount = new AtomicInteger(0); - - // 最大并发任务限制: 队列buffer数 + 最大线程数 - maxSubmittedTaskCount = queueCapacity + maxThreads; - } - - @Override - public void execute(Runnable command) { - int count = submittedTasksCount.incrementAndGet(); - - // 超过最大的并发任务限制,进行 reject - // 依赖的LinkedTransferQueue没有长度限制,因此这里进行控制 - if (count > maxSubmittedTaskCount) { - submittedTasksCount.decrementAndGet(); - getRejectedExecutionHandler().rejectedExecution(command, this); - } - - try { - super.execute(command); - } catch (RejectedExecutionException rx) { - // there could have been contention around the queue - if (!((ExecutorQueue) getQueue()).force(command)) { - submittedTasksCount.decrementAndGet(); - getRejectedExecutionHandler().rejectedExecution(command, this); - } - rx.printStackTrace(); - } - } - - public int getSubmittedTasksCount() { - return this.submittedTasksCount.get(); - } - - - protected void afterExecute(Runnable r, Throwable t) { - submittedTasksCount.decrementAndGet(); - } -} diff --git a/src/main/java/com/myself/nettychat/common/properties/InitNetty.java b/src/main/java/com/myself/nettychat/common/properties/InitNetty.java index ab6ad0c..eed34b4 100644 --- a/src/main/java/com/myself/nettychat/common/properties/InitNetty.java +++ b/src/main/java/com/myself/nettychat/common/properties/InitNetty.java @@ -3,8 +3,6 @@ import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; -import com.myself.nettychat.common.enums.ProtocolEnum; -import com.myself.nettychat.common.mqtts.MqttHander; /** * @Author:UncleCatMySelf @@ -13,11 +11,10 @@ * @Date:Created in 10:54 2018\8\14 0014 */ @Data +@Component @ConfigurationProperties(prefix = "netty") public class InitNetty { - private ProtocolEnum protocol; - private int webport; private int tcpport; @@ -52,8 +49,6 @@ public class InitNetty { private String jksCertificatePassword; - private Class mqttHander ; - private int initalDelay ; private int period ; diff --git a/src/main/java/com/myself/nettychat/common/ssl/SecureSocketKeyStore.java b/src/main/java/com/myself/nettychat/common/ssl/SecureSocketKeyStore.java deleted file mode 100644 index 3bae691..0000000 --- a/src/main/java/com/myself/nettychat/common/ssl/SecureSocketKeyStore.java +++ /dev/null @@ -1,456 +0,0 @@ -package com.myself.nettychat.common.ssl; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.security.KeyStore; - -/** - * A bogus key store which provides all the required information to create an - * example SSL connection. - * - * To generate a bogus key store: - * - *
- * keytool -genkey -alias securesocket \ -keysize 2048 -validity 36500 \  -keyalg RSA -dname "CN=securesocket" \   -keypass inc0rrect -storepass mu$tch8ng3 \  -keystore cert.jks
- *
- *
- *
- *
- * 
- */ -public class SecureSocketKeyStore { - - private static final byte[] CERT_BYTES = { (byte) 254, (byte) 237, - (byte) 254, (byte) 237, (byte) 0, (byte) 0, (byte) 0, (byte) 2, - (byte) 0, (byte) 0, (byte) 0, (byte) 1, (byte) 0, (byte) 0, - (byte) 0, (byte) 1, (byte) 0, (byte) 12, (byte) 115, (byte) 101, - (byte) 99, (byte) 117, (byte) 114, (byte) 101, (byte) 115, - (byte) 111, (byte) 99, (byte) 107, (byte) 101, (byte) 116, - (byte) 0, (byte) 0, (byte) 1, (byte) 69, (byte) 231, (byte) 201, - (byte) 156, (byte) 140, (byte) 0, (byte) 0, (byte) 5, (byte) 0, - (byte) 48, (byte) 130, (byte) 4, (byte) 252, (byte) 48, (byte) 14, - (byte) 6, (byte) 10, (byte) 43, (byte) 6, (byte) 1, (byte) 4, - (byte) 1, (byte) 42, (byte) 2, (byte) 17, (byte) 1, (byte) 1, - (byte) 5, (byte) 0, (byte) 4, (byte) 130, (byte) 4, (byte) 232, - (byte) 221, (byte) 18, (byte) 203, (byte) 171, (byte) 175, - (byte) 82, (byte) 132, (byte) 227, (byte) 115, (byte) 143, - (byte) 38, (byte) 191, (byte) 42, (byte) 202, (byte) 130, - (byte) 171, (byte) 75, (byte) 6, (byte) 161, (byte) 120, - (byte) 204, (byte) 61, (byte) 106, (byte) 160, (byte) 81, (byte) 9, - (byte) 204, (byte) 153, (byte) 166, (byte) 38, (byte) 246, - (byte) 13, (byte) 43, (byte) 19, (byte) 100, (byte) 132, (byte) 45, - (byte) 90, (byte) 143, (byte) 1, (byte) 231, (byte) 182, (byte) 89, - (byte) 228, (byte) 183, (byte) 17, (byte) 95, (byte) 129, - (byte) 229, (byte) 42, (byte) 182, (byte) 126, (byte) 114, - (byte) 76, (byte) 124, (byte) 123, (byte) 246, (byte) 152, - (byte) 0, (byte) 141, (byte) 212, (byte) 111, (byte) 52, - (byte) 243, (byte) 112, (byte) 31, (byte) 117, (byte) 124, - (byte) 142, (byte) 24, (byte) 59, (byte) 198, (byte) 164, - (byte) 253, (byte) 21, (byte) 177, (byte) 189, (byte) 74, - (byte) 218, (byte) 110, (byte) 83, (byte) 154, (byte) 49, - (byte) 186, (byte) 159, (byte) 173, (byte) 202, (byte) 94, - (byte) 174, (byte) 183, (byte) 223, (byte) 119, (byte) 109, - (byte) 110, (byte) 72, (byte) 93, (byte) 208, (byte) 195, - (byte) 19, (byte) 89, (byte) 33, (byte) 34, (byte) 186, (byte) 12, - (byte) 86, (byte) 156, (byte) 156, (byte) 210, (byte) 111, - (byte) 110, (byte) 44, (byte) 106, (byte) 36, (byte) 67, - (byte) 168, (byte) 7, (byte) 179, (byte) 244, (byte) 53, - (byte) 134, (byte) 10, (byte) 86, (byte) 179, (byte) 34, (byte) 60, - (byte) 184, (byte) 179, (byte) 162, (byte) 69, (byte) 24, - (byte) 168, (byte) 100, (byte) 183, (byte) 206, (byte) 64, - (byte) 4, (byte) 32, (byte) 66, (byte) 237, (byte) 228, (byte) 92, - (byte) 6, (byte) 213, (byte) 141, (byte) 147, (byte) 198, - (byte) 141, (byte) 216, (byte) 41, (byte) 0, (byte) 101, (byte) 65, - (byte) 41, (byte) 185, (byte) 128, (byte) 229, (byte) 107, - (byte) 25, (byte) 89, (byte) 148, (byte) 16, (byte) 194, - (byte) 101, (byte) 100, (byte) 243, (byte) 147, (byte) 77, - (byte) 230, (byte) 11, (byte) 151, (byte) 99, (byte) 124, - (byte) 55, (byte) 195, (byte) 185, (byte) 30, (byte) 234, - (byte) 83, (byte) 61, (byte) 109, (byte) 131, (byte) 156, - (byte) 244, (byte) 133, (byte) 66, (byte) 39, (byte) 153, (byte) 9, - (byte) 34, (byte) 218, (byte) 201, (byte) 143, (byte) 190, - (byte) 127, (byte) 119, (byte) 102, (byte) 6, (byte) 83, - (byte) 134, (byte) 96, (byte) 170, (byte) 79, (byte) 196, - (byte) 214, (byte) 47, (byte) 215, (byte) 37, (byte) 250, - (byte) 64, (byte) 8, (byte) 165, (byte) 203, (byte) 44, (byte) 53, - (byte) 113, (byte) 147, (byte) 251, (byte) 29, (byte) 26, - (byte) 38, (byte) 193, (byte) 11, (byte) 223, (byte) 212, - (byte) 114, (byte) 96, (byte) 162, (byte) 39, (byte) 48, - (byte) 200, (byte) 172, (byte) 182, (byte) 254, (byte) 180, - (byte) 198, (byte) 11, (byte) 128, (byte) 75, (byte) 74, (byte) 93, - (byte) 226, (byte) 157, (byte) 80, (byte) 14, (byte) 9, (byte) 217, - (byte) 236, (byte) 205, (byte) 153, (byte) 35, (byte) 242, - (byte) 130, (byte) 140, (byte) 25, (byte) 16, (byte) 156, - (byte) 247, (byte) 230, (byte) 5, (byte) 247, (byte) 0, (byte) 34, - (byte) 196, (byte) 15, (byte) 118, (byte) 255, (byte) 185, - (byte) 199, (byte) 59, (byte) 99, (byte) 27, (byte) 187, (byte) 83, - (byte) 81, (byte) 12, (byte) 71, (byte) 69, (byte) 127, (byte) 130, - (byte) 164, (byte) 97, (byte) 195, (byte) 216, (byte) 215, - (byte) 61, (byte) 29, (byte) 196, (byte) 62, (byte) 160, - (byte) 188, (byte) 209, (byte) 173, (byte) 230, (byte) 0, - (byte) 204, (byte) 225, (byte) 1, (byte) 5, (byte) 42, (byte) 223, - (byte) 232, (byte) 187, (byte) 190, (byte) 67, (byte) 126, - (byte) 235, (byte) 178, (byte) 218, (byte) 179, (byte) 46, - (byte) 186, (byte) 156, (byte) 186, (byte) 6, (byte) 191, - (byte) 68, (byte) 239, (byte) 31, (byte) 16, (byte) 204, (byte) 24, - (byte) 68, (byte) 164, (byte) 88, (byte) 10, (byte) 174, (byte) 26, - (byte) 54, (byte) 187, (byte) 149, (byte) 132, (byte) 128, - (byte) 173, (byte) 165, (byte) 8, (byte) 69, (byte) 96, (byte) 49, - (byte) 57, (byte) 223, (byte) 110, (byte) 29, (byte) 215, - (byte) 98, (byte) 42, (byte) 15, (byte) 153, (byte) 228, - (byte) 216, (byte) 61, (byte) 160, (byte) 230, (byte) 34, - (byte) 40, (byte) 232, (byte) 136, (byte) 139, (byte) 140, - (byte) 236, (byte) 251, (byte) 119, (byte) 242, (byte) 199, - (byte) 167, (byte) 61, (byte) 141, (byte) 89, (byte) 29, (byte) 82, - (byte) 114, (byte) 229, (byte) 198, (byte) 27, (byte) 133, - (byte) 87, (byte) 0, (byte) 53, (byte) 69, (byte) 42, (byte) 91, - (byte) 174, (byte) 82, (byte) 244, (byte) 160, (byte) 82, - (byte) 142, (byte) 221, (byte) 106, (byte) 151, (byte) 241, - (byte) 214, (byte) 64, (byte) 14, (byte) 28, (byte) 2, (byte) 3, - (byte) 145, (byte) 143, (byte) 18, (byte) 165, (byte) 247, - (byte) 178, (byte) 211, (byte) 16, (byte) 222, (byte) 76, - (byte) 60, (byte) 119, (byte) 130, (byte) 199, (byte) 230, - (byte) 229, (byte) 3, (byte) 22, (byte) 100, (byte) 135, - (byte) 103, (byte) 60, (byte) 181, (byte) 191, (byte) 56, - (byte) 249, (byte) 181, (byte) 169, (byte) 210, (byte) 25, - (byte) 152, (byte) 201, (byte) 226, (byte) 119, (byte) 71, - (byte) 204, (byte) 70, (byte) 220, (byte) 103, (byte) 46, - (byte) 166, (byte) 125, (byte) 40, (byte) 86, (byte) 208, - (byte) 114, (byte) 138, (byte) 24, (byte) 27, (byte) 219, - (byte) 123, (byte) 161, (byte) 52, (byte) 14, (byte) 38, - (byte) 244, (byte) 112, (byte) 238, (byte) 121, (byte) 90, - (byte) 34, (byte) 157, (byte) 131, (byte) 53, (byte) 245, - (byte) 162, (byte) 89, (byte) 188, (byte) 6, (byte) 202, - (byte) 164, (byte) 130, (byte) 34, (byte) 232, (byte) 74, - (byte) 45, (byte) 137, (byte) 164, (byte) 200, (byte) 197, - (byte) 247, (byte) 64, (byte) 110, (byte) 122, (byte) 49, - (byte) 116, (byte) 137, (byte) 253, (byte) 170, (byte) 232, - (byte) 120, (byte) 26, (byte) 171, (byte) 228, (byte) 229, - (byte) 49, (byte) 56, (byte) 56, (byte) 106, (byte) 110, (byte) 12, - (byte) 109, (byte) 93, (byte) 105, (byte) 241, (byte) 196, - (byte) 11, (byte) 18, (byte) 89, (byte) 108, (byte) 146, - (byte) 224, (byte) 161, (byte) 181, (byte) 236, (byte) 74, - (byte) 128, (byte) 24, (byte) 239, (byte) 22, (byte) 146, (byte) 0, - (byte) 69, (byte) 182, (byte) 246, (byte) 43, (byte) 59, - (byte) 208, (byte) 33, (byte) 48, (byte) 81, (byte) 0, (byte) 70, - (byte) 225, (byte) 222, (byte) 122, (byte) 178, (byte) 138, - (byte) 12, (byte) 207, (byte) 233, (byte) 164, (byte) 13, - (byte) 176, (byte) 123, (byte) 95, (byte) 68, (byte) 238, - (byte) 134, (byte) 66, (byte) 95, (byte) 194, (byte) 192, - (byte) 225, (byte) 244, (byte) 14, (byte) 78, (byte) 53, - (byte) 189, (byte) 217, (byte) 229, (byte) 203, (byte) 192, - (byte) 34, (byte) 38, (byte) 169, (byte) 63, (byte) 239, - (byte) 128, (byte) 172, (byte) 143, (byte) 75, (byte) 7, - (byte) 237, (byte) 125, (byte) 179, (byte) 235, (byte) 229, - (byte) 98, (byte) 8, (byte) 211, (byte) 237, (byte) 116, (byte) 75, - (byte) 27, (byte) 211, (byte) 131, (byte) 245, (byte) 89, - (byte) 150, (byte) 35, (byte) 49, (byte) 207, (byte) 113, - (byte) 237, (byte) 114, (byte) 125, (byte) 134, (byte) 191, - (byte) 110, (byte) 30, (byte) 119, (byte) 131, (byte) 175, - (byte) 166, (byte) 201, (byte) 255, (byte) 200, (byte) 1, - (byte) 126, (byte) 163, (byte) 172, (byte) 52, (byte) 118, - (byte) 184, (byte) 221, (byte) 165, (byte) 167, (byte) 165, - (byte) 20, (byte) 135, (byte) 32, (byte) 222, (byte) 188, - (byte) 250, (byte) 64, (byte) 161, (byte) 67, (byte) 236, - (byte) 212, (byte) 131, (byte) 44, (byte) 32, (byte) 70, (byte) 0, - (byte) 24, (byte) 178, (byte) 83, (byte) 155, (byte) 145, - (byte) 136, (byte) 131, (byte) 120, (byte) 181, (byte) 164, - (byte) 155, (byte) 172, (byte) 41, (byte) 213, (byte) 164, - (byte) 98, (byte) 169, (byte) 152, (byte) 184, (byte) 170, - (byte) 107, (byte) 7, (byte) 21, (byte) 228, (byte) 175, - (byte) 192, (byte) 238, (byte) 68, (byte) 197, (byte) 119, - (byte) 228, (byte) 225, (byte) 156, (byte) 235, (byte) 241, - (byte) 172, (byte) 171, (byte) 236, (byte) 128, (byte) 78, - (byte) 117, (byte) 152, (byte) 123, (byte) 93, (byte) 156, - (byte) 57, (byte) 238, (byte) 211, (byte) 188, (byte) 47, - (byte) 62, (byte) 45, (byte) 127, (byte) 58, (byte) 38, (byte) 29, - (byte) 131, (byte) 95, (byte) 85, (byte) 149, (byte) 112, - (byte) 215, (byte) 207, (byte) 41, (byte) 201, (byte) 30, - (byte) 149, (byte) 73, (byte) 245, (byte) 179, (byte) 176, - (byte) 246, (byte) 203, (byte) 204, (byte) 252, (byte) 13, - (byte) 98, (byte) 151, (byte) 93, (byte) 87, (byte) 241, - (byte) 166, (byte) 46, (byte) 249, (byte) 148, (byte) 49, - (byte) 141, (byte) 136, (byte) 49, (byte) 77, (byte) 250, - (byte) 191, (byte) 157, (byte) 90, (byte) 84, (byte) 51, - (byte) 129, (byte) 133, (byte) 66, (byte) 253, (byte) 99, - (byte) 243, (byte) 34, (byte) 142, (byte) 197, (byte) 4, - (byte) 126, (byte) 7, (byte) 217, (byte) 126, (byte) 205, - (byte) 250, (byte) 141, (byte) 231, (byte) 225, (byte) 203, - (byte) 171, (byte) 246, (byte) 201, (byte) 48, (byte) 96, - (byte) 207, (byte) 74, (byte) 253, (byte) 120, (byte) 114, - (byte) 163, (byte) 192, (byte) 24, (byte) 12, (byte) 10, - (byte) 210, (byte) 94, (byte) 136, (byte) 152, (byte) 185, - (byte) 109, (byte) 87, (byte) 35, (byte) 159, (byte) 238, - (byte) 122, (byte) 200, (byte) 107, (byte) 103, (byte) 243, - (byte) 250, (byte) 152, (byte) 68, (byte) 66, (byte) 170, (byte) 0, - (byte) 134, (byte) 229, (byte) 168, (byte) 182, (byte) 30, - (byte) 89, (byte) 240, (byte) 121, (byte) 106, (byte) 148, - (byte) 142, (byte) 49, (byte) 242, (byte) 215, (byte) 233, - (byte) 57, (byte) 120, (byte) 204, (byte) 180, (byte) 239, - (byte) 199, (byte) 133, (byte) 255, (byte) 71, (byte) 3, - (byte) 132, (byte) 228, (byte) 110, (byte) 66, (byte) 227, - (byte) 122, (byte) 82, (byte) 118, (byte) 173, (byte) 218, - (byte) 54, (byte) 99, (byte) 167, (byte) 154, (byte) 3, (byte) 189, - (byte) 25, (byte) 123, (byte) 169, (byte) 42, (byte) 184, - (byte) 59, (byte) 36, (byte) 131, (byte) 206, (byte) 248, - (byte) 90, (byte) 32, (byte) 183, (byte) 86, (byte) 62, (byte) 149, - (byte) 107, (byte) 243, (byte) 71, (byte) 197, (byte) 124, - (byte) 155, (byte) 214, (byte) 91, (byte) 29, (byte) 81, (byte) 28, - (byte) 115, (byte) 98, (byte) 130, (byte) 184, (byte) 135, - (byte) 13, (byte) 191, (byte) 147, (byte) 43, (byte) 10, - (byte) 178, (byte) 99, (byte) 165, (byte) 210, (byte) 87, - (byte) 87, (byte) 148, (byte) 31, (byte) 198, (byte) 129, - (byte) 32, (byte) 181, (byte) 3, (byte) 144, (byte) 61, (byte) 5, - (byte) 166, (byte) 252, (byte) 73, (byte) 205, (byte) 230, - (byte) 178, (byte) 162, (byte) 46, (byte) 56, (byte) 99, (byte) 77, - (byte) 97, (byte) 236, (byte) 121, (byte) 157, (byte) 139, - (byte) 153, (byte) 217, (byte) 171, (byte) 19, (byte) 68, - (byte) 36, (byte) 14, (byte) 123, (byte) 249, (byte) 101, - (byte) 127, (byte) 184, (byte) 123, (byte) 7, (byte) 124, - (byte) 68, (byte) 98, (byte) 34, (byte) 139, (byte) 224, - (byte) 173, (byte) 246, (byte) 196, (byte) 180, (byte) 70, - (byte) 207, (byte) 168, (byte) 211, (byte) 255, (byte) 84, - (byte) 0, (byte) 174, (byte) 11, (byte) 160, (byte) 155, - (byte) 127, (byte) 228, (byte) 81, (byte) 226, (byte) 115, - (byte) 142, (byte) 200, (byte) 107, (byte) 4, (byte) 204, - (byte) 219, (byte) 192, (byte) 189, (byte) 56, (byte) 127, - (byte) 184, (byte) 187, (byte) 161, (byte) 106, (byte) 62, - (byte) 225, (byte) 211, (byte) 115, (byte) 30, (byte) 172, - (byte) 191, (byte) 66, (byte) 25, (byte) 66, (byte) 235, - (byte) 107, (byte) 41, (byte) 186, (byte) 40, (byte) 239, - (byte) 173, (byte) 11, (byte) 247, (byte) 89, (byte) 79, - (byte) 135, (byte) 86, (byte) 73, (byte) 77, (byte) 164, (byte) 34, - (byte) 109, (byte) 236, (byte) 56, (byte) 198, (byte) 141, - (byte) 87, (byte) 74, (byte) 172, (byte) 56, (byte) 24, (byte) 150, - (byte) 233, (byte) 233, (byte) 165, (byte) 122, (byte) 201, - (byte) 112, (byte) 232, (byte) 23, (byte) 12, (byte) 166, - (byte) 128, (byte) 114, (byte) 139, (byte) 207, (byte) 233, - (byte) 47, (byte) 220, (byte) 172, (byte) 175, (byte) 40, - (byte) 109, (byte) 82, (byte) 142, (byte) 130, (byte) 177, - (byte) 50, (byte) 127, (byte) 196, (byte) 106, (byte) 172, - (byte) 178, (byte) 71, (byte) 178, (byte) 204, (byte) 99, - (byte) 113, (byte) 33, (byte) 189, (byte) 188, (byte) 168, - (byte) 76, (byte) 92, (byte) 230, (byte) 211, (byte) 239, - (byte) 75, (byte) 71, (byte) 64, (byte) 197, (byte) 26, (byte) 222, - (byte) 19, (byte) 213, (byte) 161, (byte) 144, (byte) 20, - (byte) 126, (byte) 192, (byte) 156, (byte) 15, (byte) 113, - (byte) 64, (byte) 73, (byte) 7, (byte) 241, (byte) 217, (byte) 127, - (byte) 171, (byte) 199, (byte) 66, (byte) 32, (byte) 179, (byte) 4, - (byte) 181, (byte) 93, (byte) 121, (byte) 193, (byte) 10, - (byte) 169, (byte) 255, (byte) 152, (byte) 199, (byte) 95, - (byte) 177, (byte) 227, (byte) 135, (byte) 21, (byte) 64, - (byte) 203, (byte) 9, (byte) 79, (byte) 243, (byte) 114, (byte) 2, - (byte) 201, (byte) 157, (byte) 180, (byte) 52, (byte) 193, - (byte) 66, (byte) 34, (byte) 155, (byte) 52, (byte) 35, (byte) 93, - (byte) 31, (byte) 96, (byte) 77, (byte) 12, (byte) 80, (byte) 195, - (byte) 96, (byte) 247, (byte) 251, (byte) 237, (byte) 36, - (byte) 170, (byte) 7, (byte) 3, (byte) 251, (byte) 243, (byte) 47, - (byte) 180, (byte) 98, (byte) 207, (byte) 176, (byte) 106, - (byte) 237, (byte) 114, (byte) 91, (byte) 229, (byte) 56, - (byte) 94, (byte) 154, (byte) 32, (byte) 62, (byte) 240, - (byte) 132, (byte) 4, (byte) 144, (byte) 227, (byte) 140, - (byte) 137, (byte) 76, (byte) 15, (byte) 117, (byte) 82, - (byte) 223, (byte) 168, (byte) 135, (byte) 33, (byte) 91, - (byte) 173, (byte) 4, (byte) 245, (byte) 192, (byte) 95, - (byte) 135, (byte) 22, (byte) 138, (byte) 89, (byte) 1, (byte) 14, - (byte) 230, (byte) 143, (byte) 195, (byte) 93, (byte) 133, - (byte) 194, (byte) 252, (byte) 188, (byte) 31, (byte) 39, - (byte) 162, (byte) 59, (byte) 148, (byte) 219, (byte) 213, - (byte) 179, (byte) 195, (byte) 165, (byte) 67, (byte) 68, - (byte) 39, (byte) 178, (byte) 143, (byte) 192, (byte) 177, - (byte) 221, (byte) 236, (byte) 63, (byte) 40, (byte) 205, - (byte) 26, (byte) 81, (byte) 127, (byte) 5, (byte) 213, (byte) 192, - (byte) 22, (byte) 147, (byte) 98, (byte) 207, (byte) 153, (byte) 8, - (byte) 108, (byte) 75, (byte) 182, (byte) 148, (byte) 0, - (byte) 151, (byte) 15, (byte) 178, (byte) 98, (byte) 145, - (byte) 255, (byte) 213, (byte) 142, (byte) 63, (byte) 247, - (byte) 42, (byte) 161, (byte) 246, (byte) 21, (byte) 128, - (byte) 47, (byte) 248, (byte) 217, (byte) 70, (byte) 195, - (byte) 151, (byte) 236, (byte) 73, (byte) 153, (byte) 230, - (byte) 152, (byte) 217, (byte) 12, (byte) 189, (byte) 65, - (byte) 85, (byte) 189, (byte) 204, (byte) 212, (byte) 161, - (byte) 210, (byte) 217, (byte) 74, (byte) 75, (byte) 186, - (byte) 122, (byte) 167, (byte) 149, (byte) 178, (byte) 202, - (byte) 205, (byte) 246, (byte) 225, (byte) 225, (byte) 190, - (byte) 56, (byte) 42, (byte) 162, (byte) 215, (byte) 107, - (byte) 45, (byte) 121, (byte) 235, (byte) 195, (byte) 219, - (byte) 22, (byte) 0, (byte) 0, (byte) 0, (byte) 1, (byte) 0, - (byte) 5, (byte) 88, (byte) 46, (byte) 53, (byte) 48, (byte) 57, - (byte) 0, (byte) 0, (byte) 2, (byte) 211, (byte) 48, (byte) 130, - (byte) 2, (byte) 207, (byte) 48, (byte) 130, (byte) 1, (byte) 183, - (byte) 160, (byte) 3, (byte) 2, (byte) 1, (byte) 2, (byte) 2, - (byte) 4, (byte) 58, (byte) 247, (byte) 71, (byte) 185, (byte) 48, - (byte) 13, (byte) 6, (byte) 9, (byte) 42, (byte) 134, (byte) 72, - (byte) 134, (byte) 247, (byte) 13, (byte) 1, (byte) 1, (byte) 11, - (byte) 5, (byte) 0, (byte) 48, (byte) 23, (byte) 49, (byte) 21, - (byte) 48, (byte) 19, (byte) 6, (byte) 3, (byte) 85, (byte) 4, - (byte) 3, (byte) 19, (byte) 12, (byte) 115, (byte) 101, (byte) 99, - (byte) 117, (byte) 114, (byte) 101, (byte) 115, (byte) 111, - (byte) 99, (byte) 107, (byte) 101, (byte) 116, (byte) 48, - (byte) 32, (byte) 23, (byte) 13, (byte) 49, (byte) 52, (byte) 48, - (byte) 53, (byte) 49, (byte) 48, (byte) 50, (byte) 48, (byte) 49, - (byte) 56, (byte) 52, (byte) 48, (byte) 90, (byte) 24, (byte) 15, - (byte) 50, (byte) 49, (byte) 49, (byte) 52, (byte) 48, (byte) 52, - (byte) 49, (byte) 54, (byte) 50, (byte) 48, (byte) 49, (byte) 56, - (byte) 52, (byte) 48, (byte) 90, (byte) 48, (byte) 23, (byte) 49, - (byte) 21, (byte) 48, (byte) 19, (byte) 6, (byte) 3, (byte) 85, - (byte) 4, (byte) 3, (byte) 19, (byte) 12, (byte) 115, (byte) 101, - (byte) 99, (byte) 117, (byte) 114, (byte) 101, (byte) 115, - (byte) 111, (byte) 99, (byte) 107, (byte) 101, (byte) 116, - (byte) 48, (byte) 130, (byte) 1, (byte) 34, (byte) 48, (byte) 13, - (byte) 6, (byte) 9, (byte) 42, (byte) 134, (byte) 72, (byte) 134, - (byte) 247, (byte) 13, (byte) 1, (byte) 1, (byte) 1, (byte) 5, - (byte) 0, (byte) 3, (byte) 130, (byte) 1, (byte) 15, (byte) 0, - (byte) 48, (byte) 130, (byte) 1, (byte) 10, (byte) 2, (byte) 130, - (byte) 1, (byte) 1, (byte) 0, (byte) 153, (byte) 113, (byte) 7, - (byte) 44, (byte) 219, (byte) 76, (byte) 101, (byte) 226, - (byte) 138, (byte) 96, (byte) 219, (byte) 60, (byte) 167, - (byte) 138, (byte) 222, (byte) 6, (byte) 78, (byte) 169, (byte) 64, - (byte) 188, (byte) 156, (byte) 190, (byte) 119, (byte) 16, - (byte) 34, (byte) 228, (byte) 250, (byte) 253, (byte) 119, - (byte) 75, (byte) 240, (byte) 60, (byte) 242, (byte) 52, - (byte) 137, (byte) 146, (byte) 20, (byte) 130, (byte) 202, - (byte) 226, (byte) 125, (byte) 19, (byte) 7, (byte) 34, (byte) 8, - (byte) 61, (byte) 243, (byte) 202, (byte) 225, (byte) 206, - (byte) 223, (byte) 53, (byte) 74, (byte) 56, (byte) 222, (byte) 47, - (byte) 99, (byte) 235, (byte) 57, (byte) 73, (byte) 90, (byte) 198, - (byte) 109, (byte) 104, (byte) 36, (byte) 255, (byte) 124, - (byte) 57, (byte) 155, (byte) 248, (byte) 120, (byte) 56, - (byte) 56, (byte) 38, (byte) 41, (byte) 216, (byte) 1, (byte) 216, - (byte) 216, (byte) 100, (byte) 239, (byte) 79, (byte) 222, - (byte) 34, (byte) 21, (byte) 182, (byte) 112, (byte) 136, - (byte) 137, (byte) 16, (byte) 141, (byte) 15, (byte) 83, (byte) 94, - (byte) 245, (byte) 36, (byte) 203, (byte) 178, (byte) 137, - (byte) 159, (byte) 86, (byte) 220, (byte) 253, (byte) 112, - (byte) 200, (byte) 50, (byte) 135, (byte) 215, (byte) 190, - (byte) 21, (byte) 186, (byte) 84, (byte) 21, (byte) 96, (byte) 126, - (byte) 253, (byte) 115, (byte) 209, (byte) 241, (byte) 94, - (byte) 115, (byte) 219, (byte) 0, (byte) 25, (byte) 253, - (byte) 209, (byte) 182, (byte) 118, (byte) 230, (byte) 10, - (byte) 50, (byte) 131, (byte) 39, (byte) 249, (byte) 136, - (byte) 11, (byte) 101, (byte) 192, (byte) 12, (byte) 210, - (byte) 179, (byte) 237, (byte) 213, (byte) 68, (byte) 101, - (byte) 58, (byte) 187, (byte) 255, (byte) 240, (byte) 164, - (byte) 147, (byte) 72, (byte) 148, (byte) 227, (byte) 155, - (byte) 88, (byte) 250, (byte) 101, (byte) 253, (byte) 87, - (byte) 140, (byte) 168, (byte) 39, (byte) 163, (byte) 133, - (byte) 150, (byte) 252, (byte) 226, (byte) 234, (byte) 52, - (byte) 88, (byte) 40, (byte) 56, (byte) 23, (byte) 105, (byte) 236, - (byte) 4, (byte) 113, (byte) 98, (byte) 4, (byte) 0, (byte) 117, - (byte) 59, (byte) 77, (byte) 236, (byte) 135, (byte) 93, (byte) 54, - (byte) 30, (byte) 6, (byte) 126, (byte) 90, (byte) 15, (byte) 105, - (byte) 89, (byte) 216, (byte) 154, (byte) 72, (byte) 134, - (byte) 209, (byte) 74, (byte) 197, (byte) 237, (byte) 51, - (byte) 37, (byte) 33, (byte) 106, (byte) 50, (byte) 71, (byte) 134, - (byte) 169, (byte) 173, (byte) 88, (byte) 111, (byte) 217, - (byte) 117, (byte) 184, (byte) 97, (byte) 1, (byte) 38, (byte) 76, - (byte) 112, (byte) 170, (byte) 190, (byte) 250, (byte) 96, - (byte) 17, (byte) 45, (byte) 117, (byte) 183, (byte) 82, - (byte) 155, (byte) 10, (byte) 53, (byte) 15, (byte) 214, (byte) 36, - (byte) 134, (byte) 249, (byte) 146, (byte) 98, (byte) 99, - (byte) 64, (byte) 158, (byte) 99, (byte) 227, (byte) 21, (byte) 92, - (byte) 98, (byte) 90, (byte) 202, (byte) 214, (byte) 134, - (byte) 233, (byte) 212, (byte) 149, (byte) 2, (byte) 3, (byte) 1, - (byte) 0, (byte) 1, (byte) 163, (byte) 33, (byte) 48, (byte) 31, - (byte) 48, (byte) 29, (byte) 6, (byte) 3, (byte) 85, (byte) 29, - (byte) 14, (byte) 4, (byte) 22, (byte) 4, (byte) 20, (byte) 115, - (byte) 110, (byte) 177, (byte) 165, (byte) 41, (byte) 26, - (byte) 142, (byte) 198, (byte) 221, (byte) 63, (byte) 79, - (byte) 252, (byte) 219, (byte) 159, (byte) 68, (byte) 102, - (byte) 76, (byte) 153, (byte) 128, (byte) 164, (byte) 48, - (byte) 13, (byte) 6, (byte) 9, (byte) 42, (byte) 134, (byte) 72, - (byte) 134, (byte) 247, (byte) 13, (byte) 1, (byte) 1, (byte) 11, - (byte) 5, (byte) 0, (byte) 3, (byte) 130, (byte) 1, (byte) 1, - (byte) 0, (byte) 118, (byte) 55, (byte) 245, (byte) 122, - (byte) 159, (byte) 155, (byte) 98, (byte) 122, (byte) 229, - (byte) 186, (byte) 23, (byte) 207, (byte) 109, (byte) 225, - (byte) 220, (byte) 74, (byte) 51, (byte) 218, (byte) 10, - (byte) 115, (byte) 137, (byte) 103, (byte) 127, (byte) 28, - (byte) 30, (byte) 184, (byte) 149, (byte) 249, (byte) 193, - (byte) 206, (byte) 208, (byte) 181, (byte) 191, (byte) 128, - (byte) 18, (byte) 208, (byte) 24, (byte) 132, (byte) 147, - (byte) 184, (byte) 198, (byte) 82, (byte) 204, (byte) 183, - (byte) 127, (byte) 87, (byte) 234, (byte) 136, (byte) 197, - (byte) 34, (byte) 232, (byte) 124, (byte) 210, (byte) 2, - (byte) 192, (byte) 69, (byte) 246, (byte) 25, (byte) 232, - (byte) 162, (byte) 0, (byte) 157, (byte) 216, (byte) 194, - (byte) 26, (byte) 207, (byte) 225, (byte) 169, (byte) 59, - (byte) 246, (byte) 52, (byte) 51, (byte) 150, (byte) 210, - (byte) 50, (byte) 118, (byte) 58, (byte) 154, (byte) 45, - (byte) 128, (byte) 138, (byte) 47, (byte) 174, (byte) 83, - (byte) 117, (byte) 18, (byte) 224, (byte) 9, (byte) 146, - (byte) 180, (byte) 178, (byte) 22, (byte) 76, (byte) 82, - (byte) 229, (byte) 16, (byte) 150, (byte) 127, (byte) 13, - (byte) 122, (byte) 218, (byte) 159, (byte) 195, (byte) 232, - (byte) 168, (byte) 206, (byte) 105, (byte) 82, (byte) 37, - (byte) 252, (byte) 186, (byte) 223, (byte) 222, (byte) 7, - (byte) 106, (byte) 87, (byte) 218, (byte) 89, (byte) 22, - (byte) 252, (byte) 7, (byte) 177, (byte) 52, (byte) 180, (byte) 9, - (byte) 16, (byte) 29, (byte) 57, (byte) 192, (byte) 209, - (byte) 225, (byte) 155, (byte) 16, (byte) 219, (byte) 38, - (byte) 90, (byte) 174, (byte) 152, (byte) 140, (byte) 252, - (byte) 114, (byte) 133, (byte) 106, (byte) 24, (byte) 107, - (byte) 227, (byte) 80, (byte) 166, (byte) 63, (byte) 47, (byte) 16, - (byte) 15, (byte) 89, (byte) 242, (byte) 19, (byte) 87, (byte) 193, - (byte) 250, (byte) 222, (byte) 223, (byte) 183, (byte) 61, - (byte) 91, (byte) 17, (byte) 92, (byte) 35, (byte) 142, (byte) 44, - (byte) 153, (byte) 135, (byte) 86, (byte) 97, (byte) 70, - (byte) 205, (byte) 38, (byte) 192, (byte) 18, (byte) 244, - (byte) 61, (byte) 46, (byte) 21, (byte) 145, (byte) 99, (byte) 72, - (byte) 142, (byte) 37, (byte) 19, (byte) 219, (byte) 167, - (byte) 62, (byte) 71, (byte) 197, (byte) 86, (byte) 152, - (byte) 139, (byte) 122, (byte) 231, (byte) 122, (byte) 206, - (byte) 42, (byte) 142, (byte) 164, (byte) 237, (byte) 19, - (byte) 60, (byte) 95, (byte) 239, (byte) 191, (byte) 64, - (byte) 188, (byte) 94, (byte) 154, (byte) 199, (byte) 252, - (byte) 62, (byte) 26, (byte) 181, (byte) 194, (byte) 141, - (byte) 13, (byte) 1, (byte) 112, (byte) 161, (byte) 195, - (byte) 149, (byte) 116, (byte) 57, (byte) 118, (byte) 114, - (byte) 248, (byte) 235, (byte) 54, (byte) 229, (byte) 48, - (byte) 53, (byte) 30, (byte) 145, (byte) 199, (byte) 207, - (byte) 49, (byte) 175, (byte) 44, (byte) 172, (byte) 120, - (byte) 254, (byte) 181, (byte) 100, (byte) 113, (byte) 191, - (byte) 64, (byte) 131, (byte) 125, (byte) 80, (byte) 180, - (byte) 229, (byte) 109, (byte) 97, (byte) 8, (byte) 166, - (byte) 155, (byte) 72, (byte) 252, (byte) 84, (byte) 62, (byte) 97, - (byte) 80, (byte) 26, (byte) 17, (byte) 143, (byte) 96, (byte) 16, - (byte) 204, (byte) 86, (byte) 61, (byte) 226, (byte) 149 }; - - - public static KeyStore getKeyStore() - { - KeyStore ks = null; - try{ - ks = KeyStore.getInstance("JKS"); - ks.load(asInputStream(), getKeyStorePassword()); - }catch(Exception ex){ - throw new RuntimeException("Failed to load SSL key store.", ex); - } - return ks; - } - - public static InputStream asInputStream() { - return new ByteArrayInputStream(CERT_BYTES); - } - - public static char[] getCertificatePassword() { - return "inc0rrect".toCharArray(); - } - - public static char[] getKeyStorePassword() { - return "mu$tch8ng3".toCharArray(); - } - - public static String getCertificatePasswordString() { - return "inc0rrect"; - } - - public static String getKeyStorePasswordString() { - return "mu$tch8ng3"; - } - - private SecureSocketKeyStore() { - - } - -} diff --git a/src/main/java/com/myself/nettychat/common/ssl/SecureSocketSslContextFactory.java b/src/main/java/com/myself/nettychat/common/ssl/SecureSocketSslContextFactory.java deleted file mode 100644 index d4a0bf7..0000000 --- a/src/main/java/com/myself/nettychat/common/ssl/SecureSocketSslContextFactory.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.myself.nettychat.common.ssl; - -import io.netty.util.internal.SystemPropertyUtil; - -import javax.net.ssl.*; -import java.security.KeyStore; -import java.security.SecureRandom; - -/** - * Creates a bogus {@link SSLContext}. A client-side context created by this - * factory accepts any certificate even if it is invalid. A server-side context - * created by this factory sends a bogus certificate defined in {@link }. - *

- * You will have to create your context differently in a real world application. - * - *

Client Certificate Authentication

- * - * To enable client certificate authentication: - *
    - *
  • Enable client authentication on the server side by calling - * {@link SSLEngine#setNeedClientAuth(boolean)} before creating - * {@link }.
  • - *
  • When initializing an {@link SSLContext} on the client side, - * specify the {@link KeyManager} that contains the client certificate as - * the first argument of {@link SSLContext#init(KeyManager[], TrustManager[], SecureRandom)}.
  • - *
  • When initializing an {@link SSLContext} on the server side, - * specify the proper {@link TrustManager} as the second argument of - * {@link SSLContext#init(KeyManager[], TrustManager[], SecureRandom)} - * to validate the client certificate.
  • - *
- */ -public final class SecureSocketSslContextFactory { - - private static final String PROTOCOL = "TLS"; - private static final SSLContext SERVER_CONTEXT; - private static final SSLContext CLIENT_CONTEXT; - - static { - String algorithm = SystemPropertyUtil.get("ssl.KeyManagerFactory.algorithm"); - if (algorithm == null) { - algorithm = "SunX509"; - } - - SSLContext serverContext; - SSLContext clientContext; - try { - // - //SecureSocketSslContextFactory.class.getResourceAsStream("/securesocket.jks") - KeyStore ks = KeyStore.getInstance("JKS"); - ks.load(SecureSocketKeyStore.asInputStream(), - SecureSocketKeyStore.getKeyStorePassword()); - - // Set up key manager factory to use our key store - KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm); - kmf.init(ks, SecureSocketKeyStore.getCertificatePassword()); - - // Initialize the SSLContext to work with our key managers. - serverContext = SSLContext.getInstance(PROTOCOL); - serverContext.init(kmf.getKeyManagers(), null, null); - } catch (Exception e) { - throw new Error( - "Failed to initialize the server-side SSLContext", e); - } - - try { - clientContext = SSLContext.getInstance(PROTOCOL); - clientContext.init(null, SecureSokcetTrustManagerFactory.getTrustManagers(), null); - } catch (Exception e) { - throw new Error( - "Failed to initialize the client-side SSLContext", e); - } - - SERVER_CONTEXT = serverContext; - CLIENT_CONTEXT = clientContext; - } - - public static SSLContext getServerContext() { - return SERVER_CONTEXT; - } - - public static SSLContext getClientContext() { - return CLIENT_CONTEXT; - } - - private SecureSocketSslContextFactory() { - // Unused - } - -} diff --git a/src/main/java/com/myself/nettychat/common/ssl/SecureSokcetTrustManagerFactory.java b/src/main/java/com/myself/nettychat/common/ssl/SecureSokcetTrustManagerFactory.java deleted file mode 100644 index fdc57a1..0000000 --- a/src/main/java/com/myself/nettychat/common/ssl/SecureSokcetTrustManagerFactory.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.myself.nettychat.common.ssl; - -import javax.net.ssl.ManagerFactoryParameters; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactorySpi; -import javax.net.ssl.X509TrustManager; -import java.security.InvalidAlgorithmParameterException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.cert.X509Certificate; - -/** - * Bogus {@link TrustManagerFactorySpi} which accepts any certificate - * even if it is invalid. - */ -public class SecureSokcetTrustManagerFactory extends TrustManagerFactorySpi { - - private static final TrustManager DUMMY_TRUST_MANAGER = new X509TrustManager() { - @Override - public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; - } - - @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) { - // Always trust - it is an example. - // You should do something in the real world. - // You will reach here only if you enabled client certificate auth, - // as described in SecureChatSslContextFactory. - System.err.println( - "UNKNOWN CLIENT CERTIFICATE: " + chain[0].getSubjectDN()); - } - - @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) { - // Always trust - it is an example. - // You should do something in the real world. - System.err.println( - "UNKNOWN SERVER CERTIFICATE: 222 " + chain[0].getSubjectDN()); - } - }; - - public static TrustManager[] getTrustManagers() { - return new TrustManager[] { DUMMY_TRUST_MANAGER }; - } - - @Override - protected TrustManager[] engineGetTrustManagers() { - return getTrustManagers(); - } - - @Override - protected void engineInit(KeyStore keystore) throws KeyStoreException { - // Unused - } - - @Override - protected void engineInit(ManagerFactoryParameters managerFactoryParameters) - throws InvalidAlgorithmParameterException { - // Unused - } - -} diff --git a/src/main/java/com/myself/nettychat/common/ssl/StreamReader.java b/src/main/java/com/myself/nettychat/common/ssl/StreamReader.java deleted file mode 100644 index 25cf5b7..0000000 --- a/src/main/java/com/myself/nettychat/common/ssl/StreamReader.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.myself.nettychat.common.ssl; - -import java.io.InputStream; - -public class StreamReader { - - public String toByteArray(InputStream fin) - { - int i = -1; - StringBuilder buf = new StringBuilder(); - try{ - while((i=fin.read())!=-1){ - if(buf.length()>0) buf.append(","); - buf.append("(byte)"); - buf.append(i); - } - - }catch(Throwable e){ - ; - } - - return buf.toString(); - } - -} diff --git a/src/main/java/com/myself/nettychat/common/ssl/X509CertTool.java b/src/main/java/com/myself/nettychat/common/ssl/X509CertTool.java deleted file mode 100644 index be36d26..0000000 --- a/src/main/java/com/myself/nettychat/common/ssl/X509CertTool.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.myself.nettychat.common.ssl; - - - - -import sun.security.x509.*; - -import java.io.IOException; -import java.math.BigInteger; -import java.security.GeneralSecurityException; -import java.security.KeyPair; -import java.security.PrivateKey; -import java.security.SecureRandom; -import java.security.cert.X509Certificate; -import java.util.Date; - - -/** - * This class would require rt.jar in the class path in order to - * generated it alternative is using keytool. - */ -public class X509CertTool { - - /** - * Create a self-signed X.509 Certificate - * @param dn the X.509 Distinguished Name, eg "CN=Test, L=London, C=GB" - * @param pair the KeyPair - * @param days how many days from now the Certificate is valid for - * @param algorithm the signing algorithm, eg "SHA1withRSA" - */ - @SuppressWarnings("restriction") - X509Certificate generateCertificate(String dn, KeyPair pair, int days, - String algorithm) throws GeneralSecurityException, IOException { - PrivateKey privkey = pair.getPrivate(); - X509CertInfo info = new X509CertInfo(); - Date from = new Date(); - Date to = new Date(from.getTime() + days * 86400000l); - CertificateValidity interval = new CertificateValidity(from, to); - BigInteger sn = new BigInteger(64, new SecureRandom()); - X500Name owner = new X500Name(dn); - - info.set(X509CertInfo.VALIDITY, interval); - info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn)); - info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(owner)); - info.set(X509CertInfo.ISSUER, new CertificateIssuerName(owner)); - info.set(X509CertInfo.KEY, new CertificateX509Key(pair.getPublic())); - info.set(X509CertInfo.VERSION, new CertificateVersion( - CertificateVersion.V3)); - AlgorithmId algo = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid); - info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo)); - - // Sign the cert to identify the algorithm that's used. - X509CertImpl cert = new X509CertImpl(info); - cert.sign(privkey, algorithm); - - // Update the algorith, and resign. - algo = (AlgorithmId) cert.get(X509CertImpl.SIG_ALG); - info.set(CertificateAlgorithmId.NAME + "." - + CertificateAlgorithmId.ALGORITHM, algo); - cert = new X509CertImpl(info); - cert.sign(privkey, algorithm); - return cert; - } - - public static void main(String[] args) { - - } - -} diff --git a/src/main/java/com/myself/nettychat/common/utils/ResultVOUtil.java b/src/main/java/com/myself/nettychat/common/utils/ResultVOUtil.java index b2b678d..52fdf21 100644 --- a/src/main/java/com/myself/nettychat/common/utils/ResultVOUtil.java +++ b/src/main/java/com/myself/nettychat/common/utils/ResultVOUtil.java @@ -1,30 +1,30 @@ -package com.myself.nettychat.common.utils; - -import com.myself.nettychat.vo.ResultVo; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 20:59 2018\10\7 0007 - */ -public class ResultVOUtil { - public static ResultVo success(Object object){ - ResultVo resultVO = new ResultVo(); - resultVO.setData(object); - resultVO.setCode(200); - resultVO.setMsg("成功"); - return resultVO; - } - - public static ResultVo success(){ - return success(null); - } - - public static ResultVo error(Integer code, String msg){ - ResultVo resultVO = new ResultVo(); - resultVO.setCode(code); - resultVO.setMsg(msg); - return resultVO; - } -} +package com.myself.nettychat.common.utils; + +import com.myself.nettychat.vo.ResultVo; + +/** + * @Author:UncleCatMySelf + * @Email:zhupeijie_java@126.com + * @QQ:1341933031 + * @Date:Created in 20:59 2018\10\7 0007 + */ +public class ResultVOUtil { + public static ResultVo success(Object object){ + ResultVo resultVO = new ResultVo(); + resultVO.setData(object); + resultVO.setCode(200); + resultVO.setMsg("成功"); + return resultVO; + } + + public static ResultVo success(){ + return success(null); + } + + public static ResultVo error(Integer code, String msg){ + ResultVo resultVO = new ResultVo(); + resultVO.setCode(code); + resultVO.setMsg(msg); + return resultVO; + } +} diff --git a/src/main/java/com/myself/nettychat/common/utils/SendUtil.java b/src/main/java/com/myself/nettychat/common/utils/SendUtil.java index c902996..a110caa 100644 --- a/src/main/java/com/myself/nettychat/common/utils/SendUtil.java +++ b/src/main/java/com/myself/nettychat/common/utils/SendUtil.java @@ -33,6 +33,48 @@ public boolean send(Integer item, Channel channel, String channelID, String type return false; } + /** + * 消息测试 + * @param channel + * @param result + * @return + */ + public boolean send(Channel channel, String result){ + try { + if (channel != null){ + System.out.println("send:" + result); + ByteBuf msg = Unpooled.unreleasableBuffer( + Unpooled.copiedBuffer(result, Charset.forName("UTF-8"))); + channel.writeAndFlush(msg.duplicate()); + return true; + } + }catch (Exception e){ + System.out.println(e.getMessage()); + return false; + } + return false; + } + + /** + * 向websocket端发送信息 + * @param channel + * @param result + * @return + */ + public boolean sendWebSocket(Channel channel, String result){ + try { + if (channel != null){ + System.out.println("send:" + result); + channel.writeAndFlush(new TextWebSocketFrame(result)); + return true; + } + }catch (Exception e){ + System.out.println(e.getMessage()); + return false; + } + return false; + } + /** * 广播发送事件 * @param items diff --git a/src/main/java/com/myself/nettychat/common/zookeeper/ZkStateListener.java b/src/main/java/com/myself/nettychat/common/zookeeper/ZkStateListener.java deleted file mode 100644 index b2658fa..0000000 --- a/src/main/java/com/myself/nettychat/common/zookeeper/ZkStateListener.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.myself.nettychat.common.zookeeper; - -import org.apache.curator.framework.CuratorFramework; -import org.apache.curator.framework.state.ConnectionState; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc zookeeper 监听 - **/ -public interface ZkStateListener { - - default void connectedEvent(CuratorFramework curator, ConnectionState state) { - } - - default void ReconnectedEvent(CuratorFramework curator, ConnectionState state) { - } - - default void lostEvent(CuratorFramework curator, ConnectionState state) { - } - -} diff --git a/src/main/java/com/myself/nettychat/common/zookeeper/ZkUtils.java b/src/main/java/com/myself/nettychat/common/zookeeper/ZkUtils.java deleted file mode 100644 index 1cc853b..0000000 --- a/src/main/java/com/myself/nettychat/common/zookeeper/ZkUtils.java +++ /dev/null @@ -1,366 +0,0 @@ -package com.myself.nettychat.common.zookeeper; - -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -import com.google.common.base.Charsets; -import com.google.common.base.Objects; -import org.apache.commons.lang3.ObjectUtils; -import org.apache.curator.framework.CuratorFramework; -import org.apache.curator.framework.CuratorFrameworkFactory; -import org.apache.curator.framework.api.GetDataBuilder; -import org.apache.curator.framework.recipes.cache.NodeCache; -import org.apache.curator.framework.recipes.cache.PathChildrenCache; -import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent; -import org.apache.curator.framework.recipes.cache.TreeCache; -import org.apache.curator.framework.state.ConnectionState; -import org.apache.curator.retry.RetryNTimes; -import org.apache.curator.utils.CloseableUtils; -import org.apache.curator.utils.ZKPaths; -import org.apache.zookeeper.CreateMode; -import org.apache.zookeeper.data.Stat; - -import java.util.List; -import java.util.Map; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.function.BiConsumer; -import java.util.function.Function; -import java.util.stream.Collectors; - -@Slf4j -@Data -@NoArgsConstructor -public class ZkUtils { - - private CuratorFramework zkClient = null; - - ExecutorService pool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2); - - List pathChildrenCaches = new CopyOnWriteArrayList<>(); - - List nodeCaches = new CopyOnWriteArrayList<>(); - - List treeCaches = new CopyOnWriteArrayList<>(); - - - /** - * 初始化zk链接 - * - * @param zookeeperServer - * @param connectionTimeout - * @param sessionTimeout - * @param maxRetries - * @param retriesSleepTime - * @param namespace - * @param listener - */ - public void init(String zookeeperServer, - int connectionTimeout, - int sessionTimeout, - int maxRetries, int retriesSleepTime, - String namespace, - ZkStateListener listener) { - if (zkClient == null) { - zkClient = CuratorFrameworkFactory.builder() - .connectString(zookeeperServer) - .connectionTimeoutMs(connectionTimeout) - .sessionTimeoutMs(sessionTimeout) - .namespace(namespace) - .retryPolicy(new RetryNTimes(maxRetries, retriesSleepTime)) - .build(); - } - zkClient.getConnectionStateListenable().addListener((curatorFramework, connectionState) -> { - pathChildrenCaches.clear(); - nodeCaches.clear(); - treeCaches.clear(); - if (connectionState == ConnectionState.CONNECTED) { - listener.connectedEvent(curatorFramework, connectionState); - } else if (connectionState == ConnectionState.RECONNECTED) { - listener.ReconnectedEvent(curatorFramework, connectionState); - } else if (connectionState == ConnectionState.LOST) { - listener.lostEvent(curatorFramework, connectionState); - } - }); - zkClient.start(); - } - /** - * 销毁所有 - */ - public void destory() { - pathChildrenCaches.stream().forEach(cache -> CloseableUtils.closeQuietly(cache)); - pathChildrenCaches.clear(); - pathChildrenCaches = null; - nodeCaches.stream().forEach(cache -> CloseableUtils.closeQuietly(cache)); - nodeCaches.clear(); - nodeCaches = null; - treeCaches.stream().forEach(cache -> CloseableUtils.closeQuietly(cache)); - treeCaches.clear(); - treeCaches = null; - if (zkClient != null) { - CloseableUtils.closeQuietly(zkClient); - } - } - - - /** - * 创建节点 - * - * @param path - * @param data - * @param mode - * @return - */ - public boolean createNode(String path, String data, CreateMode mode) { - if (!ObjectUtils.allNotNull(zkClient, path)) { - return Boolean.FALSE; - } - try { - Stat stat = exists(path); - if (stat == null) { - mode = mode == null ? CreateMode.PERSISTENT : mode; - String opResult; - if (ObjectUtils.allNotNull(data)) { - opResult = zkClient.create().creatingParentContainersIfNeeded().withMode(mode).forPath(path, data.getBytes(Charsets.UTF_8)); - } else { - opResult = zkClient.create().creatingParentContainersIfNeeded().withMode(mode).forPath(path); - } - return Objects.equal(opResult, path); - } - return Boolean.TRUE; - } catch (Exception e) { - log.error("create node fail! path: {}, error: {}", path, e); - } - return Boolean.FALSE; - } - - - /** - * 删除节点 递归删除子节点 - * - * @param path - * @param version - * @return - */ - public boolean deleteNode(String path, Integer version) { - if (!ObjectUtils.allNotNull(zkClient, path)) { - return Boolean.FALSE; - } - try { - Stat stat = exists(path); - if (stat != null) { - if (version == null) { - zkClient.delete().deletingChildrenIfNeeded().forPath(path); - } else { - zkClient.delete().deletingChildrenIfNeeded().withVersion(version).forPath(path); - } - } - return Boolean.TRUE; - } catch (Exception e) { - log.error("delete node fail! path: {}, error: {}", path, e); - } - return Boolean.FALSE; - } - - /** - * 删除节点 - * - * @param path - * @return - */ - public boolean deleteNode(String path) { - return deleteNode(path, null); - } - - /** - * 获取指定节点的值 - * - * @param path - * @return - */ - public byte[] getNodeData(String path) { - if (!ObjectUtils.allNotNull(zkClient, path)) { - return null; - } - try { - Stat stat = exists(path); - if (stat != null) { - return zkClient.getData().forPath(path); - } - } catch (Exception e) { - log.error("get node data fail! path: {}, error: {}", path, e); - } - return null; - } - - /** - * 获取指定节点的值 - * - * @param path - * @return - */ - public String getNodeDataStr(String path) { - byte[] val = getNodeData(path); - return val == null ? null : new String(val, Charsets.UTF_8); - } - - /** - * 检查节点是否存在 - * - * @param path - * @return - */ - public Stat exists(String path) { - if (!ObjectUtils.allNotNull(zkClient, path)) { - return null; - } - try { - return zkClient.checkExists().forPath(path); - } catch (Exception e) { - log.error("check node exists fail! path: {}, error: {}", path, e); - } - return null; - } - - /** - * 检查节点是否存在 - * - * @param path - * @return - */ - public boolean checkExists(String path) { - return exists(path) == null ? Boolean.FALSE : Boolean.TRUE; - } - - /** - * 设置节点数据 - * - * @param path - * @param data - * @return - */ - public boolean setNodeData(String path, String data) { - return setNodeData(path, data.getBytes(Charsets.UTF_8), null); - } - - /** - * 设置节点数据 - * - * @param path - * @param data - * @param version - * @return - */ - public boolean setNodeData(String path, byte[] data, Integer version) { - if (!ObjectUtils.allNotNull(zkClient, path)) { - return Boolean.FALSE; - } - try { - Stat stat = exists(path); - if (stat != null) { - if (version == null) { - zkClient.setData().forPath(path, data); - } else { - zkClient.setData().withVersion(version).forPath(path, data); - } - return Boolean.TRUE; - } - } catch (Exception e) { - log.error("set node data fail! path: {}, error: {}", path, e); - } - return Boolean.FALSE; - } - - /** - * 设置子节点更改监听 - * - * @param path - * @throws Exception - */ - public boolean listenerPathChildrenCache(String path, BiConsumer biConsumer) { - - if (!ObjectUtils.allNotNull(zkClient, path, biConsumer)) { - return Boolean.FALSE; - } - try { - Stat stat = exists(path); - if (stat != null) { - PathChildrenCache watcher = new PathChildrenCache(zkClient, path, true); - watcher.start(PathChildrenCache.StartMode.POST_INITIALIZED_EVENT); - //该模式下 watcher在重连的时候会自动 rebuild - watcher.getListenable().addListener(biConsumer::accept, pool); - if (!pathChildrenCaches.contains(watcher)) { - pathChildrenCaches.add(watcher); - } -// else{ -// watcher.rebuild(); -// } - return Boolean.TRUE; - } - } catch (Exception e) { - log.error("listen path children cache fail! path:{} , error:{}", path, e); - } - return Boolean.FALSE; - } - - - /** - * 读取指定节点的子菜单的值 - * - * @param path - * @return - */ - public Map readTargetChildsData(String path) { - if (!ObjectUtils.allNotNull(zkClient, path)) { - return null; - } - Map map = null; - try { - Stat stat = exists(path); - if (stat != null) { - List childrens = zkClient.getChildren().forPath(path); - GetDataBuilder dataBuilder = zkClient.getData(); - if (childrens != null) { - map = childrens.stream().collect(Collectors.toMap(Function.identity(), (child) -> { - try { - return new String(dataBuilder.forPath(ZKPaths.makePath(path, child)), Charsets.UTF_8); - } catch (Exception e1) { - return null; - } - })); - } - } - } catch (Exception e) { - log.error("get target childs data fail!, path:{} , error:{}", path, e); - } - return map; - - } - - - public static void main(String[] a) throws Exception { - ZkUtils zkUtils = new ZkUtils(); - zkUtils.init("127.0.0.1:2181", 1000, 2000, 5, 1000, "test", new ZkStateListener() { - @Override - public void connectedEvent(CuratorFramework curator, ConnectionState state) { - - } - - @Override - public void ReconnectedEvent(CuratorFramework curator, ConnectionState state) { - - } - - @Override - public void lostEvent(CuratorFramework curator, ConnectionState state) { - - } - }); - zkUtils.getZkClient().create().creatingParentContainersIfNeeded().withMode(CreateMode.EPHEMERAL).forPath("/yy/uu/ii"); - - Thread.sleep(Long.MAX_VALUE); - } - -} diff --git a/src/main/java/com/myself/nettychat/common/zookeeper/testZk.java b/src/main/java/com/myself/nettychat/common/zookeeper/testZk.java deleted file mode 100644 index e51292b..0000000 --- a/src/main/java/com/myself/nettychat/common/zookeeper/testZk.java +++ /dev/null @@ -1,256 +0,0 @@ -package com.myself.nettychat.common.zookeeper; - -import org.apache.curator.RetryPolicy; -import org.apache.curator.framework.CuratorFramework; -import org.apache.curator.framework.CuratorFrameworkFactory; -import org.apache.curator.framework.api.ACLProvider; -import org.apache.curator.framework.api.CuratorEvent; -import org.apache.curator.framework.api.CuratorListener; -import org.apache.curator.framework.recipes.cache.*; -import org.apache.curator.retry.ExponentialBackoffRetry; -import org.apache.curator.retry.RetryNTimes; -import org.apache.zookeeper.WatchedEvent; -import org.apache.zookeeper.Watcher; -import org.apache.zookeeper.ZooDefs; -import org.apache.zookeeper.data.ACL; -import org.apache.zookeeper.data.Id; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 测试 - **/ -public class testZk { - - /** - * 先测试玩玩 - * @描述:XXXXXXX - * @param args - * @return void - * @exception - * @createTime:2016年5月17日 - * @author: songqinghu - * @throws Exception - */ - public static void main(String[] args) throws Exception { - CuratorFramework client = clientTwo(); - //setListenterDateNode(); - //setListenterThreeOne(client); - // setListenterThreeTwo(client); - setListenterThreeThree(client); - // getDataNode(client, "/two"); - // setDataNode(client, "/two", "sss"); - - } - - /** - * - * @描述:创建一个zookeeper连接---连接方式一: 最简单的连接 - * @return void - * @exception - * @createTime:2016年5月17日 - * @author: songqinghu - */ - private static CuratorFramework clientOne(){ - //zk 地址 - String connectString = "10.125.2.44:2181"; - // 连接时间 和重试次数 - RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3); - CuratorFramework client = CuratorFrameworkFactory.newClient(connectString, retryPolicy); - client.start(); - return client; - } - - /** - * - * @描述:创建一个zookeeper连接---连接方式二:优选这个 - * @return void - * @exception - * @createTime:2016年5月17日 - * @author: songqinghu - */ - private static CuratorFramework clientTwo(){ - - //默认创建的根节点是没有做权限控制的--需要自己手动加权限???---- - ACLProvider aclProvider = new ACLProvider() { - private List acl ; - @Override - public List getDefaultAcl() { - if(acl ==null){ - ArrayList acl = ZooDefs.Ids.CREATOR_ALL_ACL; - acl.clear(); - acl.add(new ACL(ZooDefs.Perms.ALL, new Id("auth", "admin:admin") )); - this.acl = acl; - } - return acl; - } - @Override - public List getAclForPath(String path) { - return acl; - } - }; - String scheme = "digest"; - byte[] auth = "admin:admin".getBytes(); - int connectionTimeoutMs = 5000; - String connectString = "127.0.0.1:2181"; - String namespace = "testnamespace"; - CuratorFramework client = CuratorFrameworkFactory.builder().aclProvider(aclProvider). - authorization(scheme, auth). - connectionTimeoutMs(connectionTimeoutMs). - connectString(connectString). - namespace(namespace). - retryPolicy(new RetryNTimes(Integer.MAX_VALUE, 1000)).build(); - client.start(); - return client; - } - - - /** - * - * @描述:第一种监听器的添加方式: 对指定的节点进行添加操作 - * 仅仅能监控指定的本节点的数据修改,删除 操作 并且只能监听一次 --->不好 - * @return void - * @exception - * @createTime:2016年5月18日 - * @author: songqinghu - * @throws Exception - */ - private static void setListenterOne(CuratorFramework client) throws Exception{ - // 注册观察者,当节点变动时触发 - byte[] data = client.getData().usingWatcher(new Watcher() { - @Override - public void process(WatchedEvent event) { - System.out.println("获取 two 节点 监听器 : " + event); - } - }).forPath("/two"); - System.out.println("two 节点数据: "+ new String(data)); - } - /** - * - * @描述:第二种监听器的添加方式: - * 也是一次性的监听操作,使用后就无法在继续监听了 - * @return void - * @exception - * @createTime:2016年5月18日 - * @author: songqinghu - * @throws Exception - */ - private static void setListenterTwo(CuratorFramework client) throws Exception{ - - ExecutorService pool = Executors.newCachedThreadPool(); - - CuratorListener listener = new CuratorListener() { - @Override - public void eventReceived(CuratorFramework client, CuratorEvent event) throws Exception { - System.out.println("监听器 : "+ event.toString()); - } - }; - client.getCuratorListenable().addListener(listener,pool); - client.getData().inBackground().forPath("/two"); - client.getData().inBackground().forPath("/two"); - client.getData().inBackground().forPath("/two"); - client.getData().inBackground().forPath("/two"); - Thread.sleep(Long.MAX_VALUE ); - } - /** - * - * @描述:第三种监听器的添加方式: Cache 的三种实现 实践 - * Path Cache:监视一个路径下1)孩子结点的创建、2)删除,3)以及结点数据的更新。 - * 产生的事件会传递给注册的PathChildrenCacheListener。 - * Node Cache:监视一个结点的创建、更新、删除,并将结点的数据缓存在本地。 - * Tree Cache:Path Cache和Node Cache的“合体”,监视路径下的创建、更新、删除事件,并缓存路径下所有孩子结点的数据。 - * @return void - * @exception - * @createTime:2016年5月18日 - * @author: songqinghu - * @throws Exception - */ - //1.path Cache 连接 路径 是否获取数据 - //能监听所有的字节点 且是无限监听的模式 但是 指定目录下节点的子节点不再监听 - private static void setListenterThreeOne(CuratorFramework client) throws Exception{ - ExecutorService pool = Executors.newCachedThreadPool(); - PathChildrenCache childrenCache = new PathChildrenCache(client, "/test", true); - PathChildrenCacheListener childrenCacheListener = new PathChildrenCacheListener() { - @Override - public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception { - System.out.println("开始进行事件分析:-----"); - ChildData data = event.getData(); - switch (event.getType()) { - case CHILD_ADDED: - System.out.println("CHILD_ADDED : "+ data.getPath() +" 数据:"+ data.getData()); - break; - case CHILD_REMOVED: - System.out.println("CHILD_REMOVED : "+ data.getPath() +" 数据:"+ data.getData()); - break; - case CHILD_UPDATED: - System.out.println("CHILD_UPDATED : "+ data.getPath() +" 数据:"+ data.getData()); - break; - default: - break; - } - } - }; - childrenCache.getListenable().addListener(childrenCacheListener); - System.out.println("Register zk watcher successfully!"); - childrenCache.start(PathChildrenCache.StartMode.POST_INITIALIZED_EVENT); - } - - //2.Node Cache 监控本节点的变化情况 连接 目录 是否压缩 - //监听本节点的变化 节点可以进行修改操作 删除节点后会再次创建(空节点) - private static void setListenterThreeTwo(CuratorFramework client) throws Exception{ - ExecutorService pool = Executors.newCachedThreadPool(); - //设置节点的cache - final NodeCache nodeCache = new NodeCache(client, "/test", false); - nodeCache.getListenable().addListener(new NodeCacheListener() { - @Override - public void nodeChanged() throws Exception { - System.out.println("the test node is change and result is :"); - System.out.println("path : "+nodeCache.getCurrentData().getPath()); - System.out.println("data : "+new String(nodeCache.getCurrentData().getData())); - System.out.println("stat : "+nodeCache.getCurrentData().getStat()); - } - }); - nodeCache.start(); - } - //3.Tree Cache - // 监控 指定节点和节点下的所有的节点的变化--无限监听 可以进行本节点的删除(不在创建) - private static void setListenterThreeThree(CuratorFramework client) throws Exception{ - ExecutorService pool = Executors.newCachedThreadPool(); - //设置节点的cache - TreeCache treeCache = new TreeCache(client, "/test"); - //设置监听器和处理过程 - treeCache.getListenable().addListener(new TreeCacheListener() { - @Override - public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception { - ChildData data = event.getData(); - if(data !=null){ - switch (event.getType()) { - case NODE_ADDED: - System.out.println("NODE_ADDED : "+ data.getPath() +" 数据:"+ new String(data.getData())); - break; - case NODE_REMOVED: - System.out.println("NODE_REMOVED : "+ data.getPath() +" 数据:"+ new String(data.getData())); - break; - case NODE_UPDATED: - System.out.println("NODE_UPDATED : "+ data.getPath() +" 数据:"+ new String(data.getData())); - break; - - default: - break; - } - }else{ - System.out.println( "data is null : "+ event.getType()); - } - } - }); - //开始监听 - treeCache.start(); - - } - -} diff --git a/src/main/java/com/myself/nettychat/config/TCPServerHandler.java b/src/main/java/com/myself/nettychat/config/TCPServerHandler.java index f5afdfc..87955da 100644 --- a/src/main/java/com/myself/nettychat/config/TCPServerHandler.java +++ b/src/main/java/com/myself/nettychat/config/TCPServerHandler.java @@ -1,6 +1,8 @@ package com.myself.nettychat.config; import com.myself.nettychat.common.utils.*; +import com.myself.nettychat.dto.CacheDTO; +import com.myself.nettychat.template.CacheTemplate; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; @@ -10,9 +12,11 @@ import io.netty.util.ReferenceCountUtil; import io.netty.util.concurrent.GlobalEventExecutor; import io.netty.util.concurrent.ScheduledFuture; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; +import java.util.List; import java.util.Set; import java.util.UUID; import java.util.concurrent.TimeUnit; @@ -30,214 +34,42 @@ public class TCPServerHandler extends ChannelInboundHandlerAdapter { static final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + @Autowired + private CacheTemplate cacheTemplate; + @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { String ChannelID = null; - try{ + try { String data = (String)msg; - System.out.println(data); - if (DataValida.ValidateHeadAndFeet(data)){ - data = DataResction.ResctionHeadAndFeet(data); - if (DataValida.ValidateCRCCode(DataResction.ResctionData(data),DataResction.ResctionCRCCode(data))){ - data = DataResction.ResctionData(data); - ChannelID = DataResction.ResctionID(data); - System.out.println("Const.hasChannelID(ChannelID):"+ Const.hasChannelID(ChannelID)); - //更换连接ID - if (!Const.hasChannelID(ChannelID)){ - String realChannelID = Const.isChannel(ctx.channel()); - System.out.println(realChannelID); - Const.ChangeClientId(realChannelID,ChannelID); - } - //检查重复链接ID 不同实例 切换实例 - if(Const.hasChannelID(ChannelID)){ - Const.changeChannel(ChannelID,ctx.channel()); + //切换真实ID + String realChannelID = Const.isChannel(ctx.channel()); + ChannelID = data.substring(0,4); + String type = data.substring(4,5); + System.out.println(ChannelID); + Const.ChangeClientId(realChannelID,ChannelID); + if (type.equals("c")){ + String tip = data.substring(data.length()-1,data.length()); + System.out.println("tip="+tip); + if (cacheTemplate.hasCacheDTO(ChannelID)){ + System.out.println("true"); + List cacheDTOList = cacheTemplate.getDTO(ChannelID); + System.out.println(cacheDTOList.size()); + for (CacheDTO item: cacheDTOList){ + if (tip.equals(item.getMsg())){ + SendUtil sendUtil = new SendUtil(); + sendUtil.sendWebSocket((Channel) cacheTemplate.getChannel(item.getToken()),"开锁成功!"); + System.out.println("通知成功"); + } } - data = DataResction.ResctionDataNoID(data); - String type = DataResction.ResctionType(data); - String RealData = DataResction.ResctionRealData(data); - //数据类型判断 - switch (type){ - case "s": - //控制类型 - futureByController(ctx,RealData,ChannelID); - break; - case "g": - //经纬度传输 - futureByLoLa(ctx,RealData,ChannelID); - break; - case "v": - //设备电量信息 - RealData = DataResction.ResctionPower(RealData); - futureByCharge(ctx,RealData,ChannelID); - break; - case "p": - //设备检测物体信息 - futureByPStates(ctx,RealData,ChannelID); - break; - case "r": - //设备开关异常 - futureByException(ctx,RealData,ChannelID); - break; - case "j": - //客户端执行结果 - futureByChlientResult(ctx,RealData,ChannelID); - break; - case "t": - futureBYTesting(ctx,RealData,ChannelID); - break; - default: - //其他类型 - ctx.writeAndFlush(CallBackMessage.sendString( - CRC16MySelf.getAllString(ChannelID,Const.RESULT_TYPE,Const.ERROR))); - break; - } - } else { - ctx.writeAndFlush(CallBackMessage.ERROR.duplicate()); - ctx.close(); } - } else { - ctx.writeAndFlush(CallBackMessage.ERROR.duplicate()); - ctx.close(); } + ctx.writeAndFlush(CallBackMessage.Check1_test.duplicate()); }finally { ReferenceCountUtil.release(msg); } } - - /** - * 客户端执行开锁测试执行方法 - * @param ctx - * @param realData - * @param ChannelID - */ - private void futureBYTesting(ChannelHandlerContext ctx, String realData, String ChannelID) { - Set ids = Const.getIdList(); - System.out.println("测试广播事件执行"); - for (String item : ids){ - SendUtil sendUtil = new SendUtil(); - Channel channel = Const.get(item); - if (channel != null){ - sendUtil.sendAll(realData,channel,item,Const.RESULT_TEXT); - } - } - } - - /** - * 客户端执行结果执行方法 - * @param ctx - * @param realData - */ - private void futureByChlientResult(ChannelHandlerContext ctx, String realData,String ChannelID) { - //测试方法 - ScheduledFuture future = ctx.channel().eventLoop().schedule( - new Runnable() { - @Override - public void run() { - System.out.println("-------尝试执行SQL操作--------客户端执行结果"); - } - },0, TimeUnit.SECONDS); - ctx.writeAndFlush(CallBackMessage.sendString( - CRC16MySelf.getAllString(ChannelID,Const.RESULT_TYPE,Const.SUCCESS))); - } - - /** - * 开关异常执行方法 - * @param ctx - * @param realData - */ - private void futureByException(ChannelHandlerContext ctx,final String realData,final String ChannelID) { - //测试方法 - ScheduledFuture future = ctx.channel().eventLoop().schedule( - new Runnable() { - @Override - public void run() { - System.out.println("-------尝试执行SQL操作--------开关异常"); - } - },0,TimeUnit.SECONDS); - ctx.writeAndFlush(CallBackMessage.sendString( - CRC16MySelf.getAllString(ChannelID,Const.RESULT_TYPE,Const.SUCCESS))); - } - - /** - * 设备电量执行方法 - * @param ctx - * @param realData - */ - private void futureByCharge(ChannelHandlerContext ctx,final String realData,final String ChannelID) { - //测试方法 - ScheduledFuture future = ctx.channel().eventLoop().schedule( - new Runnable() { - @Override - public void run() { - System.out.println("-------尝试执行SQL操作--------设备电量"); - } - },0,TimeUnit.SECONDS); - ctx.writeAndFlush(CallBackMessage.sendString( - CRC16MySelf.getAllString(ChannelID,Const.RESULT_TYPE,Const.SUCCESS))); - } - - /** - * 经纬度传输执行方法 - * @param ctx - * @param realData - */ - private void futureByLoLa(ChannelHandlerContext ctx, String realData, final String ChannelID) { - final String Longitude = DataResction.ResctionLongitude(realData); - final String Latitude = DataResction.ResctionLatitude(realData); - ScheduledFuture future = ctx.channel().eventLoop().schedule( - new Runnable() { - @Override - public void run() { - System.out.println("-------尝试执行SQL操作--------经纬度传输"); - } - },0,TimeUnit.SECONDS); - ctx.writeAndFlush(CallBackMessage.sendString( - CRC16MySelf.getAllString(ChannelID,Const.RESULT_TYPE,Const.SUCCESS))); - } - - /** - * 控制类执行方法 - * @param ctx - * @param realData - */ - private void futureByController(ChannelHandlerContext ctx,final String realData, final String ChannelID) { - //SQL入库操作 - ScheduledFuture future = ctx.channel().eventLoop().schedule( - new Runnable() { - @Override - public void run() { - System.out.println("-------尝试执行SQL操作--------控制类型"); -// - } - },0,TimeUnit.SECONDS); -// ctx.writeAndFlush(CallBackMessage.sendString( -// CRC16MySelf.getAllString(ChannelID,Const.RESULT_TYPE,Const.SUCCESS))); - ctx.writeAndFlush(CallBackMessage.Check1_test.duplicate()); - } - - private void futureByPStates(ChannelHandlerContext ctx,final String realData,final String channelID) { - System.out.println("检测物体事件执行"); - ScheduledFuture future = ctx.channel().eventLoop().schedule( - new Runnable() { - @Override - public void run() { - System.out.println("-------尝试执行SQL操作--------物体检测类型"); - } - },0,TimeUnit.SECONDS); - } - - private String getUpdateKey(String channelID, String pstates, String realData) { - Integer openid = null; - for (int i = 0; i < realData.length(); i++){ - if(pstates.charAt(i) != realData.charAt(i)){ - openid = i; - break; - } - } - return channelID + "_" + openid; - } - @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); diff --git a/src/main/java/com/myself/nettychat/config/TextWebSocketFrameHandler.java b/src/main/java/com/myself/nettychat/config/TextWebSocketFrameHandler.java index a47c5aa..1ecfc3d 100644 --- a/src/main/java/com/myself/nettychat/config/TextWebSocketFrameHandler.java +++ b/src/main/java/com/myself/nettychat/config/TextWebSocketFrameHandler.java @@ -1,26 +1,19 @@ package com.myself.nettychat.config; -import com.myself.nettychat.task.MsgAsyncTesk; -import com.myself.nettychat.constont.LikeRedisTemplate; -import com.myself.nettychat.constont.LikeSomeCacheTemplate; import com.myself.nettychat.common.utils.StringUtil; -import io.netty.buffer.ByteBuf; +import com.myself.nettychat.template.CacheTemplate; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.group.ChannelGroup; import io.netty.channel.group.DefaultChannelGroup; -import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; -import io.netty.handler.codec.http.websocketx.WebSocketFrame; import io.netty.util.concurrent.GlobalEventExecutor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; -import java.io.FileOutputStream; - /** * @Author:UncleCatMySelf @@ -36,71 +29,22 @@ public class TextWebSocketFrameHandler extends SimpleChannelInboundHandler RedisMap = new ConcurrentHashMap<>(); - - private Map SecondRedisMap = new ConcurrentHashMap<>(); - - /**存放链接池实例*/ - private Map ChannelRedisMap = new ConcurrentHashMap<>(); - - public void save(Object id,Object name){ - RedisMap.put(id,name); - SecondRedisMap.put(name,id); - } - - /** - * 存储对应的用户名与Netty链接实例 - * @param name 登录用户名 - * @param channel Netty链接实例 - */ - public void saveChannel(Object name,Object channel){ - ChannelRedisMap.put(name,channel); - } - - /** - * 删除存储池实例 - * @param name 登录用户名 - */ - public void deleteChannel(Object name){ - ChannelRedisMap.remove(name); - } - - /** - * 获取存储池中的链接实例 - * @param name 登录用户名 - * @return {@link io.netty.channel.Channel 链接实例} - */ - public Object getChannel(Object name){ - return ChannelRedisMap.get(name); - } - - /** - * 获取储存池链接数 - * @return 在线数 - */ - public Integer getSize(){ - return ChannelRedisMap.size(); - } - - /** - * 获取连接对应用户名称 - * @param id 连接Id - * @return 用户名称 - */ - public Object getName(Object id){ - return RedisMap.get(id); - } - - - public boolean check(Object id,Object name){ - if (SecondRedisMap.get(name) == null){ - return true; - } - if (id.equals(SecondRedisMap.get(name))){ - return true; - }else{ - return false; - } - } - - public void delete(Object id){ - try { - SecondRedisMap.remove(RedisMap.get(id)); - RedisMap.remove(id); - }catch (NullPointerException e){ - e.printStackTrace(); - } - } - - /** - * 返回在线用户列表信息 - * @return 用户名列表 - */ - public Object getOnline() { - List result = new ArrayList<>(); - for (Object key:ChannelRedisMap.keySet()){ - result.add(key); - } - return result; - } -} diff --git a/src/main/java/com/myself/nettychat/constont/LikeSomeCacheTemplate.java b/src/main/java/com/myself/nettychat/constont/LikeSomeCacheTemplate.java deleted file mode 100644 index e1ca623..0000000 --- a/src/main/java/com/myself/nettychat/constont/LikeSomeCacheTemplate.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.myself.nettychat.constont; - -import com.myself.nettychat.dataobject.UserMsg; -import org.omg.CORBA.OBJ_ADAPTER; -import org.springframework.stereotype.Component; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - -/** - * 聊天内容临时存储 - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 13:38 2018\8\14 0014 - */ -@Component -public class LikeSomeCacheTemplate { - - private List SomeCache = new LinkedList<>(); - - public void save(Object user,Object msg){ - UserMsg userMsg = new UserMsg(); - userMsg.setName(String.valueOf(user)); - userMsg.setMsg(String.valueOf(msg)); - SomeCache.add(userMsg); - } - - public List cloneCacheMap(){ - return SomeCache; - } - - public void clearCacheMap(){ - SomeCache.clear(); - } -} diff --git a/src/main/java/com/myself/nettychat/controller/NCBackController.java b/src/main/java/com/myself/nettychat/controller/NCBackController.java index 579cd9e..05ab733 100644 --- a/src/main/java/com/myself/nettychat/controller/NCBackController.java +++ b/src/main/java/com/myself/nettychat/controller/NCBackController.java @@ -1,13 +1,18 @@ package com.myself.nettychat.controller; +import com.myself.nettychat.common.utils.Const; import com.myself.nettychat.common.utils.ResultVOUtil; import com.myself.nettychat.common.utils.SendUtil; -import com.myself.nettychat.constont.LikeRedisTemplate; +import com.myself.nettychat.dto.CacheDTO; +import com.myself.nettychat.template.CacheTemplate; import com.myself.nettychat.vo.ResultVo; import io.netty.channel.Channel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import java.util.ArrayList; +import java.util.List; + /** * @Author:UncleCatMySelf * @Email:zhupeijie_java@126.com @@ -19,40 +24,68 @@ public class NCBackController { @Autowired - private LikeRedisTemplate redisTemplate; + private CacheTemplate cacheTemplate; - /** - * 获取在线用户数 - * @return {@link ResultVo} - */ - @GetMapping("/size") - public ResultVo getSize(){ - return ResultVOUtil.success(redisTemplate.getSize()); - } +// /** +// * 获取当前连接数 +// * @return +// */ +// @GetMapping(value = "/get_channel_size") +// public ResultVo getChannelSize(){ +// return ResultVOUtil.success(Const.getSzie()); +// } +// +// /** +// * 获取连接Id数组 +// * @return +// */ +// @GetMapping(value = "/get_channel_id_list") +// public ResultVo getChannelIDList(){ +// return ResultVOUtil.success(Const.getIdList()); +// } - /** - * 获取在线用户列表 - * @return {@link ResultVo} - */ - @GetMapping("/online") - public ResultVo getOnline(){ - return ResultVOUtil.success(redisTemplate.getOnline()); - } +// /** +// * 向存在链接发送指定的端口 +// * @param channelId 连接Id +// * @param lock 打开第几把锁 +// * @return +// */ +// @PostMapping(value = "/send_to_channel") +// public ResultVo SendToChannel(String channelId,Integer lock){ +// SendUtil sendUtil = new SendUtil(); +// Channel channel = Const.get(channelId); +// if (channel != null){ +// if (sendUtil.send(lock,channel,channelId,Const.CONTROL_TYPE)){ +// return ResultVOUtil.success("【发送成功】"); +// } +// } +// return ResultVOUtil.error(888,"【发送失败】"); +// } /** - * API调用向在线用户发送消息 - * @param name 用户名 - * @param msg 消息 - * @return {@link ResultVo} + * 单业务模拟-开锁 + * @param channelId 柜子ID--与tcp通信ID一致 + * @param msg 打开第几把锁 + * @param token 用户标识 + * @return */ - @PostMapping("/send") - public ResultVo send(@RequestParam String name,@RequestParam String msg){ - Channel channel = (Channel) redisTemplate.getChannel(name); - if (channel == null){ - return ResultVOUtil.error(555,"当前用户连接已断开"); + @PostMapping(value = "/send_test") + public ResultVo SendTest(String channelId,String msg,String token){ + SendUtil sendUtil = new SendUtil(); + Channel channel = Const.get(channelId); + if (channel != null){ + if (sendUtil.send(channel,msg)){ + String tip = msg.substring(msg.length()-1,msg.length()); + System.out.println(tip); + CacheDTO cacheDTO = new CacheDTO(token,tip); + List cacheDTOList = new ArrayList<>(); + cacheDTOList.add(cacheDTO); + //存储等待二次通知判断 + cacheTemplate.saveDTO(channelId,cacheDTOList); + return ResultVOUtil.success("【发送成功】"); + } } - String result = SendUtil.sendTest(msg,channel); - return ResultVOUtil.success(result); + return ResultVOUtil.error(888,"【发送失败】"); } } diff --git a/src/main/java/com/myself/nettychat/controller/NcChangeController.java b/src/main/java/com/myself/nettychat/controller/NcChangeController.java deleted file mode 100644 index feb492b..0000000 --- a/src/main/java/com/myself/nettychat/controller/NcChangeController.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.myself.nettychat.controller; - -import com.myself.nettychat.constont.CookieConstant; -import com.myself.nettychat.constont.H5Constant; -import com.myself.nettychat.dataobject.User; -import com.myself.nettychat.service.UserService; -import com.myself.nettychat.store.TokenStore; -import com.myself.nettychat.common.utils.CookieUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; -import org.springframework.web.servlet.ModelAndView; - -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import java.util.Map; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 15:59 2018\9\5 0005 - */ -@Controller -@RequestMapping("/su") -public class NcChangeController { - - @Autowired - private UserService userService; - - /** - * 我的中心界面 - * @param map - * @return - */ - @GetMapping("/me") - public ModelAndView Me(Map map){ - ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); - HttpServletRequest request = attributes.getRequest(); - Cookie cookie = CookieUtil.get(request, CookieConstant.TOKEN); - if (cookie == null){ - map.put("msg","cookie中不存在token"); - return new ModelAndView(H5Constant.LOGIN_SUI,map); - } - Integer userId = (Integer) TokenStore.get(cookie.getValue()); - if (userId == null){ - map.put("msg","用户信息不存在"); - return new ModelAndView(H5Constant.LOGIN_SUI,map); - } - User user = userService.findOne(userId); - map.put("userName",user.getUserName()); - return new ModelAndView(H5Constant.ME,map); - } - - /** - * 发现 - * @param map - * @return - */ - @GetMapping("/find") - public ModelAndView find(Map map){ - return new ModelAndView(H5Constant.FIND); - } - - /** - * 聊天 - * @param map - * @return - */ - @GetMapping("/chat") - public ModelAndView chat(Map map){ - return new ModelAndView(H5Constant.CHAT); - } - - /** - * 主页 - * @param map - * @return - */ - @GetMapping("/home") - public ModelAndView home(Map map){ - return new ModelAndView(H5Constant.HOME); - } - -} diff --git a/src/main/java/com/myself/nettychat/controller/NcChatController.java b/src/main/java/com/myself/nettychat/controller/NcChatController.java deleted file mode 100644 index 3a7d79b..0000000 --- a/src/main/java/com/myself/nettychat/controller/NcChatController.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.myself.nettychat.controller; - -import com.myself.nettychat.constont.CookieConstant; -import com.myself.nettychat.constont.H5Constant; -import com.myself.nettychat.dataobject.User; -import com.myself.nettychat.dataobject.UserMsg; -import com.myself.nettychat.repository.UserMsgRepository; -import com.myself.nettychat.service.UserService; -import com.myself.nettychat.store.TokenStore; -import com.myself.nettychat.common.utils.CookieUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; -import org.springframework.web.servlet.ModelAndView; - -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 14:32 2018\8\14 0014 - */ -@Controller -@RequestMapping("/chat") -public class NcChatController { - - @Autowired - private UserMsgRepository userMsgRepository; - - @Autowired - private UserService userService; - - @GetMapping("/netty") - public ModelAndView netty(@RequestParam(value = "page",defaultValue = "1") Integer page, - @RequestParam(value = "size",defaultValue = "10") Integer size, - Map map){ - ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); - HttpServletRequest request = attributes.getRequest(); - Cookie cookie = CookieUtil.get(request, CookieConstant.TOKEN); - if (cookie == null){ - map.put("msg","cookie中不存在token"); - return new ModelAndView(H5Constant.LOGIN,map); - } - Integer userId = (Integer) TokenStore.get(cookie.getValue()); - if (userId == null){ - map.put("msg","用户信息不存在"); - return new ModelAndView(H5Constant.LOGIN,map); - } - User user = userService.findOne(userId); - Sort sort = new Sort(Sort.Direction.DESC,"id"); - Pageable pageable = new PageRequest(page-1,size,sort); - Page userMsgPage = userMsgRepository.findAll(pageable); - //日期颠倒 - List userMsgList = new ArrayList<>(); - for (int i = 0,j = userMsgPage.getContent().size()-1; i < userMsgPage.getContent().size();i++,j--){ - userMsgList.add(userMsgPage.getContent().get(j)); - } - map.put("userName",user.getUserName()); - map.put("userMsgList",userMsgList); - return new ModelAndView(H5Constant.ALLCHAT,map); - } - -} diff --git a/src/main/java/com/myself/nettychat/controller/NcLoginController.java b/src/main/java/com/myself/nettychat/controller/NcLoginController.java deleted file mode 100644 index 2db26fb..0000000 --- a/src/main/java/com/myself/nettychat/controller/NcLoginController.java +++ /dev/null @@ -1,145 +0,0 @@ -package com.myself.nettychat.controller; - -import com.myself.nettychat.constont.CookieConstant; -import com.myself.nettychat.constont.H5Constant; -import com.myself.nettychat.dataobject.User; -import com.myself.nettychat.form.LoginForm; -import com.myself.nettychat.repository.UserMsgRepository; -import com.myself.nettychat.service.UserService; -import com.myself.nettychat.store.TokenStore; -import com.myself.nettychat.common.utils.CookieUtil; -import org.springframework.beans.BeanUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.servlet.ModelAndView; - -import javax.servlet.http.HttpServletResponse; -import javax.validation.Valid; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 16:01 2018\8\18 0018 - */ -@Controller -@RequestMapping("/admin") -public class NcLoginController { - - @Autowired - private UserService userService; - @Autowired - private UserMsgRepository userMsgRepository; - - /** - * 登录页面 - * @return - */ -// @GetMapping("/login") -// public ModelAndView login(Map map){ -// return new ModelAndView(H5Constant.LOGIN); -// } - - - /** - * 登录页面SUI - * @return - */ - @GetMapping("/loginsui") - public ModelAndView loginSui(Map map){ - return new ModelAndView(H5Constant.LOGIN_SUI); - } - - /** - * 注册页面 - * @return - */ - @GetMapping("/regis") - public ModelAndView register(){ - return new ModelAndView(H5Constant.LOGIN_SUI); - } - - - - /** - * 执行注册 - * @param form - * @param bindingResult - * @param response - * @param map - * @return - */ - @PostMapping("/toRegister") - public ModelAndView toRegister(@Valid LoginForm form, BindingResult bindingResult , HttpServletResponse response, - Map map){ - if (bindingResult.hasErrors()){ - map.put("msg",bindingResult.getFieldError().getDefaultMessage()); - return new ModelAndView(H5Constant.LOGIN_SUI,map); - } - List userList = userService.findAll(); - for (User item:userList){ - if (item.getUserName().equals(form.getFUserName())){ - map.put("msg","用户名已存在,请重新填写唯一用户名"); - return new ModelAndView(H5Constant.LOGIN_SUI,map); - } - } - User user = new User(); - BeanUtils.copyProperties(form,user); - userService.save(user); - map.put("userName",user.getUserName()); - map.put("passWord",user.getPassWord()); - return new ModelAndView(H5Constant.LOGIN_SUI,map); - } - - /** - * 登录判断 - * @return - */ - @PostMapping("/toLogin") - public ModelAndView toLogin(@RequestParam(value = "page",defaultValue = "1") Integer page, - @RequestParam(value = "size",defaultValue = "10") Integer size, - @Valid LoginForm form, BindingResult bindingResult , HttpServletResponse response, - Map map){ - if (bindingResult.hasErrors()){ - map.put("msg",bindingResult.getFieldError().getDefaultMessage()); - return new ModelAndView(H5Constant.LOGIN_SUI,map); - } - try { - User user = userService.findByUserName(form.getFUserName()); - if (user.getPassWord().equals(form.getFPassWord())){ - //登录成功 - String token = UUID.randomUUID().toString(); - //将token信息添加到系统缓存中 - TokenStore.add(token,user.getId()); - //将Token信息添加到Cookie中 - CookieUtil.set(response, CookieConstant.TOKEN,token,CookieConstant.EXPIRE); -// Sort sort = new Sort(Sort.Direction.DESC,"id"); -// Pageable pageable = new PageRequest(page-1,size,sort); -// Page userMsgPage = userMsgRepository.findAll(pageable); -// //日期颠倒 -// List userMsgList = new ArrayList<>(); -// for (int i = 0,j = userMsgPage.getContent().size()-1; i < userMsgPage.getContent().size();i++,j--){ -// userMsgList.add(userMsgPage.getContent().get(j)); -// } -// map.put("userMsgList",userMsgList); -// map.put("userName",user.getUserName()); - return new ModelAndView(H5Constant.HOME); - }else{ - map.put("msg","密码错误"); - return new ModelAndView(H5Constant.LOGIN_SUI,map); - } - }catch (Exception e){ - map.put("msg","用户不存在"); - return new ModelAndView(H5Constant.LOGIN_SUI,map); - } - } - -} diff --git a/src/main/java/com/myself/nettychat/dataobject/User.java b/src/main/java/com/myself/nettychat/dataobject/User.java deleted file mode 100644 index d00bbad..0000000 --- a/src/main/java/com/myself/nettychat/dataobject/User.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.myself.nettychat.dataobject; - -import lombok.Data; -import org.hibernate.annotations.DynamicUpdate; - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import java.io.Serializable; -import java.util.Date; - -/** - * 主用户信息表 - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 15:44 2018\8\13 0013 - */ -@Data -@Entity -@DynamicUpdate -public class User implements Serializable { - - private static final long serialVersionUID = 8143981246513357880L; - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Integer id; - - private String userName; - - private String passWord; - - private Date createTime; - - private Date updateTime; - -} diff --git a/src/main/java/com/myself/nettychat/dataobject/UserMsg.java b/src/main/java/com/myself/nettychat/dataobject/UserMsg.java deleted file mode 100644 index a651839..0000000 --- a/src/main/java/com/myself/nettychat/dataobject/UserMsg.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.myself.nettychat.dataobject; - -import lombok.Data; -import org.hibernate.annotations.DynamicUpdate; - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import java.io.Serializable; -import java.util.Date; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 14:03 2018\8\14 0014 - */ -@Data -@Entity -@DynamicUpdate -public class UserMsg implements Serializable { - - private static final long serialVersionUID = 4133316147283239759L; - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Integer id; - - private String name; - - private String msg; - - private Date createTime; - - private Date updateTime; - -} diff --git a/src/main/java/com/myself/nettychat/dto/CacheDTO.java b/src/main/java/com/myself/nettychat/dto/CacheDTO.java new file mode 100644 index 0000000..a0c8ccd --- /dev/null +++ b/src/main/java/com/myself/nettychat/dto/CacheDTO.java @@ -0,0 +1,22 @@ +package com.myself.nettychat.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Author:UncleCatMySelf + * @Email:zhupeijie_java@126.com + * @QQ:1341933031 + * @Date:Created in 22:01 2018\11\8 0008 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class CacheDTO { + + private String token; + + private String msg; + +} diff --git a/src/main/java/com/myself/nettychat/form/LoginForm.java b/src/main/java/com/myself/nettychat/form/LoginForm.java deleted file mode 100644 index 2792a74..0000000 --- a/src/main/java/com/myself/nettychat/form/LoginForm.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.myself.nettychat.form; - -import lombok.Data; - -import javax.validation.constraints.NotEmpty; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 16:02 2018\8\13 0013 - */ -@Data -public class LoginForm { - @NotEmpty(message = "用户名不能为空") - private String fUserName; - @NotEmpty(message = "密码不能为空") - private String fPassWord; - -} diff --git a/src/main/java/com/myself/nettychat/repository/UserMsgRepository.java b/src/main/java/com/myself/nettychat/repository/UserMsgRepository.java deleted file mode 100644 index 6e98ace..0000000 --- a/src/main/java/com/myself/nettychat/repository/UserMsgRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.myself.nettychat.repository; - -import com.myself.nettychat.dataobject.UserMsg; -import org.springframework.data.jpa.repository.JpaRepository; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 14:06 2018\8\14 0014 - */ -public interface UserMsgRepository extends JpaRepository { -} diff --git a/src/main/java/com/myself/nettychat/repository/UserRepository.java b/src/main/java/com/myself/nettychat/repository/UserRepository.java deleted file mode 100644 index be6c18a..0000000 --- a/src/main/java/com/myself/nettychat/repository/UserRepository.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.myself.nettychat.repository; - -import com.myself.nettychat.dataobject.User; -import org.springframework.data.jpa.repository.JpaRepository; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 15:47 2018\8\13 0013 - */ -public interface UserRepository extends JpaRepository { - - User findByUserName(String userName); - -} diff --git a/src/main/java/com/myself/nettychat/service/UserService.java b/src/main/java/com/myself/nettychat/service/UserService.java deleted file mode 100644 index d106993..0000000 --- a/src/main/java/com/myself/nettychat/service/UserService.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.myself.nettychat.service; - -import com.myself.nettychat.dataobject.User; - -import java.util.List; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 15:52 2018\8\18 0018 - */ -public interface UserService { - - User findOne(Integer id); - - User save(User user); - - User findByUserName(String userName); - - List findAll(); -} diff --git a/src/main/java/com/myself/nettychat/service/impl/UserServiceImpl.java b/src/main/java/com/myself/nettychat/service/impl/UserServiceImpl.java deleted file mode 100644 index 951cc04..0000000 --- a/src/main/java/com/myself/nettychat/service/impl/UserServiceImpl.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.myself.nettychat.service.impl; - -import com.myself.nettychat.dataobject.User; -import com.myself.nettychat.repository.UserRepository; -import com.myself.nettychat.service.UserService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 15:52 2018\8\18 0018 - */ -@Service -public class UserServiceImpl implements UserService { - - @Autowired - private UserRepository repository; - - - @Override - public User findOne(Integer id) { - return repository.getOne(id); - } - - @Override - public User save(User user) { - return repository.save(user); - } - - @Override - public User findByUserName(String userName) { - return repository.findByUserName(userName); - } - - @Override - public List findAll() { - return repository.findAll(); - } -} diff --git a/src/main/java/com/myself/nettychat/store/TokenStore.java b/src/main/java/com/myself/nettychat/store/TokenStore.java deleted file mode 100644 index 224cb97..0000000 --- a/src/main/java/com/myself/nettychat/store/TokenStore.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.myself.nettychat.store; - -import lombok.Data; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * 全局Token存储环境实例 - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 18:00 2018\8\13 0013 - */ -@Data -public class TokenStore { - - private static Map TokenStoreMap = new ConcurrentHashMap(); - - /** - * 添加到全局Token缓存中 - * @param token - * @param userId - */ - public static void add(String token,Object userId){ - TokenStoreMap.put(token,userId); - } - - /** - * 从全局Token缓存中移除 - * @param token - */ - public static void remove(String token){ - TokenStoreMap.remove(token); - } - - /** - * 获取Token对象 - * @param token - * @return - */ - public static Object get(String token){ - return TokenStoreMap.get(token); - } -} diff --git a/src/main/java/com/myself/nettychat/task/MsgAsyncTesk.java b/src/main/java/com/myself/nettychat/task/MsgAsyncTesk.java deleted file mode 100644 index 445e50b..0000000 --- a/src/main/java/com/myself/nettychat/task/MsgAsyncTesk.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.myself.nettychat.task; - -import com.myself.nettychat.constont.LikeSomeCacheTemplate; -import com.myself.nettychat.dataobject.User; -import com.myself.nettychat.dataobject.UserMsg; -import com.myself.nettychat.repository.UserMsgRepository; -import com.myself.nettychat.repository.UserRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.scheduling.annotation.Async; -import org.springframework.scheduling.annotation.AsyncResult; -import org.springframework.stereotype.Component; - -import java.util.List; -import java.util.concurrent.Future; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 13:50 2018\8\14 0014 - */ -@Component -public class MsgAsyncTesk { - - @Autowired - private LikeSomeCacheTemplate cacheTemplate; - - @Autowired - private UserMsgRepository userMsgRepository; - - @Autowired - private UserRepository userRepository; - - @Async - public Future saveChatMsgTask() throws Exception{ - - List userMsgList = cacheTemplate.cloneCacheMap(); - for (UserMsg item:userMsgList){ - //保护措施 - User user = userRepository.findByUserName(item.getName()); - if (user != null){ - userMsgRepository.save(item); - } - } - //清空临时缓存 - cacheTemplate.clearCacheMap(); - return new AsyncResult<>(true); - } - -} diff --git a/src/main/java/com/myself/nettychat/task/ScheduledPool.java b/src/main/java/com/myself/nettychat/task/ScheduledPool.java deleted file mode 100644 index ebff4f8..0000000 --- a/src/main/java/com/myself/nettychat/task/ScheduledPool.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.myself.nettychat.task; - -import com.myself.nettychat.common.properties.InitNetty; -import com.myself.nettychat.common.pool.Scheduled; -import org.springframework.stereotype.Service; - -import java.util.concurrent.*; - - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 定时任务 - **/ -@Service -public class ScheduledPool implements Scheduled { - - private ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(20); - - private final InitNetty serverBean; - - public ScheduledPool(InitNetty serverBean) { - this.serverBean = serverBean; - } - - @Override - public ScheduledFuture submit(Runnable runnable) { - int initalDelay = serverBean.getInitalDelay(); - int period = serverBean.getPeriod(); - return scheduledExecutorService.scheduleAtFixedRate(runnable, initalDelay, period, TimeUnit.SECONDS); - } - -} diff --git a/src/main/java/com/myself/nettychat/tcptest/TCPTestClient.java b/src/main/java/com/myself/nettychat/tcptest/TCPTestClient.java index 083983a..f2abae9 100644 --- a/src/main/java/com/myself/nettychat/tcptest/TCPTestClient.java +++ b/src/main/java/com/myself/nettychat/tcptest/TCPTestClient.java @@ -19,7 +19,7 @@ public class TCPTestClient { public static void main(String[] args) throws IOException { //10万测试 - for (int i = 0;i<100000;i++){ + for (int i = 0;i<1;i++){ new Thread(new Runnable() { @Override public void run() { @@ -47,21 +47,21 @@ private static void runtest() throws IOException{ boolean flag = true; int i = 1; while(flag){ - //if (i == 1){ - //帧头+ID+数据类型+24把锁状态+crc校验+帧尾 - String str = "test"; - //发送数据到服务端 - out.println(str); - if("bye".equals(str)){ - flag = false; - }else{ - try{ - //从服务器端接收数据有个时间限制(系统自设,也可以自己设置),超过了这个时间,便会抛出该异常 - String echo = buf.readLine(); - System.out.println(echo); - }catch(SocketTimeoutException e){ - System.out.println("Time out, No response"); + try{ + out.println("4400_test"); + //从服务器端接收数据有个时间限制(系统自设,也可以自己设置),超过了这个时间,便会抛出该异常 + String echo = buf.readLine(); + System.out.println(echo); + if ("stop".equals(echo)){ + flag = false; + }else if("c".equals(echo.substring(0,1))){ + System.err.println(echo); + String str = "4400c"+echo.substring(1,2); + //发送数据到服务端 + out.println(str); } + }catch(SocketTimeoutException e){ + System.out.println("Time out, No response"); } sleep(5000); } diff --git a/src/main/java/com/myself/nettychat/template/CacheTemplate.java b/src/main/java/com/myself/nettychat/template/CacheTemplate.java new file mode 100644 index 0000000..f4dd65b --- /dev/null +++ b/src/main/java/com/myself/nettychat/template/CacheTemplate.java @@ -0,0 +1,55 @@ +package com.myself.nettychat.template; + +import com.myself.nettychat.dto.CacheDTO; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @Author:UncleCatMySelf + * @Email:zhupeijie_java@126.com + * @QQ:1341933031 + * @Date:Created in 21:46 2018\11\8 0008 + */ +@Component +public class CacheTemplate { + + /**存放链接池实例*/ + private Map ChannelRedisMap = new ConcurrentHashMap<>(); + /**用户与柜子与锁关系*/ + private Map> DTOMap = new ConcurrentHashMap<>(); + + /** + * 存储对应的用户名与Netty链接实例 + * @param name 登录用户名 + * @param channel Netty链接实例 + */ + public void saveChannel(String name,Object channel){ + ChannelRedisMap.put(name,channel); + } + + /** + * 获取存储池中的链接实例 + * @param name 登录用户名 + * @return {@link io.netty.channel.Channel 链接实例} + */ + public Object getChannel(String name){ + return ChannelRedisMap.get(name); + } + + public void saveDTO(String channelId,List cacheDTOS){ + System.out.println("添加"+channelId); + DTOMap.put(channelId, cacheDTOS); + } + + public List getDTO(String channelId){ + return DTOMap.get(channelId); + } + + public boolean hasCacheDTO(String channelId){ + return DTOMap.containsKey(channelId); + } + +} diff --git a/src/main/java/com/myself/nettychat/vo/ResultVo.java b/src/main/java/com/myself/nettychat/vo/ResultVo.java index a83c84e..a331794 100644 --- a/src/main/java/com/myself/nettychat/vo/ResultVo.java +++ b/src/main/java/com/myself/nettychat/vo/ResultVo.java @@ -1,28 +1,24 @@ -package com.myself.nettychat.vo; - -import lombok.Data; - -import java.io.Serializable; - -/** - * API 统一返回对象 - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 20:58 2018\10\7 0007 - */ -@Data -public class ResultVo implements Serializable { - - private static final long serialVersionUID = -1020280450330091843L; - - /** 错误码. */ - private Integer code; - - /** 提示信息. */ - private String msg; - - /** 具体内容. */ - private T data; - -} +package com.myself.nettychat.vo; + +import lombok.Data; + +import java.io.Serializable; + +/** + * Created by MySelf on 2018/11/6. + */ +@Data +public class ResultVo implements Serializable { + + private static final long serialVersionUID = -1020280450330091843L; + + /** 错误码. */ + private Integer code; + + /** 提示信息. */ + private String msg; + + /** 具体内容. */ + private T data; + +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 77aaf54..ad5a9c4 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,15 +1,3 @@ -spring: - datasource: - driver-class-name: com.mysql.jdbc.Driver - username: root - password: root - url: jdbc:mysql://localhost:3306/nettychat?characterEncoding=utf-8&useSSL=false - jpa: - show-sql: true -# database: oracle -# properties: -# hibernate: -# dialect: org.hibernate.dialect.Oracle12cDialect server: servlet: context-path: /susu @@ -28,9 +16,7 @@ netty: revbuf: 10485760 # Socket参数,TCP数据接收缓冲区大小。 heart: 180 # 读超时时间 ssl: false # 使用ssl加密 - mqttHander: com.myself.nettychat.bootstrap.handler.DefaultMqttHandler # 默认处理 initalDelay: 10 # mqtts qos1 qos2 消息 重发延迟 - protocol: MQTT # MQTT MQTT_WS_MQTT(mqtts.js) MQTT_WS_PAHO(paho.js) period: 10 # mqtts qos1 qos2 消息 重发周期 jksFile: /securesocket.jks # ssl 加密 jks文件地址 jksStorePassword: mu$tch8ng3 # 读取jks密码 diff --git a/src/main/resources/static/css/allchat.css b/src/main/resources/static/css/allchat.css deleted file mode 100644 index b35a89f..0000000 --- a/src/main/resources/static/css/allchat.css +++ /dev/null @@ -1,59 +0,0 @@ -.history{ - width: 90%; -} - -.his{ - margin-right: auto; - border-left: 20px; - padding-left: 20px; -} - -.chat { - width: 100%; - position: absolute; - box-sizing: border-box; - padding: 10px 4px; - padding-top: 20px; - bottom: 0; -} - -.msgCente{ - text-align: center; - margin-bottom: 100px; -} - -.chatimg{ - height: 90px; - width: 90px; -} - -.msgRight { - text-align: right; -} - -.msgLeft { - text-align: left; -} - -.msgLeft, -.msgRight { - margin-bottom: 26px; -} - -.msgLeft>span, -.msgRight>span { - padding: 10px; - font-size: 16px; - line-height: 20px; - border-radius: 10px; -} - -.msgLeft>span { - background-color: #d8f1f9; - box-shadow: inset -2px -3px 8px 1px #75ddff; -} - -.msgRight>span { - background-color: #FFF; - box-shadow: inset -2px -3px 8px 1px #d8d8d8; -} \ No newline at end of file diff --git a/src/main/resources/static/css/chat.css b/src/main/resources/static/css/chat.css deleted file mode 100644 index 3a25d39..0000000 --- a/src/main/resources/static/css/chat.css +++ /dev/null @@ -1,43 +0,0 @@ -form { - width: 406px; - height: 650px; - border: 4px solid #98bcde; - border-radius: 10px; - margin: 0 auto; - background-color: #eceff9; - display: flex; - flex-wrap: wrap; - justify-content: space-around; -} - -h3 { - color: #92acdc; - text-align: center; - font-size: 26px; -} - -textarea { - resize: none; - font-size: 20px; - width: 401px; - height: 511px; -} - -.msg { - width: 324px; - height: 40px; - text-indent: 10px; - font-size: 20px; - outline: none; -} - -.btn { - width: 78px; - height: 46px; - background-color: #d8f1f9; - border-radius: 6px; - border: 1px solid #98bcde; - font-size: 18px; - color: #92acdc; - font-weight: bold; -} \ No newline at end of file diff --git a/src/main/resources/static/css/newChat.css b/src/main/resources/static/css/newChat.css deleted file mode 100644 index 77f1406..0000000 --- a/src/main/resources/static/css/newChat.css +++ /dev/null @@ -1,172 +0,0 @@ -.container { - width: 750px; - border: 4px solid #98bcde; - border-radius: 10px; - margin: 100px auto; - background-color: #fff; - /*display: flex; - justify-content: space-around;*/ - display: table; - clear: both; - overflow: hidden; -} - -.left_content { - width: 160px; - height: 600px; - background-color: #d8f1f9; - float: left; - text-align: center; -} - -.content { - width: 590px; - height: 600px; - background-color: #FFF; - float: right; -} - -.content_top { - width: 100%; - height: 80px; - background-color: #6fdcff; - position: relative; -} - -.content_top .tips { - text-align: center; - font-size: 16px; - line-height: 30px; - color: #000000; -} - -.content_bodyer { - width: 100%; - height: 410px; - background: #f4f4f4; - overflow: hidden; - position: relative; -} - -.chat { - width: 100%; - position: absolute; - box-sizing: border-box; - padding: 10px 4px; - padding-top: 20px; - bottom: 0; -} - -form { - width: 100%; - height: 110px; - position: relative; -} - -textarea { - resize: none; - font-size: 20px; - width: 100%; - height: 511px; -} - -.msg { - width: 486px; - border: none; - height: 74px; - box-sizing: border-box; - padding: 4px 10px; - font-size: 20px; - outline: none; -} - -.btn { - width: 78px; - height: 30px; - background-color: #d8f1f9; - border-radius: 6px; - border: 1px solid #98bcde; - font-size: 16px; - color: #92acdc; - font-weight: bold; - position: absolute; - bottom: 4px; - right: 4px; -} - -.openHistory { - font-size: 16px; - color: #000; - z-index: 10; - position: absolute; - bottom: 5px; - right: 5px; - cursor: pointer; -} - -.history { - width: 250px; - height: 410px; - background-color: rgba(0, 0, 0, 0.5); - color: #FFF; - font-size: 16px; - position: absolute; - top: 0; - right: 0; - display: none; - z-index: 10; -} - -.scrollbar { - width: 12px; - height: 100%; - background: black; - position: absolute; - right: 0; - top: 0; - opacity: 0.5; - overflow: hidden; - display: none; - z-index: 10; -} - -.scrollbar .thumb { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 40px; - background: #6d6a6a; - cursor: pointer; -} - -.msgRight { - text-align: right; -} - -.msgLeft { - text-align: left; -} - -.msgLeft, -.msgRight { - margin-bottom: 26px; -} - -.msgLeft>span, -.msgRight>span { - padding: 10px; - font-size: 16px; - line-height: 20px; - border-radius: 10px; -} - -.msgLeft>span { - background-color: #d8f1f9; - box-shadow: inset -2px -3px 8px 1px #75ddff; -} - -.msgRight>span { - background-color: #FFF; - box-shadow: inset -2px -3px 8px 1px #d8d8d8; -} \ No newline at end of file diff --git a/src/main/resources/static/css/registered.css b/src/main/resources/static/css/registered.css deleted file mode 100644 index 206cf22..0000000 --- a/src/main/resources/static/css/registered.css +++ /dev/null @@ -1,160 +0,0 @@ -* { - margin: 0; - padding: 0; -} - -.bodyer .panel { - width: 362px; - height: 320px; - border-radius: 6px; - margin: 90px auto; - background: #FFF; - position: relative; - overflow: hidden; -} - -.logo { - width: 100px; - height: 100px; - background: url("../image/logoSmall.png") no-repeat; - position: absolute; - top: 29px; - right: -8px; - transform: rotate(30deg); -} - -.panel_tit { - text-align: center; - line-height: 40px; - font-size: 24px; - padding-top: 20px; - color: #92acdc; -} - -.bodyer .panel .register { - padding-left: 45px; - float: left; - color: #999; - width: 268px; - position: relative; -} - -.bodyer .panel .register .register_top { - font-size: 14px; - margin: 30px 0 26px; -} - -.bodyer .panel .register .register_top span { - margin: 0 2px; -} - -.bodyer .panel .register .register_top a { - font-size: 14px; - text-decoration: none; -} - -.bodyer .panel .register .register_top a:first-child { - color: #303030; -} - -.bodyer .panel .register .register_top a:last-child { - color: #999; -} - -.bodyer .panel .register input { - font-size: 14px; - width: 268px; - height: 38px; - display: block; - box-sizing: border-box; - border: 1px solid #dfdfdf; - padding: 8px 0 8px 36px; -} - -.bodyer .panel .register .user_icon { - position: relative; - margin-bottom: 18px; -} - -.bodyer .panel .register .user_icon input:focus { - border: 1px solid #98bcde; - outline: #98bcde solid 1px; -} - -.bodyer .panel .register .user_icon i { - position: absolute; - display: block; - width: 30px; - height: 30px; - background: url("../image/nuandao.png") no-repeat -310px -390px; -} - -.bodyer .panel .register .pass_icon { - position: relative; - margin-bottom: 30px; -} - -.bodyer .panel .register .pass_icon input:focus { - border: 1px solid #98bcde; - outline: #98bcde solid 1px; -} - -.bodyer .panel .register .pass_icon i { - position: absolute; - display: block; - width: 30px; - height: 30px; - background: url("../image/nuandao.png") no-repeat -333px -434px; -} - -.bodyer .panel .register .pass_icon span { - position: absolute; - left: 0; - bottom: -20px; - color: #d9534f; - font-size: 13px; - display: none; -} - -.bodyer .panel .register input.btn1 { - margin: 0; - padding: 0; - display: block; - width: 100%; - height: 40px; - font-size: 16px; - line-height: 40px; - text-align: center; - text-decoration: none; - color: #FFF; - background: #98bcde; - margin-bottom: 20px; -} - -.bodyer .panel .register input.btn1:hover { - background: #5694ce; -} - -.tips { - width: 100px; - height: 30px; - text-align: center; - font-size: 14px; - line-height: 30px; - background-color: rgba(0, 0, 0, 0.5); - color: #FFF; - position: absolute; - top: 35%; - left: 40%; - display: none; -} - -.mask2 { - width: 100%; - height: 100%; - z-index: -100; - position: fixed; - top: 0; - left: 0; - background: rgba(0, 0, 0, 0.5); -} \ No newline at end of file diff --git a/src/main/resources/static/image/logoBig.jpg b/src/main/resources/static/image/logoBig.jpg deleted file mode 100644 index 0c62304..0000000 Binary files a/src/main/resources/static/image/logoBig.jpg and /dev/null differ diff --git a/src/main/resources/static/image/logoSmall.png b/src/main/resources/static/image/logoSmall.png deleted file mode 100644 index 08b5d51..0000000 Binary files a/src/main/resources/static/image/logoSmall.png and /dev/null differ diff --git a/src/main/resources/static/image/nuandao.png b/src/main/resources/static/image/nuandao.png deleted file mode 100644 index be015d1..0000000 Binary files a/src/main/resources/static/image/nuandao.png and /dev/null differ diff --git a/src/main/resources/static/js/chat.js b/src/main/resources/static/js/chat.js deleted file mode 100644 index 3380613..0000000 --- a/src/main/resources/static/js/chat.js +++ /dev/null @@ -1,51 +0,0 @@ -var socket; -if(!window.WebSocket) { - window.WebSocket = window.MozWebSocket; -} - -if(window.WebSocket) { - socket = new WebSocket("ws://localhost:8090/ws"); - socket.onmessage = function(event) { - var ta = document.getElementById('responseText'); - ta.value = ta.value + '\n' + event.data - }; - socket.onopen = function(event) { - var ta = document.getElementById('responseText'); - if(msg.length > 0){ - ta.value = "--- 连接开启! ---"+'\n'+msg; - }else{ - ta.value = "--- 连接开启! ---" - } - }; - socket.onclose = function(event) { - var ta = document.getElementById('responseText'); - ta.value = ta.value + "连接被关闭"; - }; -} else { - alert("你的浏览器不支持 WebSocket!"); -} - -function send(message) { - if(!window.WebSocket) { - return; - } - if(socket.readyState == WebSocket.OPEN) { - socket.send(message); - } else { - alert("连接没有开启."); - } -} - -window.onbeforeunload = function(event) { - event.returnValue = "刷新提醒"; -} - -; -document.onkeydown = function(e) { - var userName = document.getElementById('userName'); - if(e.keyCode == 13) { - var message = userName.value + '-' +document.getElementsByClassName('msg')[0].value; - send(message); - document.getElementsByClassName('msg')[0].value = ''; - } -} \ No newline at end of file diff --git a/src/main/resources/static/js/newChat.js b/src/main/resources/static/js/newChat.js deleted file mode 100644 index 1bc7e78..0000000 --- a/src/main/resources/static/js/newChat.js +++ /dev/null @@ -1,165 +0,0 @@ -var socket; -if(!window.WebSocket) { - window.WebSocket = window.MozWebSocket; -} - -var chars = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']; - -function generateMixed(n) { - var res = ""; - for(var i = 0; i < n ; i ++) { - var id = Math.ceil(Math.random()*35); - res += chars[id]; - } - return res; -} - -if(window.WebSocket) { - socket = new WebSocket("ws://localhost:8090/ws"); - socket.onmessage = function(event) { - var msg = event.data; - console.log(msg); - if(msg instanceof Blob){ - console.log("blobs"); - var idran = generateMixed(3); - var ta = "
"; - $('.chat').append(ta); - //var previewImg = document.querySelector('img'); - var previewImg = document.getElementById(idran); - - var reader = new FileReader(); - // 监听reader对象的的onload事件,当图片加载完成时,把base64编码賦值给预览图片 - reader.addEventListener("load", function () { - previewImg.src = reader.result; - }, false); - // 调用reader.readAsDataURL()方法,把图片转成base64 - reader.readAsDataURL(msg); - } - if(msg.substring(0, 1) == '[') { - var ta = "
"+event.data+"
"; - $('.chat').append(ta); - } else { - var ta = "
"+event.data+"
"; - $('.chat').append(ta); - } - }; - socket.onopen = function(event) { - $('.tips').html('连接开启!'); - $('.tips').css('color', 'green'); - - var his = $('#TTHistory'); - - console.log(msg); - his.html(msg); - }; - socket.onclose = function(event) { - $('.tips').html('连接被关闭'); - $('.tips').css('color', 'red'); - }; -} else { - var ta = "
你的浏览器不支持 WebSocket!
"; - $('.content_bodyer').append(ta); -} - -function send(message) { - if(!window.WebSocket) { - return; - } - if(socket.readyState == WebSocket.OPEN) { - socket.send(message); - } else { - alert("连接没有开启."); - } -} - -window.onbeforeunload = function(event) { - event.returnValue = "刷新提醒"; -} - -; -// document.onkeydown = function(e) { -// -// var userName = $('#userName'); -// if(e.keyCode == 13) { -// $('.chat').css('bottom', 0); -// var message = userName.val() + '-' + $('.msg').val().trim(); -// send(message); -// $('.msg').val(''); -// } -// } - -function sendd() { - var userName = $('#userName'); - var message = userName.val() + '-' + $('.msg').val().trim(); - send(message); - sendFile(); - $('.msg').val(''); -} - -$('.openHistory').click(function() { - $('.history').fadeToggle(); -}); - -$('.content_bodyer').mouseenter(function() { - $('.scrollbar').fadeIn(); -}) - -$('.content_bodyer').mouseleave(function() { - $('.scrollbar').fadeOut(); -}) - -function sendFile(){ - var thum = $('#file')[0].files[0]; - if(!thum) return; - console.log(thum); - var reader = new FileReader(); - //以二进制形式读取文件 - reader.readAsArrayBuffer(thum); - //文件读取完毕后该函数响应 - reader.onload = function loaded(evt) { - console.log(evt); - var blob = evt.target.result; - //发送二进制表示的文件 - socket.send(blob); - console.log(blob); - - console.log("finnish"); - } -} - -var thumb = $('.thumb'); -var scrollBar = $('.scrollbar'); -var chat = $('.chat'); - -thumb.on('mousedown', function(e) { - chat.css('bottom', 'initial'); - thumb.isMouseDown = true; - return false; -}); - -thumb.on('selectstart', function() { - return false; -}); - -$(window).on('mouseup', function(e) { - thumb.isMouseDown = false; -}); - -$(window).on('mousemove', function(e) { - if (thumb.isMouseDown){ - var pos = e.clientY - scrollBar.parent().offset().top - thumb.height() / 2; - if (pos < 0 ){ - pos = 0; - } else if(pos > scrollBar.height() - thumb.height()){ - pos = scrollBar.height() - thumb.height(); - } - thumb.css("top", pos + "px"); - - // 计算thumb所在的位置占父亲的% - var percentage = thumb.offset().top / (scrollBar.height() - thumb.height()); - var top = (chat.height() - chat.parent().height()) * percentage; - chat.css("top", -top + "px"); - } -}) - - diff --git a/src/main/resources/static/js/registered.js b/src/main/resources/static/js/registered.js deleted file mode 100644 index ebd3ea0..0000000 --- a/src/main/resources/static/js/registered.js +++ /dev/null @@ -1,72 +0,0 @@ -var register = $('.register_top').children().first(); -var register2 = $('.register_top').children().last(); -register.click(function () { - $(register).css('color', ' #303030'); - register2.css('color', '#999'); - $('.btn1').val('登陆'); - $('form').attr("action", "/susu/admin/toLogin"); -}); -register2.click(function () { - $(register2).css('color', ' #303030'); - register.css('color', '#999'); - $('.btn1').val('注册'); - $('form').attr("action", "/susu/admin/toRegister"); -}); -$('.btn3').click(function () { - $('.more').slideToggle(0); -}); - -/** - * 用户名验证 - */ -var input1 = $('.user_icon').children('input'); -var userName = /^[\u4e00-\u9fa5_a-zA-Z]{2,5}$/; -input1.blur(function () { - var val = input1.val().trim(); - if (val.length == 0) { - $($('.Span').children()[0]).css('display', 'block'); - $($('.Span').children()[0]).siblings().css('display', 'none'); - } else if (userName.test(val)) { - $($('.Span').children('span')).css('display', 'none'); - } else { - $($('.Span').children()[1]).css('display', 'block'); - $($('.Span').children()[1]).siblings().css('display', 'none'); - } -}); - -/** - * 密码验证 - */ -var input2 = $('.pass_icon').children('input'); -// 关于密码的正则表达式(6-16位数字和字母的组合) -var Password = /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,16}$/; -input2.blur(function () { - var val = input2.val().trim(); - if (val.length == 0) { - $($('.Span').children()[2]).css('display', 'block'); - $($('.Span').children()[2]).siblings().css('display', 'none'); - } else if (Password.test(val)) { - console.log(1); - $($('.Span').children('span')).css('display', 'none'); - } else { - $($('.Span').children()[3]).css('display', 'block'); - $($('.Span').children()[3]).siblings().css('display', 'none'); - } -}); - -//登录注册校验 -$('form').submit(function(e) { - var User = $('.user_icon').children('input'); - var Pass = $('.pass_icon').children('input'); - var md5_pwd= $('#md5_pwd'); - if (userName.test(User) && Password.test(Pass)) { - return true; - } -}) - -function MsgTo() { - $('.tips').fadeIn(10, function() { - $('.tips').fadeOut(1500); - }); -} - diff --git a/src/main/resources/templates/chat/allchat.ftl b/src/main/resources/templates/chat/allchat.ftl deleted file mode 100644 index 317cd89..0000000 --- a/src/main/resources/templates/chat/allchat.ftl +++ /dev/null @@ -1,49 +0,0 @@ - - -<#include "../common/header.ftl"> - - - -
-
- - - -

全体用户

-
- -
-
- -
-
- -
-
-
-
-
- -
- -
-
- <#--Image preview area...--> -
-
- - -<#include "../common/floor.ftl"> - - - \ No newline at end of file diff --git a/src/main/resources/templates/chat/chat.ftl b/src/main/resources/templates/chat/chat.ftl deleted file mode 100644 index f18b178..0000000 --- a/src/main/resources/templates/chat/chat.ftl +++ /dev/null @@ -1,33 +0,0 @@ - - -<#include "../common/header.ftl"> - - -<#include "../common/floor.ftl"> - - \ No newline at end of file diff --git a/src/main/resources/templates/common/floor.ftl b/src/main/resources/templates/common/floor.ftl deleted file mode 100644 index 9b8124e..0000000 --- a/src/main/resources/templates/common/floor.ftl +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/main/resources/templates/common/header.ftl b/src/main/resources/templates/common/header.ftl deleted file mode 100644 index d519ed4..0000000 --- a/src/main/resources/templates/common/header.ftl +++ /dev/null @@ -1,12 +0,0 @@ - - - - 酥酥 - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/templates/find/find.ftl b/src/main/resources/templates/find/find.ftl deleted file mode 100644 index b0feb38..0000000 --- a/src/main/resources/templates/find/find.ftl +++ /dev/null @@ -1,41 +0,0 @@ - - -<#include "../common/header.ftl"> - -
-
-

酥酥

-
- -
-
-
    -
  • -
    -
    朋友圈
    -
    -
  • -
-
-
-
-<#include "../common/floor.ftl"> - - \ No newline at end of file diff --git a/src/main/resources/templates/h5.ftl b/src/main/resources/templates/h5.ftl deleted file mode 100644 index a650b30..0000000 --- a/src/main/resources/templates/h5.ftl +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - Su Su - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/templates/home/home.ftl b/src/main/resources/templates/home/home.ftl deleted file mode 100644 index f76b3b4..0000000 --- a/src/main/resources/templates/home/home.ftl +++ /dev/null @@ -1,62 +0,0 @@ - - -<#include "../common/header.ftl"> - - -
-
-

酥酥

-
- -
- - - <#--
--> -
-
    -
  • -
    -
    全体用户
    -
    -
  • -
-
- <#-- - <#--
--> - <#--
--> - <#--
--> - <#--
--> -
-
-<#include "../common/floor.ftl"> - - - \ No newline at end of file diff --git a/src/main/resources/templates/login/login.ftl b/src/main/resources/templates/login/login.ftl deleted file mode 100644 index 17e5a2a..0000000 --- a/src/main/resources/templates/login/login.ftl +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - Su Su - - - - - - - -
-
- - - -
-
- -

“酥酥”聊天室

-
-
- 登录 - | - 注册 -
-
-
-
- - -
- 请填写用户名 - 2-5位中文字符和英文字符 - 请填写6-16位数字和字母的组合密码 - 密码格式有误 - <#--${msg!''}--> -
-
- - -
${msg!''}
- -
-
- - - - - - \ No newline at end of file diff --git a/src/main/resources/templates/login/loginSui.ftl b/src/main/resources/templates/login/loginSui.ftl deleted file mode 100644 index 40a962c..0000000 --- a/src/main/resources/templates/login/loginSui.ftl +++ /dev/null @@ -1,124 +0,0 @@ - - -<#include "../common/header.ftl"> - -
-
- -
-

登录

-
- - - - -
-
-
    -
  • -
    -
    -
    -
    账号
    -
    - -
    -
    -
    -
  • -
  • -
    -
    -
    -
    密码
    -
    - -
    -
    -
    -
  • -
-
-
-
- - -
-
-
- -
- -
-
-

注册

-
-
-
- -
-
    - -
  • -
    -
    -
    -
    账号
    -
    - -
    -
    -
    -
  • -
  • -
    -
    -
    -
    密码
    -
    - -
    -
    -
    -
  • -
-
-
-
- - -
-
- -
-
-
- -
-<#include "../common/floor.ftl"> - - - \ No newline at end of file diff --git a/src/main/resources/templates/me/me.ftl b/src/main/resources/templates/me/me.ftl deleted file mode 100644 index 5997f0d..0000000 --- a/src/main/resources/templates/me/me.ftl +++ /dev/null @@ -1,78 +0,0 @@ - - -<#include "../common/header.ftl"> - -
-
-

酥酥

-
- -
-
-
    -
  • -
    -
    ${userName!''}
    -
    -
  • -
-
-
-
-
    -
  • -
    -
    收藏
    -
    -
  • -
-
-
-
    -
  • -
    -
    相册
    -
    -
  • -
-
-
-
    -
  • -
    -
    卡包
    -
    -
  • -
-
-
-
    -
  • -
    -
    表情
    -
    -
  • -
-
-
-
-<#include "../common/floor.ftl"> - - \ No newline at end of file