diff --git a/.github/ISSUE_TEMPLATE/----.md b/.github/ISSUE_TEMPLATE/----.md new file mode 100644 index 0000000..e11187b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/----.md @@ -0,0 +1,22 @@ +--- +name: 功能请求 +about: 功能请求 +title: 功能请求 +labels: '' +assignees: UncleCatMySelf + +--- + +**建议这个项目的想法** + +**您的功能请求是否与问题有关?请描述一下。** +简明扼要地描述了问题所在。防爆。[...]我总是感到沮丧 + +**描述您想要的解决方案** +清晰简洁地描述您想要发生的事情。 + +**描述您考虑过** +的替代方案对您考虑过的任何替代解决方案或功能的简明扼要描述。 + +**其他上下文** +在此处添加有关功能请求的任何其他上下文或屏幕截图。 diff --git a/.gitignore b/.gitignore index 82eca33..421462b 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,8 @@ /nbbuild/ /dist/ /nbdist/ -/.nb-gradle/ \ No newline at end of file +/.nb-gradle/ + +### log ### + +*.log \ No newline at end of file diff --git a/Front-End-Testing/chat70.html b/Front-End-Testing/chat70.html new file mode 100644 index 0000000..ea22f3d --- /dev/null +++ b/Front-End-Testing/chat70.html @@ -0,0 +1,156 @@ + + + + + WebSocket Chat + + + + +
+

InChat 聊天室-8070

+ +
+ + + + + +
+
+
+ + \ No newline at end of file diff --git a/Front-End-Testing/chat90.html b/Front-End-Testing/chat90.html new file mode 100644 index 0000000..e039f7f --- /dev/null +++ b/Front-End-Testing/chat90.html @@ -0,0 +1,156 @@ + + + + + WebSocket Chat + + + + +
+

InChat 聊天室-8090

+ +
+ + + + + +
+
+
+ + \ No newline at end of file diff --git a/README.md b/README.md index dbafcba..4df66e4 100644 --- a/README.md +++ b/README.md @@ -1,55 +1,85 @@ -# InChat -#### [Developer Chat](https://gitter.im/In-Chat/Lobby) +
->The entire MAVEN toolkit is still under construction.... +![Image text](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/inchat/logo.png) -## Summery +[![QQ群](https://img.shields.io/badge/QQ%E7%BE%A4-628793702-yellow.svg)](https://jq.qq.com/?_wv=1027&k=57X4L74) +[![作者](https://img.shields.io/badge/%E4%BD%9C%E8%80%85-MySelf-blue.svg)](https://github.com/UncleCatMySelf) +[![Netty入门](https://img.shields.io/badge/%E5%AD%A6%E4%B9%A0-Netty%E5%85%A5%E9%97%A8-ff69b4.svg)](doc/study/mulu.md) +[![Maven](https://img.shields.io/badge/Maven-1.1.2-orange.svg)](https://mvnrepository.com/artifact/com.github.UncleCatMySelf/InChat) + + +
+ +## 简介 ***(InChat)Iot Netty Chat*** -> 2018-11-15 began to change to MAVEN project package, currently not released, please see the demo branch for details, thank you. +一个轻量级、高效、分布式的异步通信框架, 支持聊天和物联网, 您可以使用它来快速构建具有后台的聊天服务器, 并快速自定义自己的通信 api, 包括具有不同的通讯可以支持的协议。 + +**欢迎参与QQ群交流与提供建议、业务场景、需求功能等** + +## Maven版本 -A lightweight, efficient communication framework that supports chat and the Internet of things, you can use it to quickly build a chat server with the background and quickly customize your own communication APIs, including physical networks with different protocols that can be supported. +功能列表: -## Branch demo:Stop updates +> * 用户token登录校验 +> * 自我聊天 +> * 点对点聊天 +> * 群聊 +> * 获取在线用户数与用户标签列表 +> * 发送系统通知 -Original Project Core demo, you can first run to understand, imitation WeChat chat application, step by step update, based on Springboot-websocket General framework, combined with Netty to chat social, and record chat logs, asynchronous storage, front-end provisional sui Mobile, add implementation tcp/ -IP back-end communication port (MQTT protocol, real-time and single-chip computer and other TCP hardware communication), add picture processing stream, chat implementation text and picture sending function, API call Netty long link execution Send message (number of online, user list) +* [V1.1.2版本使用说明](https://unclecatmyself.github.io/2019/01/03/inchatby112/) +* [V1.1.2版本视频教学](https://v.qq.com/x/page/y08228i7znk.html) -## Demo Effect Diagram +``` + + com.github.UncleCatMySelf + InChat + 1.1.2 + +``` -![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) +## 项目日志 -## Branch im-api:Stop updates +* [项目研发日志更新](doc/Project-Log-cn.md) -Tencent im (cloud communications) backend imitation project, are docked in the form of APIs, if there is a front-end want to dock can run this branch, this branch is expected to end up for a single service concurrent 300,000 users of IM background project +## 教程 -## Branch paho-mqtt:Stop updates +### [Netty入门与源码讲解](doc/study/mulu.md) +* [项目设计思路](doc/design_cn.md) -Based on the small program end or mobile Web end of the Paho.js and Java MQTT Client simulation of message subscriptions and communications, small program IoT demo, currently supports WS format +> * [登录模块详细设计](doc/detail/Login-cn.md) +> * [登录模块整改版V0.1](doc/detail/login_rect.md) -## Branch tcp-wechat:Stop updates +## 里程碑 -Based on the main communication between the small program end and the single chip computer and other hardware TCP/IP, IoT Center as a relay, this demo will fully implement the specific functions, please see the Branch home page for details +* [InChat项目里程碑](doc/goal/goal.md) -## Download Address +## 相关资料(欢迎贡献) -Download Address:https://github.com/UncleCatMySelf/SBToNettyChat/releases +* [QQ群建议贡献](doc/advice/advice.md) -## Issues & Questions +## 效果展示 + +![demo](https://github.com/UncleCatMySelf/img-myself/blob/master/img/inchatGIF/inchat_demo.gif) +![log](https://github.com/UncleCatMySelf/img-myself/blob/master/img/inchatGIF/inchat_log.gif) +![postman](https://github.com/UncleCatMySelf/img-myself/blob/master/img/inchatGIF/inchat_postman.gif) +![send](https://github.com/UncleCatMySelf/img-myself/blob/master/img/inchatGIF/inchat_send.gif) + +## 下载地址 + +下载地址:https://github.com/UncleCatMySelf/SBToNettyChat/releases + +## 下载 & 问题 https://github.com/UncleCatMySelf/SBToNettyChat/issues -QQ Group:628793702 +## 赞助 + +打赏时请记得备注上你的github账号或者其他链接,谢谢支持! -## About the author +![Image text](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/%E4%BB%98%E6%AC%BE.png) +![Image text](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/%E6%94%AF%E4%BB%98%E5%AE%9D.png) -![Image text](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/%E5%85%AC%E4%BC%97%E5%8F%B7.png) diff --git a/doc/Project-Log-cn.md b/doc/Project-Log-cn.md new file mode 100644 index 0000000..d018b94 --- /dev/null +++ b/doc/Project-Log-cn.md @@ -0,0 +1,31 @@ +# 项目研发日志更新 + +* 【2018-11-21】 目前Maven包开发目标,设计WebSocket登录接口[详情请看设计文档](design_cn.md) +* 【2018-11-22】 编码实现WebSocket聊天通讯的登录流程,[撰写说明文档](detail/Login-cn.md) +* 【2018-11-23】 添加贡献建议信息,重构修改登录检测常量代码,提取成接口形式 +* 【2018-11-26】 登录存储用户token与链接实例,发送给自己功能API,部分功能代码重构 +* 【2018-11-27】 发送消息给在线其他用户,代码部分模块加注释,[撰写设计文档](detail/login_rect.md),但是中途思路有所转变 +* 【2018-11-29】 修复登录下线关闭channel异常BUG,移除原始未重构代码,更新下线模块,与本地在线存储功能。 +* 【2018-11-30】 启动赞助功能,新增【服务端向API发送消息】接口功能,暂未测试 +* 【2018-12-02】 转变部分项目思路,减少用户对框架的依赖与开发成本。 +* 【2018-12-03】 构建【组建群聊】模块功能,整改数据接收Map转为Map,放弃【组建群聊】,仅作基本im业务,完成功能【发送群聊】 +* 【2018-12-04】 明确项目文档的重要性,并设定Netty相关文档说明,与Netty入门说明 +* 【2018-12-05】 移除部分Iot使用的代码(一版暂时还没使用到),清楚pom文件中不用的jar包,需添加【系统时间】参数 +* 【2018-12-06】 确定LOGO并上传,InChat QQ群项目组成立,移除对lombok的依赖,使用传统形式,统一注释说明 +* 【2018-12-14】 打包完成v1.0.0Maven版本,并提交说明文档与相关资料,正对v1.0.0提交对应demo分支。 +* 【2018-12-15】 [录制V1.0.0使用说明视频](https://v.qq.com/x/page/i0813oy0lov.html) +* 【2018-12-18】 明确移除对SpringBoot的依赖于环境,做成自纯应用。[添加NIO服务端与客户端Demo](https://github.com/UncleCatMySelf/InChat/wiki/Java-NIO%E4%B9%8BSelector%EF%BC%88%E9%80%89%E6%8B%A9%E5%99%A8%EF%BC%89) +* 【2018-12-19】 移除lombok,嵌入log4j的依赖,并配置日志信息,移除对SpringBoot的依赖成功,普通main方法既可以运行项目。 +* 【2018-12-21】 添加静态配置,添加服务端发送接口,发布V1.1.0-alpha版本,标识性版本。 +* 【2018-12-27】 添加部分注释,修改版本启动模式,并预定后期添加HTTP接入模式,修改日志配置。 +* 【2018-12-28】 预计整改常量、修改部分方法(类)命名,下一版加wss通道。 +* 【2018-12-30】 修改异步线程任务(FutureTask启动模式),整改目录与修改核心类名,捕获未注册时客户端异常断开的连接异常,新增Http接口功能整改(未完)。 +* 【2018-12-31】 下一版InChat 自带几个默认的Http接口 查询【在线用户数】、【服务端发送消息】、【用户在线用户列表】等,暂不支持自定义URI HTTP接口 +* 【2018-01-01】 添加工具方法 +* 【2018-01-02】 修复httpPOST请求接口 +* 【2018-01-03】 完成新版http接口处理与测试,预计发包,新版发布 InChatV1.1.2,更新README展示GIF,录制V1.1.2视频教程与使用说明书 +* 【2018-01-04】 修复文档,确定版本,新增Redis对接 +* 【2018-01-05】 初步转分布式、处理netty集群(未完成) +* 【2018-01-07】 完成netty集群,多用户跨服务器的消息通讯(HTTP版本) +* 【2018-01-08】 设定下一版本目标 + diff --git a/doc/advice/advice.md b/doc/advice/advice.md new file mode 100644 index 0000000..76b35e9 --- /dev/null +++ b/doc/advice/advice.md @@ -0,0 +1,27 @@ +## QQ群贡献建议 + +> 贡献者:小斑马 + +* 一个netty在物联网的应用,质量很高,有些模块可以直接拿来用 +* https://github.com/cosmoplat-dev + +* 可以考虑把长连接单独做成一个模块,上行下行数据可以直接放到消息队列里面去,上行数据上来后直接放到消息队列里,其他模块接收存数据库,长连接模块监听其他模块放到消息队列里的下发数据 + +> 贡献者:夜殇 + +* 加了规则引擎的物联网项目 +* https://github.com/thingsboard/thingsboard + +* 对上方项目的修改 +* https://github.com/JaryZhen/rulegin + +> 贡献者:[ELLIOT](https://github.com/chanjjaeseo) + +* RabbitMQ 基本操作 +* https://github.com/chanjjaeseo/rabbitMQ-sample + +> 贡献者:[noseparte](https://github.com/noseparte) + +* [netty4通信原理](../netty-study.md) +* MongoDB的基本操作 +* https://github.com/noseparte/mongoTeam diff --git a/doc/design_cn.md b/doc/design_cn.md new file mode 100644 index 0000000..1a9ef66 --- /dev/null +++ b/doc/design_cn.md @@ -0,0 +1,29 @@ +# 项目设计思路 + +## 设计原则 + +AOP、DI为主,基于Spring Boot快速搭建,尽量减少用户的二次搭配开发 + +## 关于登录 + +关于InChat统一登录的接口设计,设计针对小程序、APP、Web端的登录作用,所以将作为token的形式登录InChat的WebSocket长连接,用户服务器做sso的认证登录后得到token后直接发送login信息到InChat,用户服务器需要重写InChat中的verifyToken方法校验自己的的Token信息是否有效,正常则启动长连接。考虑到token失效问题,WebSocket长连接的登录仅做初次登录,接下来考虑以心跳形式保持链接状态(pingpong),使用token认证是为保护InChat链接的常规化(目前暂时这样设计后面根据使用情况更改设计) + +![Image text](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/design/%E6%9C%AA%E5%91%BD%E5%90%8D%E6%96%87%E4%BB%B6(12).png) + +* 【2018-11-22】 编码实现和[详细实现文档](detail/Login-cn.md) + +## 离线消息模板 + +一版采用RabbitMQ----移除 + +## 整体设计 + +![Image text](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/inchat/%E6%9C%AA%E5%91%BD%E5%90%8D%E6%96%87%E4%BB%B6(19).png) + +1、移除原本Token概念,用户均以唯一标识登录并存储在线键值对于系统本地Cache。(登录存储、退出移除) +2、DefaultWebSocketHandler,是框架默认的处理,数据均已json格式,拆分业务点 +3、由InChat内部的服务(WebSocketHandlerService )进行具体的业务实现并回写 +4、对于数据的存储与写入,默认是异步写入数据,用户可以重写InChatToDataBaseService,获取实时数据 +5、在高并发情况下,我们不推荐异步处理数据,可以通过配置化启动mq(目前支持RabbitMq),框架自动注入对应Bean,并由MQ来执行数据写入 +6、关于数据库连接池,我们不会绑定用户使用,而是支持用户自定义。 + diff --git a/doc/detail/Login-cn.md b/doc/detail/Login-cn.md new file mode 100644 index 0000000..2aa63e7 --- /dev/null +++ b/doc/detail/Login-cn.md @@ -0,0 +1,213 @@ +## 只给你最值得的信息 + +小弟正在做的一个开源IM项目,目标是实现一个轻量级、高效率的支持聊天与物联网的通讯框架。昨天刚刚出的设计稿并再今天做了实现。 + +项目是基于Netty的二次开发,关于Netty我这里就不再介绍了,懂的人自然都懂。我的预算是做一个所有企业或组织可以引用的Maven项目,并且是基本上开箱即用,简单实现对应的配置与重写方法就可以搭建自己的IM项目(某Q、某信的效果)。 + +本文着重介绍的是登录接口的设计与实现。 + +## 设计信息 + +关于InChat统一登录的接口设计,设计针对小程序、APP、Web端的登录作用,所以将作为token的形式登录InChat的WebSocket长连接,用户服务器做sso的认证登录后得到token后直接发送login信息到InChat,用户服务器需要重写InChat中的verifyToken方法校验自己的的Token信息是否有效,正常则启动长连接。考虑到token失效问题,WebSocket长连接的登录仅做初次登录,接下来考虑以心跳形式保持链接状态(pingpong),使用token认证是为保护InChat链接的常规化(目前暂时这样设计后面根据使用情况更改设计) + +![Image text](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/inchat/%E6%9C%AA%E5%91%BD%E5%90%8D%E6%96%87%E4%BB%B6(13).png) + +由于目前大部分的Web项目或基于IM的项目登录可能存在多端的单点登录,所以我选用了Token的形式,为什么登录后还需要用token再来websocket这边校验一次呢? + +因为你登录的是web应用程序端的,而websocket而言,只要别人知道你的地址,那么就可以链接上,我们不希望存在过多的死链接(无效链接),所以我们需要将token再次发给InChat登录,由InChat来检验是否是合法登录链接,如果无效则关闭链接。 + +## 代码实现 + +由于是想要做给别人用的,那么我们自己本身就要封装的好一点,对于配置我选了足够多的类型。 + +![Image text](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/inchat/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20181122171455.png) + +对于netty监听与初始化,我使用的方式是扫描与AspectJ,你可以在项目的auto包中看到扫描启动,这种启动思路我也是参考了其他的开源项目(具体忘记了地址)。 + +```java +@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.getWebport(),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); + } + return new InitServer(serverBean); +} +``` + + +在上图中存在一个DefaultWebSocketHandler,这个是默认的netty启动处理。 + +当然在执行它之前,还需要执行到一个抽象的类WebSocketHandler。 + +它将会为我做一些基本的功能操作。 + +```java +@Slf4j +public abstract class WebSocketHandler extends SimpleChannelInboundHandler { + + WebSocketHandlerApi webSocketHandlerApi; + + public WebSocketHandler(WebSocketHandlerApi webSocketHandlerApi){ + this.webSocketHandlerApi = webSocketHandlerApi; + } + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { + if (msg instanceof TextWebSocketFrame){ + textdoMessage(ctx,(TextWebSocketFrame)msg); + }else if (msg instanceof WebSocketFrame){ + webdoMessage(ctx,(WebSocketFrame)msg); + } + } + + protected abstract void webdoMessage(ChannelHandlerContext ctx, WebSocketFrame msg); + + protected abstract void textdoMessage(ChannelHandlerContext ctx, TextWebSocketFrame msg); + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + log.info("【DefaultWebSocketHandler:channelInactive】"+ctx.channel().localAddress().toString()+"关闭成功"); + webSocketHandlerApi.close(ctx.channel()); + } + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + if(evt instanceof IdleStateEvent){ + webSocketHandlerApi.doTimeOut(ctx.channel(),(IdleStateEvent)evt); + } + super.userEventTriggered(ctx, evt); + } +} +``` + +对于登录接口,他是基于WebSocket的,且是TextWebSocketFrame类型的,WebSocketFrame是后期的图片聊天功能,所以我们的DefaultWebSocketHandler暂时只需要实现textdoMessage。 + +对于websocket的传输我们推荐使用json形式,这对于前后端都是由好处的。 + +```java + @Override + protected void textdoMessage(ChannelHandlerContext ctx, TextWebSocketFrame msg) { + Channel channel = ctx.channel(); + ServerWebSocketHandlerService serverWebSocketHandlerService; + if (webSocketHandlerApi instanceof ServerWebSocketHandlerService){ + serverWebSocketHandlerService = (ServerWebSocketHandlerService)webSocketHandlerApi; + }else{ + throw new NoFindHandlerException("Server Handler 不匹配"); + } + Map maps = (Map) JSON.parse(msg.text()); + switch (maps.get("type")){ + case "login": + serverWebSocketHandlerService.login(channel,msg); + break; + default: + break; + } + } +``` + +由上面的代码,你也许才想到了前端登录的大致json内容,没错是这样的。 + +``` +{ + type: "login", + token: value +} +``` + +ServerWebSocketHandlerService是一个自己定义的后端WebSocket存在的接口实现服务,我们现在使用到他的登录接口,让我们来看看他的登录实现方法。 + +```java + + @Autowired + InChatVerifyService inChatVerifyService; + + @Override + public boolean login(Channel channel, TextWebSocketFrame textWebSocketFrame) { + //校验规则,自定义校验规则 + Map maps = (Map) JSON.parse(textWebSocketFrame.text()); + System.out.println("login-"+textWebSocketFrame.text()); + String token = maps.get("token"); + Gson gson = new Gson(); + Map backMap = new HashMap<>(); + if (inChatVerifyService.verifyToken(token)){ + backMap.put("type","login"); + backMap.put("success","true"); + channel.writeAndFlush(new TextWebSocketFrame(gson.toJson(backMap))); + return true; + } + backMap.put("type","login"); + backMap.put("success","false"); + channel.writeAndFlush(new TextWebSocketFrame(gson.toJson(backMap))); + close(channel); + return false; + } +``` + +由以上可看出,我们会将token和inChatVerifyService.verifyToken做校验,这是一个接口,我并没有写实现,因为这个是用户的事情了,它需要实现并重写我的verifyToken方法,并返回给我一个值,如下是我测试的时候写的模拟实现。 + +```java +/** + * 不属于项目代码 + * Created by MySelf on 2018/11/22. + */ +@Service +public class InChatVerifyServiceImpl implements InChatVerifyService { + + @Override + public boolean verifyToken(String token) { + //与Redis中的Token做比较,请用户自己实现,查找是否存在该Token值 + System.out.println("verify---"+token); + if ("3333".equals(token)){ + return true; + } + return false; + } +} +``` + +我仅仅做了普通的校验,对于用户可以注入RedisTemplate然后进行校验等工作。到此我们的登录接口就实现好了! + +## 看看效果 + +![Image text](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/inchat/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20181122171241.png) + +![Image text](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/inchat/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20181122171245.png) + +![Image text](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/inchat/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20181122171247.png) + + +> 2017-11-25 end. \ No newline at end of file diff --git a/doc/detail/login_rect.md b/doc/detail/login_rect.md new file mode 100644 index 0000000..2106932 --- /dev/null +++ b/doc/detail/login_rect.md @@ -0,0 +1,34 @@ +## 前言 + +本文旨在更新上一节设计中的不合理进行整改,关于登录的不足还有扩展功能的添加。 + +前文:[登录模块详细设计](Login-cn.md) + +对于前文中的登录原核心思路是正确的,不过对于后期的部分业务功能的扩展是比较麻烦的,比如发送给其他人,发送离线消息,判断系统用户是否离线等。 +的确,上文只是设计登录而言,但是我们还要考虑到后续功能接口的封装还有业务流程,所以一开始多磨是有好处的。 + +## 设计整改 + +这次的架构流程我们大致是这样的。 + +![Image text](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/inchat/login.png) + +我们可能需要中心整理一下: + +* 客户端是小程序、APP、Web端等的统称 +* 客户端向服务器登录请求获取服务器分配的token +* 同时服务器将用户信息与token存入redis +* 客户端登录的同时还要登录InChat,发送json格式向websocket模拟登录 + +``` +{ + type:login + token:**** +} +``` + +* InChat接收根据Type进行登录流程的执行,用户重写verifyToken方法去用户自定义的Redis中判断,返回真假 +* 校验登录成功,InChat本地存储链接与用户信息,这里的用户信息应该是User唯一标识,而不能是Token + +> 在我写到这里的时候,脑子中突然觉得说不定可以使用token,甚至想到更多,导致我没有继续写完本章 +> 2018-11-27 end. \ No newline at end of file diff --git a/doc/goal/goal.md b/doc/goal/goal.md new file mode 100644 index 0000000..16a224b --- /dev/null +++ b/doc/goal/goal.md @@ -0,0 +1,68 @@ +# InChat项目里程碑 + +> 项目研发的开放目标,以Maven包为基本的发布(兼对应版本的文档输出)设定为每个里程碑的产出。 + +### 项目于2018年8月14号开始成立,前一个月以Demo为发展路线,后期转为框架研发。 + +## V1.0.0版本 【2018-12-14】 + +> 版本昵称:赤猫 + +版本目标:完成基本的消息通讯(仅支持文本消息),离线消息存储,历史消息查询,一对一聊天、自我聊天、群聊等 + +* [V1.0.0版本使用说明](doc/version/v1.0.0.md) +* [V1.0.0版本使用说明视频教程](https://v.qq.com/x/page/i0813oy0lov.html) + +> 目前项目代码已经推进入了下一版本,如果你想下载这个版本的源码,可以到这里下载[V1.0.0-alpha](https://github.com/UncleCatMySelf/InChat/releases/tag/V1.0.0-alpha) + +``` + + + com.github.UncleCatMySelf + InChat + 1.0-alpha + +``` + +## V1.1.0-alpha版本 【2018-12-21】 + +> 版本昵称:赤猫-1 + +版本目标:移除对SpringBoot的环境依赖,InChat独立生存与使用,结合上一版的功能,并添加服务器发送消息接口 + +* [V1.1.0-alpha版本使用说明](https://unclecatmyself.github.io/2018/12/21/InChatV1.1.0%E7%89%88%E6%9C%AC%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E/) +* [V1.1.0-alpha版本视频教学](https://v.qq.com/x/page/i08165ym286.html) + +``` + + com.github.UncleCatMySelf + InChat + 1.1.0-alpha + +``` + +## 【2018-12-20】 项目突破 **150** Star,感谢大家的支持 + +## V1.1.2版本 【2019-01-04】 + +> 版本昵称:赤猫-2 + +版本更新:添加HTTP接口调用,捕获已知异常 + +* [V1.1.2版本使用说明](https://unclecatmyself.github.io/2019/01/03/inchatby112/) +* [V1.1.2版本视频教学](https://v.qq.com/x/page/y08228i7znk.html) + +``` + + com.github.UncleCatMySelf + InChat + 1.1.2 + +``` + + +## V1.1.3版本 【待定】 + +> 版本昵称:橙猫 + +版本目标:InChat集群与wss diff --git a/doc/netty-study.md b/doc/netty-study.md new file mode 100644 index 0000000..e9a55cb --- /dev/null +++ b/doc/netty-study.md @@ -0,0 +1,40 @@ +## netty4通信步骤,原理 + +> 感谢 贡献者:[Noseparte](https://github.com/noseparte) + +### 服务端依次发生的步骤 + +* 1.建立服务端监听套接字ServerSocketChannel,以及对应的管道pipeline; +* 2.启动boss线程,将ServerSocketChannel注册到boss线程持有的selector中,并将注册返回的selectionKey赋值给ServerSocketChannel关联的selectionKey变量; +* 3.在ServerSocketChannel对应的管道中触发channelRegistered事件; +* 4.绑定IP和端口 +* 5.触发channelActive事件,并将ServerSocketChannel关联的selectionKey的OP_ACCEPT位置为1。 +* 6.客户端发起connect请求后,boss线程正在运行的select循环检测到了该ServerSocketChannel的ACCEPT事件就绪,则通过accept系统调用建立一个已连接套接字SocketChannel,并为其创建对应的管道; +* 7.在服务端监听套接字对应的管道中触发channelRead事件; +* 8.channelRead事件由ServerBootstrapAcceptor的channelRead方法响应:为已连接套接字对应的管道加入ChannelInitializer处理器; +启动一个worker线程,并将已连接套接字的注册任务加入到worker线程的任务队列中; +* 9.worker线程执行已连接套接字的注册任务:将已连接套接字注册到worker线程持有的selector中,并将注册返回的selectionKey赋值给已连接套接字关联的selectionKey变量; +在已连接套接字对应的管道中触发channelRegistered事件;channelRegistered事件由ChannelInitializer的channelRegistered方法响应: +将自定义的处理器(譬如EchoServerHandler)加入到已连接套接字对应的管道中;在已连接套接字对应的管道中触发channelActive事件;c +hannelActive事件由已连接套接字对应的管道中的inbound处理器的channelActive方法响应;将已连接套接字关联的selectionKey的OP_READ位置为1;至此,worker线程关联的selector就开始监听已连接套接字的READ事件了。 +* 10.在worker线程运行的同时,Boss线程接着在服务端监听套接字对应的管道中触发channelReadComplete事件。 +* 11.客户端向服务端发送消息后,worker线程正在运行的selector循环会检测到已连接套接字的READ事件就绪。则通过read系统调用将消息从套接字的接受缓冲区中读到AdaptiveRecvByteBufAllocator(可以自适应调整分配的缓存的大小)分配的缓存中; +* 12.在已连接套接字对应的管道中触发channelRead事件; +* 13.channelRead事件由EchoServerHandler处理器的channelRead方法响应:执行write操作将消息存储到ChannelOutboundBuffer中; +* 14.在已连接套接字对应的管道中触发ChannelReadComplete事件; +* 15.ChannelReadComplete事件由EchoServerHandler处理器的channelReadComplete方法响应:执行flush操作将消息从ChannelOutboundBuffer中flush到套接字的发送缓冲区中; + + + +### 客户端依次发生的步骤 + +* 1.建立套接字SocketChannel,以及对应的管道pipeline; +* 2.启动客户端线程,将SocketChannel注册到客户端线程持有的selector中,并将注册返回的selectionKey赋值给SocketChannel关联的selectionKey变量; +* 3.触发channelRegistered事件; +* 4.channelRegistered事件由ChannelInitializer的channelRegistered方法响应:将客户端自定义的处理器(譬如EchoClientHandler)按顺序加入到管道中; +* 5.向服务端发起connect请求,并将SocketChannel关联的selectionKey的OP_CONNECT位置为1; +* 6.开始三次握手,客户端线程正在运行的select循环检测到了该SocketChannel的CONNECT事件就绪,则将关联的selectionKey的OP_CONNECT位置为0,再通过调用finishConnect完成连接的建立; +* 7.触发channelActive事件; +* 8.channelActive事件由EchoClientHandler的channelActive方法响应,通过调用ctx.writeAndFlush方法将消息发往服务端; +* 9.首先将消息存储到ChannelOutboundBuffer中;(如果ChannelOutboundBuffer存储的所有未flush的消息的大小超过高水位线writeBufferHighWaterMark(默认值为64 * 1024),则会触发ChannelWritabilityChanged事件) +* 10.然后将消息从ChannelOutboundBuffer中flush到套接字的发送缓冲区中;(如果ChannelOutboundBuffer存储的所有未flush的消息的大小小于低水位线,则会触发ChannelWritabilityChanged事件) \ No newline at end of file diff --git a/doc/study/1-st.md b/doc/study/1-st.md new file mode 100644 index 0000000..d93848c --- /dev/null +++ b/doc/study/1-st.md @@ -0,0 +1,34 @@ +# 第一章 Netty的大致介绍 + +netty被广泛应用于世面上的许多框架,如Dubbo、RocketMQ、Spark、ElasticSearch、Cassandra、Flink、Netty-SocketIO、Spring5、Play、Grpc..... + +以上均是将Netty作为底层网络通讯。 + +## Netty是什么? + +* 异步事件驱动框架,用于快速开发高性能服务端和客户端 +* 封装了JDK底层BIO和NIO模型,提供高度可用的API +* 自带编解码器解决拆包粘包问题,用户只用关心业务逻辑 +* 精心设计的reactor线程模型支持高并发海量连接 +* 自带各种协议栈让你处理任何一种通用协议都几乎不用亲自动手 + +## 学习Netty有必要吗? + +* 各大开源项目选择Netty作为底层通信框架 +* 更好的使用,少走弯路 +* 遇到BUG?单机连接数上不去?性能遇到瓶颈?如何调优? +* 详解reactor线程模型,实践中举一反三 +* 庞大的项目是如何组织的,设计模式,体验优秀的设计 +* 阅读源码其实没有那么困难 + +## 怎么学习Netty? + +* 自己摸索不如前人指路 +* 对应socket编程,逐个切入 +* 填坑路程 + +## 适合人群 + +* 系统掌握Netty底层核心原理 +* 加速掌握基于Netty的各类中间件框架 +* 对技术有追求。对优秀代码由执念的开发者 diff --git a/doc/study/2-st.md b/doc/study/2-st.md new file mode 100644 index 0000000..4ff3c2b --- /dev/null +++ b/doc/study/2-st.md @@ -0,0 +1,195 @@ +# 第二章 Netty基本组件 + +## 一个简单的socket例子 + +![Image text](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/stduy/100.png) + +### ServerBoot启动类 + +```java +package com.example.demo; + +/** + * @Author:UncleCatMySelf + * @Email:zhupeijie_java@126.com + * @QQ:1341933031 + * @Date:Created in 23:00 2018\12\4 0004 + */ +public class ServerBoot { + + private static final int PORT = 8000; + + public static void main(String[] args){ + Server server = new Server(PORT); + server.start(); + } + +} +``` + +### Server监听端口服务类 + +```java +package com.example.demo; + +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; + +/** + * @Author:UncleCatMySelf + * @Email:zhupeijie_java@126.com + * @QQ:1341933031 + * @Date:Created in 22:46 2018\12\4 0004 + */ +@Slf4j +public class Server { + + private ServerSocket serverSocket; + + public Server(int port){ + try { + this.serverSocket = new ServerSocket(port); + log.info("服务端启动成功,端口:" + port); + }catch (IOException e){ + log.error("服务端启动失败"); + } + } + + public void start(){ + new Thread(new Runnable() { + @Override + public void run() { + doStart(); + } + }).start(); + } + + private void doStart(){ + while (true){ + try { + //阻塞方法 + Socket client = serverSocket.accept(); + new ClientHandler(client).start(); + }catch (IOException e){ + log.error("服务端异常"); + } + } + } +} +``` + +### ClientHandler客户端接入监听类 + +```java +package com.example.demo; + +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.io.InputStream; +import java.net.Socket; + +/** + * @Author:UncleCatMySelf + * @Email:zhupeijie_java@126.com + * @QQ:1341933031 + * @Date:Created in 22:50 2018\12\4 0004 + */ +@Slf4j +public class ClientHandler { + + public static final int MAX_DATA_LEN = 1024; + private final Socket socket; + + public ClientHandler(Socket socket){ + this.socket = socket; + } + + public void start(){ + log.info("新客户端接入"); + new Thread(new Runnable() { + @Override + public void run() { + doStart(); + } + }).start(); + } + + private void doStart(){ + try { + InputStream inputStream = socket.getInputStream(); + while (true){ + byte[] data = new byte[MAX_DATA_LEN]; + int len; + while((len = inputStream.read(data)) != -1){ + String message = new String(data,0,len); + log.info("客户端传来消息:" + message); + socket.getOutputStream().write(data); + } + } + }catch (IOException e){ + e.printStackTrace(); + } + } + +} +``` + + +### Client客户端启动类 + +```java +package com.example.demo; + +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.net.Socket; + +/** + * @Author:UncleCatMySelf + * @Email:zhupeijie_java@126.com + * @QQ:1341933031 + * @Date:Created in 23:01 2018\12\4 0004 + */ +@Slf4j +public class Client { + + private static final String HOST = "127.0.0.1"; + private static final int PORT = 8000; + private static final int SLEEP_TIME = 5000; + + public static void main(String[] args) throws IOException{ + final Socket socket = new Socket(HOST,PORT); + + new Thread(new Runnable() { + @Override + public void run() { + log.info("客户端启动成功!"); + while (true){ + try { + String message = "hello myself"; + log.info("客户端发送数据:" + message); + socket.getOutputStream().write(message.getBytes()); + }catch (Exception e){ + log.info("写数据出错!"); + } + sleep(); + } + } + }).start(); + } + + private static void sleep(){ + try { + Thread.sleep(SLEEP_TIME); + }catch (InterruptedException e){ + e.printStackTrace(); + } + } + +} +``` \ No newline at end of file diff --git a/doc/study/mulu.md b/doc/study/mulu.md new file mode 100644 index 0000000..ddd649c --- /dev/null +++ b/doc/study/mulu.md @@ -0,0 +1,4 @@ +# Netty 入门与源码讲解 + +* [Netty介绍与详情](1-st.md) +* [Netty基本组件](2-st.md) \ No newline at end of file diff --git a/doc/version/v1.0.0.md b/doc/version/v1.0.0.md new file mode 100644 index 0000000..f5fce28 --- /dev/null +++ b/doc/version/v1.0.0.md @@ -0,0 +1,295 @@ +## v1.0.0版本使用说明 + +### 关于InChat的Maven依赖 + +* fastjson 》 1.2.53 +* gson 》 2.8.5 +* netty 》 4.1.32.Final +* commons-lang 》 3.5 +* aspectj 》 1.9.2 +* lombok 》 1.18.4 +* spring-boot 》 2.0.2.RELEASE +* spring-boot-starter-websocket + +关于一版依旧使用SpringBoot的环境,同时为应用注入了web环境,引入InChat依赖包后,对于SpringBoot相关的web可以无需引入,同时请注意相关版本的兼容性。 +引入InChat默认可以自动运行web环境。 + +### 创建项目 + +创建一个空的Maven项目,并引入**InChat**Maven包,(注意,请不要使用与本项目相同的包目录)。 + +可能你只需要这样的Maven依赖即可 + +``` + + + com.github.UncleCatMySelf + InChat + 1.0-alpha + + + org.springframework.boot + spring-boot-starter-test + test + + +``` + +### 注入InChat的项目到自身项目中 + +你可能需要在你的项目上进行报扫描 + +```java +@SpringBootApplication +@ComponentScan({"com.inchat"}) //你的demo包目录 +@ComponentScan({"com.github.unclecatmyself"}) //InChat的包目录 --请将InChat的放到最下面 +public class DemoApplication { + + public static void main(String[] args) { + SpringApplication.run(DemoApplication.class, args); + } + +} +``` + +### 对接InChat的接口与实现 + +这次你仅需写两个实现接口即可啦!!! + +```java +@Service +public class ToDataBaseServiceImpl implements InChatToDataBaseService{ + + @Override + public Boolean writeMapToDB(Map maps) { + //异步写入数据库 + System.out.println(maps.toString()); + return true; + } +} +``` + +* 这个接口是每个人通讯的信息,InChat自带实现了异步的数据外抛得接口**InChatToDataBaseService**,目前一版只有一个方法, +就是上面得writeMapToDB,你仅需要map的内容转为对应的对象(一版还没提供对应的转换类,下一版对提供),并将数据存入自己喜欢的数据库中。 +如果数据并发大,也可以先放到MQ中,再写入数据库。 + +```java +@Service +public class verifyServiceImpl implements InChatVerifyService { + + + @Override + public boolean verifyToken(String token) { + //登录校验 + return true; + } + + @Override + public JSONArray getArrayByGroupId(String groupId) { + //根据群聊id获取对应的群聊人员ID + JSONArray jsonArray = JSONArray.parseArray("[\"1111\",\"2222\",\"3333\"]"); + return jsonArray; + } +} +``` + +* 这个接口是InChat的校验层实现,对于Token的校验就是,**verifyToken**,websocket链接的时候,你将在初次做登录校验,你可以将从InChat拿到的websocket传过来的 +Token,你可以与自己的用户登录的token做校验,返回true,则用户成功链接InChat。 + +* 关于**getArrayByGroupId**,目前是否应该放在这个接口中还有待确定,不过目前一版暂时这样,你可以去数据库中查询对应的群聊id所对应的人员ID(或Token),并返回对应的 +JSONArray即可啦。 + +### 自定义配置InChat参数 + +这个你可以直接在application中按照自己的意思配置,不过你最好先了解netty + +![Image](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/inchat/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20181214104225.png) + +### 启动项目 + +接着启动项目即可啦 + +当你看到这个日志就标志着Inchat搭建成功了!!! + +``` +2018-12-14 10:29:09.269 INFO 4920 --- [ BOSS_1] c.g.u.bootstrap.NettyBootstrapServer : 服务端启动成功【192.168.1.121:8090】 +``` + +### 关于前端 + +这里你可以来到[InChat](https://github.com/UncleCatMySelf/InChat)的Front-End-Testing文档夹中的chat.html。 + +你可以直接使用,你进需要修改对应的对接IP即可。 + +> 关于前端的js暂时还是模板 + +### 关于登录 + +你会看到chat.html中的登录按钮对应的js + +```js +function send(value) { + if (!window.WebSocket) { + return; + } + if (socket.readyState == WebSocket.OPEN) { + var message = { + type: "login", //与InChat对应的 不可修改 + token: "1111" + } + socket.send(JSON.stringify(message)); + } else { + alert("连接没有开启."); + } +} +``` + +本demo,默认登录的Token是“1111”,关于用户校验则直接返回true即可。 + +登录成功,返回以下内容。(不需要显示给用户看) + +``` +{"success":"true","type":"login"} +``` + +InChat不会有登录记录 + +### 发送给自己 + +你会看到chat.html中的登录按钮对应的js + +```js +function sendToMe(value) { + if (!window.WebSocket) { + return; + } + if (socket.readyState == WebSocket.OPEN) { + var message = { + type: "sendMe", //与InChat对应的 不可修改 + value: value, //发送的内容 + token: "1111" //发送用户的token + } + socket.send(JSON.stringify(message)); + } else { + alert("连接没有开启."); + } +} +``` + +发送成功,InChat返回内容.(你仅需将value显示到前端即可) + +``` +{"type":"sendMe","value":"发送给自己的内容"} +``` + +InChat消息记录,你将在异步消息中接受到InChat传递给你的用户通讯消息,你可以进行对应的入库操作 + +``` +{"time":"2018-12-14 10:56:24","type":"sendMe","value":"发送给自己的内容","token":"1111"} +``` + +### 发送给某人 + +你会看到chat.html中的登录按钮对应的js + +```js +function sendToOne(value) { + if (!window.WebSocket) { + return; + } + if (socket.readyState == WebSocket.OPEN) { + var message = { + type : "sendTo", //与InChat对应的 不可修改 + token : "1111", //发送用户Token + value: value, //发送内容 + one: "2222", //接受用户Token(唯一标识) + } + socket.send(JSON.stringify(message)); + } else { + alert("连接没有开启."); + } +} +``` + +发送成功,接受的用户是否登录,你都能接受到返回信息。(value应用于自己界面展示) + +``` +{"one":"2222","type":"sendTo","value":"发送给朋友的内容"} +``` + +但是用户那边就不一样了。 + +登录正常在线。 + +``` +{"from":"1111","type":"sendTo","value":"发送给朋友的内容"} +``` + +离线接受不到信息 + +InChat异步消息推送,你可以看到两种 + +``` +在线: {"one":"2222","time":"2018-12-14 11:01:36","type":"sendTo","value":"发送给朋友的内容","token":"1111"} +``` + +``` +离线: {"one":"2222","time":"2018-12-14 10:59:04","on_online":"2222","type":"sendTo","value":"发送给朋友的内容","token":"1111"} +``` + +如果出现用户发送给用户的状态是离线的,则会在消息多出on_online的字段,该字段的内容就是离线用户的Token,你可以针对性的数据入库,并在用户上线的时候,读写信息的时候,有一个未读消息的状态。 + +### 发送群聊 + +你会看到chat.html中的登录按钮对应的js + +```js +function sendGroup(value) { + if (!window.WebSocket) { + return; + } + if (socket.readyState == WebSocket.OPEN) { + var message = { + type: "sendGroup", //与InChat对应的 不可修改 + groupId: "2", //群聊ID + token: "1111", //发送用户的Token + value: value //发送的消息 + } + socket.send(JSON.stringify(message)); + } else { + alert("连接没有开启."); + } +} +``` + +发送成功,本人将接受到消息 + +``` +{"groupId":"2","from":"1111","type":"sendGroup","value":"大家明天一起去唱K吧"} +``` + +群组中有些人在线接受、离线不接受 + +``` +在线:{"groupId":"2","from":"1111","type":"sendGroup","value":"大家明天一起去唱K吧"} +``` + +InChat异步消息入库,群组只会异步给你一个消息,你可以看到on_online中,3333用户是没有接受到信息的,所以你可以在他上线发送未读消息。 + +``` +{"groupId":"2","time":"2018-12-14 11:09:17","on_online":["3333"],"type":"sendGroup","value":"大家明天一起去唱K吧","token":"1111"} +``` + +### 关于数据库设计 + +> 当前一版不会固定大家的数据库设计,大家可以自己自由设计,同时搭上自己的项目,构建一个附带IM的自项目。 + +### 前端效果 + +发送人 + +![Image](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/inchat/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20181214111435.png) + +接收人 + +![Image](https://raw.githubusercontent.com/UncleCatMySelf/img-myself/master/img/inchat/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20181214111438.png) \ No newline at end of file diff --git a/pom.xml b/pom.xml index 458d0cf..cfbbcb9 100644 --- a/pom.xml +++ b/pom.xml @@ -3,20 +3,46 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.myself - nettychat - 0.0.1-SNAPSHOT + com.github.UncleCatMySelf + InChat + 1.1.2 + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + jar - nettychat - Demo project for Spring Boot + InChat + A lightweight, efficient communication framework that supports chat and the Internet of Things + https://github.com/UncleCatMySelf + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + - - org.springframework.boot - spring-boot-starter-parent - 2.0.2.RELEASE - - + + + MySelf + zhupeijie_java@126.com + + + + + scm:git:git@github.com:UncleCatMySelf/InChat.git + scm:git:git@github.com:UncleCatMySelf/InChat.git + git@github.com:UncleCatMySelf/InChat.git + UTF-8 @@ -25,97 +51,106 @@ + - org.springframework.boot - spring-boot-starter-tomcat - - - org.springframework.boot - spring-boot-starter-data-jpa + redis.clients + jedis + 3.0.1 - mysql - mysql-connector-java + org.slf4j + slf4j-log4j12 + 1.7.25 - org.springframework.boot - spring-boot-starter-websocket + com.alibaba + fastjson + 1.2.53 - org.projectlombok - lombok + com.google.code.gson + gson + 2.8.5 io.netty netty-all - 4.1.28.Final - - - com.google.guava - guava - 26.0-jre + 4.1.32.Final org.apache.commons commons-lang3 3.5 - - org.springframework.boot - spring-boot-configuration-processor - true - - - org.apache.curator - curator-recipes - 2.9.1 - - - org.apache.curator - curator-client - 2.9.1 - - - org.apache.curator - curator-framework - 2.9.1 - - - - - - - - - org.springframework.boot - spring-boot-starter-freemarker - - - io.springfox - springfox-swagger2 - 2.8.0 - - - io.springfox - springfox-swagger-ui - 2.8.0 - - - org.springframework.boot - spring-boot-starter-test - test - - - nettychat - - - org.springframework.boot - spring-boot-maven-plugin - - - - + + + release + + + + + org.apache.maven.plugins + maven-source-plugin + 3.0.1 + + + package + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.0.1 + + private + true + UTF-8 + UTF-8 + UTF-8 + + + + package + + jar + + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + verify + + sign + + + + + + + + + oss + https://oss.sonatype.org/content/repositories/snapshots/ + + + oss + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + 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/github/unclecatmyself/application.java b/src/main/java/com/github/unclecatmyself/application.java new file mode 100644 index 0000000..0cae824 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/application.java @@ -0,0 +1,27 @@ +package com.github.unclecatmyself; + +import com.github.unclecatmyself.auto.ConfigFactory; +import com.github.unclecatmyself.auto.InitServer; +import com.github.unclecatmyself.common.bean.InitNetty; +import com.github.unclecatmyself.user.DataBaseServiceImpl; +import com.github.unclecatmyself.user.FromServerServiceImpl; +import com.github.unclecatmyself.user.MyInit; +import com.github.unclecatmyself.user.VerifyServiceImpl; + +/** + * Create by UncleCatMySelf in 22:49 2019\1\4 0004 + */ +public class application { + + public static void main(String[] args) { + ConfigFactory.initNetty = new MyInit(); + ConfigFactory.inChatVerifyService = new VerifyServiceImpl(); + ConfigFactory.inChatToDataBaseService = new DataBaseServiceImpl(); + ConfigFactory.fromServerService = FromServerServiceImpl.TYPE2; +// ConfigFactory.RedisIP = "192.168.12.129"; + ConfigFactory.RedisIP = "192.168.192.132"; + + InitServer.open(); + } + +} diff --git a/src/main/java/com/github/unclecatmyself/auto/AutoConfig.java b/src/main/java/com/github/unclecatmyself/auto/AutoConfig.java new file mode 100644 index 0000000..e0ce10a --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/auto/AutoConfig.java @@ -0,0 +1,10 @@ +package com.github.unclecatmyself.auto; + +/** + * Create by UncleCatMySelf in 14:33 2019\1\5 0005 + */ +public class AutoConfig { + + public static String address = ""; + +} diff --git a/src/main/java/com/github/unclecatmyself/auto/ConfigFactory.java b/src/main/java/com/github/unclecatmyself/auto/ConfigFactory.java new file mode 100644 index 0000000..db5160c --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/auto/ConfigFactory.java @@ -0,0 +1,27 @@ +package com.github.unclecatmyself.auto; + +import com.github.unclecatmyself.bootstrap.channel.http.FromServerService; +import com.github.unclecatmyself.bootstrap.data.InChatToDataBaseService; +import com.github.unclecatmyself.bootstrap.verify.InChatVerifyService; +import com.github.unclecatmyself.common.bean.InitNetty; + +/** + * 默认配置工厂 + * Created by MySelf on 2018/12/21. + */ +public class ConfigFactory { + + public static String RedisIP; + + /** 用户校验伪接口 */ + public static InChatVerifyService inChatVerifyService; + + /** 用户获取数据伪接口 */ + public static InChatToDataBaseService inChatToDataBaseService; + + public static FromServerService fromServerService; + + /** InChat项目配置 */ + public static InitNetty initNetty; + +} diff --git a/src/main/java/com/github/unclecatmyself/auto/InitServer.java b/src/main/java/com/github/unclecatmyself/auto/InitServer.java new file mode 100644 index 0000000..afc179a --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/auto/InitServer.java @@ -0,0 +1,38 @@ +package com.github.unclecatmyself.auto; + + +import com.github.unclecatmyself.bootstrap.BootstrapServer; +import com.github.unclecatmyself.bootstrap.NettyBootstrapServer; +import com.github.unclecatmyself.common.bean.InitNetty; + +/** + * InChat项目启动服务 + * Create by UncleCatMySelf in 2018/12/06 + **/ +public abstract class InitServer { + +// private InitNetty serverBean; + + private static InitNetty serverBean = ConfigFactory.initNetty; + +// public InitServer(InitNetty serverBean) { +// this.serverBean = serverBean; +// } + + static BootstrapServer bootstrapServer; + + public static 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/github/unclecatmyself/auto/RedisConfig.java b/src/main/java/com/github/unclecatmyself/auto/RedisConfig.java new file mode 100644 index 0000000..b0e5940 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/auto/RedisConfig.java @@ -0,0 +1,31 @@ +package com.github.unclecatmyself.auto; + +import com.github.unclecatmyself.common.constant.LogConstant; +import com.sun.org.apache.regexp.internal.RE; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import redis.clients.jedis.Jedis; + +/** + * Create by UncleCatMySelf in 13:56 2019\1\5 0005 + */ +public class RedisConfig { + + private static final Logger log = LoggerFactory.getLogger(RedisConfig.class); + + private static RedisConfig instance = new RedisConfig(); + + public static Jedis jedis; + + private RedisConfig(){ + if (ConfigFactory.initNetty.getDistributed()){ + this.jedis = new Jedis(ConfigFactory.RedisIP); + log.info(LogConstant.REDIS_START + jedis.ping()); + } + } + + public static RedisConfig getInstance(){ + return instance; + } + +} diff --git a/src/main/java/com/github/unclecatmyself/auto/ServerAutoConfigure.java b/src/main/java/com/github/unclecatmyself/auto/ServerAutoConfigure.java new file mode 100644 index 0000000..e47d692 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/auto/ServerAutoConfigure.java @@ -0,0 +1,55 @@ +package com.github.unclecatmyself.auto; + +import com.github.unclecatmyself.common.bean.InitNetty; +import org.apache.commons.lang3.ObjectUtils; + + +/** + * Create by UncleCatMySelf in 2018/12/06 + **/ +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(){ + + } + +// public InitServer initServer(InitNetty serverBean){ +// if(!ObjectUtils.allNotNull(serverBean.getWebport(),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); +// } +// return new InitServer(serverBean); +// } + +} diff --git a/src/main/java/com/github/unclecatmyself/bootstrap/AbstractBootstrapServer.java b/src/main/java/com/github/unclecatmyself/bootstrap/AbstractBootstrapServer.java new file mode 100644 index 0000000..c1d34aa --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/bootstrap/AbstractBootstrapServer.java @@ -0,0 +1,43 @@ +package com.github.unclecatmyself.bootstrap; + + +import com.github.unclecatmyself.auto.ConfigFactory; +import com.github.unclecatmyself.bootstrap.channel.HandlerServiceImpl; +import com.github.unclecatmyself.bootstrap.handler.DefaultHandler; +import com.github.unclecatmyself.common.bean.InitNetty; +import com.github.unclecatmyself.common.constant.BootstrapConstant; +import com.github.unclecatmyself.task.DataAsynchronousTask; +import io.netty.channel.ChannelPipeline; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpRequestDecoder; +import io.netty.handler.codec.http.HttpResponseEncoder; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; +import io.netty.handler.timeout.IdleStateHandler; + +/** + * Create by UncleCatMySelf in 2018/12/06 + **/ +public abstract class AbstractBootstrapServer implements BootstrapServer { + + /** + * @param channelPipeline channelPipeline + * @param serverBean 服务配置参数 + */ + protected void initHandler(ChannelPipeline channelPipeline, InitNetty serverBean){ + intProtocolHandler(channelPipeline,serverBean); + channelPipeline.addLast(new IdleStateHandler(serverBean.getHeart(),0,0)); + channelPipeline.addLast(new DefaultHandler(new HandlerServiceImpl(new DataAsynchronousTask(ConfigFactory.inChatToDataBaseService),ConfigFactory.inChatVerifyService))); + } + + private void intProtocolHandler(ChannelPipeline channelPipeline,InitNetty serverBean){ + channelPipeline.addLast(BootstrapConstant.HTTPCODE,new HttpServerCodec()); +// channelPipeline.addLast("http-decoder",new HttpRequestDecoder()); + channelPipeline.addLast(BootstrapConstant.AGGREGATOR, new HttpObjectAggregator(serverBean.getMaxContext())); +// channelPipeline.addLast("http-encoder",new HttpResponseEncoder()); + channelPipeline.addLast(BootstrapConstant.CHUNKEDWRITE,new ChunkedWriteHandler()); + channelPipeline.addLast(BootstrapConstant.WEBSOCKETHANDLER,new WebSocketServerProtocolHandler(serverBean.getWebSocketPath())); + } + +} diff --git a/src/main/java/com/github/unclecatmyself/bootstrap/BootstrapServer.java b/src/main/java/com/github/unclecatmyself/bootstrap/BootstrapServer.java new file mode 100644 index 0000000..00c36fa --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/bootstrap/BootstrapServer.java @@ -0,0 +1,16 @@ +package com.github.unclecatmyself.bootstrap; + +import com.github.unclecatmyself.common.bean.InitNetty; + +/** + * Create by UncleCatMySelf in 2018/12/06 + **/ +public interface BootstrapServer { + + void shutdown(); + + void setServerBean(InitNetty serverBean); + + void start(); + +} diff --git a/src/main/java/com/myself/nettychat/bootstrap/NettyBootstrapServer.java b/src/main/java/com/github/unclecatmyself/bootstrap/NettyBootstrapServer.java similarity index 80% rename from src/main/java/com/myself/nettychat/bootstrap/NettyBootstrapServer.java rename to src/main/java/com/github/unclecatmyself/bootstrap/NettyBootstrapServer.java index 816eea7..815cb27 100644 --- a/src/main/java/com/myself/nettychat/bootstrap/NettyBootstrapServer.java +++ b/src/main/java/com/github/unclecatmyself/bootstrap/NettyBootstrapServer.java @@ -1,134 +1,132 @@ -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(); - } - -} +package com.github.unclecatmyself.bootstrap; + +import com.github.unclecatmyself.auto.AutoConfig; +import com.github.unclecatmyself.auto.RedisConfig; +import com.github.unclecatmyself.common.ip.IpUtils; +import com.github.unclecatmyself.common.bean.InitNetty; +import com.github.unclecatmyself.common.utils.RemotingUtil; +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 org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Create by UncleCatMySelf in 2018/12/06 + **/ +public class NettyBootstrapServer extends AbstractBootstrapServer { + + private final Logger log = LoggerFactory.getLogger(NettyBootstrapServer.class); + + 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.getWebport()).addListener((ChannelFutureListener) channelFuture -> { + if (channelFuture.isSuccess()) { + log.info("服务端启动成功【" + IpUtils.getHost() + ":" + serverBean.getWebport() + "】"); + AutoConfig.address = IpUtils.getHost()+":"+serverBean.getWebport(); + RedisConfig.getInstance(); + }else{ + log.info("服务端启动失败【" + IpUtils.getHost() + ":" + serverBean.getWebport() + "】");} + }); + } + /** + * 初始化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.error("服务端关闭资源失败【" + IpUtils.getHost() + ":" + serverBean.getWebport() + "】"); + } + } + } + + private boolean useEpoll() { + return RemotingUtil.isLinuxPlatform() + && Epoll.isAvailable(); + } + +} diff --git a/src/main/java/com/github/unclecatmyself/bootstrap/backmsg/InChatBackMapService.java b/src/main/java/com/github/unclecatmyself/bootstrap/backmsg/InChatBackMapService.java new file mode 100644 index 0000000..ffb7a07 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/bootstrap/backmsg/InChatBackMapService.java @@ -0,0 +1,55 @@ +package com.github.unclecatmyself.bootstrap.backmsg; + + +import java.util.Map; + +/** + * 消息返回 + * Created by MySelf on 2018/11/23. + */ +public interface InChatBackMapService { + + /** + * 登录成功返回信息 + * @return {@link Map} Json + */ + Map loginSuccess(); + + /** + * 登录失败返回信息 + * @return {@link Map} Json + */ + Map loginError(); + + /** + * 发送给自己 + * @param value {@link String} 通讯消息 + * @return {@link Map} Json + */ + Map sendMe(String value); + + /** + * 发送给某人的信息,返回给自己 + * @param otherOne {@link String} 某人Token + * @param value {@link String} 通讯消息 + * @return {@link Map} Json + */ + Map sendBack(String otherOne, String value); + + /** + * 某人接收到他人发送给他的消息 + * @param me {@link String} 发送人的标签 + * @param value {@link String} 通讯消息 + * @return + */ + Map getMsg(String me, String value); + + /** + * 发送消息到群里 + * @param me {@link String} 发送人的标签 + * @param value {@link String} 通讯消息 + * @param groupId {@link String} 群聊Id + * @return + */ + Map sendGroup(String me,String value,String groupId); +} diff --git a/src/main/java/com/github/unclecatmyself/bootstrap/backmsg/InChatBackMapServiceImpl.java b/src/main/java/com/github/unclecatmyself/bootstrap/backmsg/InChatBackMapServiceImpl.java new file mode 100644 index 0000000..e84fc93 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/bootstrap/backmsg/InChatBackMapServiceImpl.java @@ -0,0 +1,66 @@ +package com.github.unclecatmyself.bootstrap.backmsg; + +import com.github.unclecatmyself.common.constant.Constans; + +import java.util.HashMap; +import java.util.Map; + +/** + * 列入项目中 + * Created by MySelf on 2018/11/23. + */ +public class InChatBackMapServiceImpl implements InChatBackMapService { + + + public Map loginSuccess() { + Map backMap = new HashMap(); + backMap.put(Constans.TYPE,Constans.LOGIN); + backMap.put(Constans.SUCCESS,Constans.TRUE); + return backMap; + } + + + public Map loginError() { + Map backMap = new HashMap(); + backMap.put(Constans.TYPE,Constans.LOGIN); + backMap.put(Constans.SUCCESS,Constans.FALSE); + return backMap; + } + + + public Map sendMe(String value) { + Map backMap = new HashMap(); + backMap.put(Constans.TYPE,Constans.SENDME); + backMap.put(Constans.VALUE,value); + return backMap; + } + + + public Map sendBack(String otherOne, String value) { + Map backMap = new HashMap(); + backMap.put(Constans.TYPE,Constans.SENDTO); + backMap.put(Constans.VALUE,value); + backMap.put(Constans.ONE,otherOne); + return backMap; + } + + + public Map getMsg(String token, String value) { + Map backMap = new HashMap(); + backMap.put(Constans.TYPE,Constans.SENDTO); + backMap.put(Constans.FROM,token); + backMap.put(Constans.VALUE,value); + return backMap; + } + + + public Map sendGroup(String token, String value, String groupId) { + Map backMap = new HashMap(); + backMap.put(Constans.TYPE,Constans.SENDGROUP); + backMap.put(Constans.FROM,token); + backMap.put(Constans.VALUE,value); + backMap.put(Constans.GROUPID,groupId); + return backMap; + } + +} diff --git a/src/main/java/com/github/unclecatmyself/bootstrap/channel/HandlerServiceImpl.java b/src/main/java/com/github/unclecatmyself/bootstrap/channel/HandlerServiceImpl.java new file mode 100644 index 0000000..37dfa32 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/bootstrap/channel/HandlerServiceImpl.java @@ -0,0 +1,185 @@ +package com.github.unclecatmyself.bootstrap.channel; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.github.unclecatmyself.bootstrap.backmsg.InChatBackMapService; +import com.github.unclecatmyself.bootstrap.backmsg.InChatBackMapServiceImpl; +import com.github.unclecatmyself.bootstrap.channel.cache.WsCacheMap; +import com.github.unclecatmyself.bootstrap.channel.http.HttpChannelService; +import com.github.unclecatmyself.bootstrap.channel.http.HttpChannelServiceImpl; +import com.github.unclecatmyself.bootstrap.channel.ws.WebSocketChannelService; +import com.github.unclecatmyself.common.base.HandlerService; +import com.github.unclecatmyself.common.bean.SendInChat; +import com.github.unclecatmyself.common.bean.vo.SendServerVO; +import com.github.unclecatmyself.common.constant.Constans; +import com.google.gson.Gson; +import com.github.unclecatmyself.bootstrap.channel.ws.WsChannelService; +import com.github.unclecatmyself.bootstrap.verify.InChatVerifyService; +import com.github.unclecatmyself.task.DataAsynchronousTask; +import io.netty.channel.Channel; +import io.netty.handler.codec.http.FullHttpMessage; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; +import io.netty.util.CharsetUtil; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Created by MySelf on 2018/11/21. + */ +public class HandlerServiceImpl extends HandlerService { + + private final InChatVerifyService inChatVerifyService; + + private final InChatBackMapService inChatBackMapService = new InChatBackMapServiceImpl(); + + private final HttpChannelService httpChannelService = new HttpChannelServiceImpl(); + + private final WsChannelService websocketChannelService = new WebSocketChannelService(); + + private final DataAsynchronousTask dataAsynchronousTask; + + public HandlerServiceImpl(DataAsynchronousTask dataAsynchronousTask,InChatVerifyService inChatVerifyService) { + this.dataAsynchronousTask = dataAsynchronousTask; + this.inChatVerifyService = inChatVerifyService; + } + + + @Override + public void getList(Channel channel) { + httpChannelService.getList(channel); + } + + @Override + public void getSize(Channel channel) { + httpChannelService.getSize(channel); + } + + @Override + public void sendFromServer(Channel channel, SendServerVO serverVO) { + httpChannelService.sendFromServer(channel,serverVO); + } + + @Override + public void sendInChat(Channel channel, FullHttpMessage msg) { + System.out.println(msg); + String content = msg.content().toString(CharsetUtil.UTF_8); + Gson gson = new Gson(); + SendInChat sendInChat = gson.fromJson(content,SendInChat.class); + httpChannelService.sendByInChat(channel,sendInChat); + } + + @Override + public void notFindUri(Channel channel) { + httpChannelService.notFindUri(channel); + } + + @Override + public boolean login(Channel channel, Map maps) { + //校验规则,自定义校验规则 + return check(channel, maps); + } + + @Override + public void sendMeText(Channel channel, Map maps) { + Gson gson = new Gson(); + channel.writeAndFlush(new TextWebSocketFrame( + gson.toJson(inChatBackMapService.sendMe((String) maps.get(Constans.VALUE))))); + try { + dataAsynchronousTask.writeData(maps); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void sendToText(Channel channel, Map maps) { + Gson gson = new Gson(); + String otherOne = (String) maps.get(Constans.ONE); + String value = (String) maps.get(Constans.VALUE); + String token = (String) maps.get(Constans.TOKEN); + //返回给自己 + channel.writeAndFlush(new TextWebSocketFrame( + gson.toJson(inChatBackMapService.sendBack(otherOne,value)))); + if (websocketChannelService.hasOther(otherOne)){ + //发送给对方--在线 + Channel other = websocketChannelService.getChannel(otherOne); + if (other == null){ + //转http分布式 + httpChannelService.sendInChat(otherOne,inChatBackMapService.getMsg(token,value)); + }else{ + other.writeAndFlush(new TextWebSocketFrame( + gson.toJson(inChatBackMapService.getMsg(token,value)))); + } + }else { + maps.put(Constans.ON_ONLINE,otherOne); + } + try { + dataAsynchronousTask.writeData(maps); + } catch (Exception e) { + return; + } + } + + @Override + public void sendGroupText(Channel channel, Map maps) { + Gson gson = new Gson(); + String groupId = (String) maps.get(Constans.GROUPID); + String token = (String) maps.get(Constans.TOKEN); + String value = (String) maps.get(Constans.VALUE); + List no_online = new ArrayList<>(); + JSONArray array = inChatVerifyService.getArrayByGroupId(groupId); + channel.writeAndFlush(new TextWebSocketFrame( + gson.toJson(inChatBackMapService.sendGroup(token,value,groupId)))); + for (Object item:array) { + if (!token.equals(item)){ + if (websocketChannelService.hasOther((String) item)){ + Channel other = websocketChannelService.getChannel((String) item); + other.writeAndFlush(new TextWebSocketFrame( + gson.toJson(inChatBackMapService.sendGroup(token,value,groupId)))); + }else{ + no_online.add((String) item); + } + } + } + maps.put(Constans.ONLINE_GROUP,no_online); + try { + dataAsynchronousTask.writeData(maps); + } catch (Exception e) { + return; + } + } + + @Override + public void verify(Channel channel, Map maps) { + Gson gson = new Gson(); + String token = (String) maps.get(Constans.TOKEN); + System.out.println(token); + if (inChatVerifyService.verifyToken(token)){ + return; + }else{ + channel.writeAndFlush(new TextWebSocketFrame(gson.toJson(inChatBackMapService.loginError()))); + close(channel); + } + } + + private Boolean check(Channel channel, Map maps){ + Gson gson = new Gson(); + String token = (String) maps.get(Constans.TOKEN); + if (inChatVerifyService.verifyToken(token)){ + channel.writeAndFlush(new TextWebSocketFrame(gson.toJson(inChatBackMapService.loginSuccess()))); + websocketChannelService.loginWsSuccess(channel,token); + return true; + } + channel.writeAndFlush(new TextWebSocketFrame(gson.toJson(inChatBackMapService.loginError()))); + close(channel); + return false; + } + + @Override + public void close(Channel channel) { + websocketChannelService.close(channel); + } +} diff --git a/src/main/java/com/myself/nettychat/bootstrap/channel/cache/CacheMap.java b/src/main/java/com/github/unclecatmyself/bootstrap/channel/cache/CacheMap.java similarity index 89% rename from src/main/java/com/myself/nettychat/bootstrap/channel/cache/CacheMap.java rename to src/main/java/com/github/unclecatmyself/bootstrap/channel/cache/CacheMap.java index 68f805e..3ed8d75 100644 --- a/src/main/java/com/myself/nettychat/bootstrap/channel/cache/CacheMap.java +++ b/src/main/java/com/github/unclecatmyself/bootstrap/channel/cache/CacheMap.java @@ -1,137 +1,134 @@ -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; - } - } - -} +package com.github.unclecatmyself.bootstrap.channel.cache; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * Create by UncleCatMySelf in 2018/12/06 + **/ +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/github/unclecatmyself/bootstrap/channel/cache/WsCacheMap.java b/src/main/java/com/github/unclecatmyself/bootstrap/channel/cache/WsCacheMap.java new file mode 100644 index 0000000..a0a9099 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/bootstrap/channel/cache/WsCacheMap.java @@ -0,0 +1,150 @@ +package com.github.unclecatmyself.bootstrap.channel.cache; + +import com.github.unclecatmyself.auto.AutoConfig; +import com.github.unclecatmyself.auto.ConfigFactory; +import com.github.unclecatmyself.auto.RedisConfig; +import com.github.unclecatmyself.common.exception.NotFindLoginChannlException; +import com.github.unclecatmyself.common.constant.NotInChatConstant; +import com.github.unclecatmyself.common.utils.RedisUtil; +import io.netty.channel.Channel; +import redis.clients.jedis.Jedis; + +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * WebSocket链接实例本地存储 + * Created by MySelf on 2018/11/26. + */ +public class WsCacheMap { + + /** + * 存储用户标识与链接实例 + */ + private final static Map maps = new ConcurrentHashMap(); + + /** + * 存储链接地址与用户标识 + */ + private final static Map addMaps = new ConcurrentHashMap<>(); + + /** + * Redis连接实例 + */ + private final static Jedis jedis = RedisConfig.jedis; + + /** + * 是否启动分布式 + */ + private final static Boolean isDistributed = ConfigFactory.initNetty.getDistributed(); + + private final static String address = AutoConfig.address; + + /** + * 存储链接 + * @param token {@link String} 用户标签 + * @param channel {@link Channel} 链接实例 + */ + public static void saveWs(String token,Channel channel){ + maps.put(token,channel); + if (isDistributed){ + jedis.set(token, RedisUtil.convertMD5(address,token)); + } + } + + /** + * 存储登录信息 + * @param address 登录地址 + * @param token 用户标签 + */ + public static void saveAd(String address,String token){ + addMaps.put(address, token); + } + + /** + * 获取链接数据 + * @param token {@link String} 用户标识 + * @return {@link Channel} 链接实例 + */ + public static Channel getByToken(String token){ + if (isDistributed){ + if (!maps.containsKey(token)){ + //转分布式发送 + return null; + } + } + return maps.get(token); + } + + /** + * 获取对应token标签 + * @param address {@link String} 链接地址 + * @return {@link String} + */ + public static String getByAddress(String address){ + return addMaps.get(address); + } + + /** + * 删除链接数据 + * @param token {@link String} 用户标识 + */ + public static void deleteWs(String token){ + try { + maps.remove(token); + if (isDistributed){ + jedis.del(token); + } + }catch (NullPointerException e){ + throw new NotFindLoginChannlException(NotInChatConstant.Not_Login); + } + } + + /** + * 删除链接地址 + * @param address + */ + public static void deleteAd(String address){ + addMaps.remove(address); + } + + /** + * 获取链接数 + * @return {@link Integer} 链接数 + */ + public static Integer getSize(){ + if (isDistributed){ + return jedis.keys("*").size(); + } + return maps.size(); + } + + /** + * 判断是否存在链接账号 + * @param token {@link String} 用户标识 + * @return {@link Boolean} 是否存在 + */ + public static boolean hasToken(String token){ + if (isDistributed){ + return jedis.exists(token); + } + return maps.containsKey(token); + } + + /** + * 获取在线用户标签列表 + * @return {@link Set} 标识列表 + */ + public static Set getTokenList(){ + if (isDistributed){ + return jedis.keys("*"); + } + Set keys = maps.keySet(); + return keys; + } + + public static String getByJedis(String token) { + return jedis.get(token); + } +} diff --git a/src/main/java/com/github/unclecatmyself/bootstrap/channel/http/FromServerService.java b/src/main/java/com/github/unclecatmyself/bootstrap/channel/http/FromServerService.java new file mode 100644 index 0000000..c92a28f --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/bootstrap/channel/http/FromServerService.java @@ -0,0 +1,55 @@ +package com.github.unclecatmyself.bootstrap.channel.http; + +/** + * public enum FromServerServiceImpl implements FromServerService { + * + * TYPE1(1,"【系统通知】您的账号存在异常,请注意安全保密信息。"), + * TYPE2(2,"【系统通知】恭喜您连续登录超过5天,奖励5积分。"); + * + * private Integer code; + * + * private String message; + * + * FromServerServiceImpl(Integer code, String message){ + * this.code = code; + * this.message = message; + * } + * + * + * public Integer getCode() { + * return code; + * } + * + * + * public String findByCode(Object code) { + * Integer codes = (Integer)code; + * for (FromServerServiceImpl item: FromServerServiceImpl.values()) { + * if (item.code == codes){ + * return item.message; + * } + * } + * return null; + * } + * + * public void setCode(Integer code) { + * this.code = code; + * } + * + * public String getMessage() { + * return message; + * } + * + * public void setMessage(String message) { + * this.message = message; + * } + * + * + * } + * Created by MySelf on 2019/1/2. + */ +public interface FromServerService { + + Integer getCode(); + + String findByCode(Integer code); +} diff --git a/src/main/java/com/github/unclecatmyself/bootstrap/channel/http/HttpChannelService.java b/src/main/java/com/github/unclecatmyself/bootstrap/channel/http/HttpChannelService.java new file mode 100644 index 0000000..0f730a1 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/bootstrap/channel/http/HttpChannelService.java @@ -0,0 +1,30 @@ +package com.github.unclecatmyself.bootstrap.channel.http; + +import com.github.unclecatmyself.common.bean.SendInChat; +import com.github.unclecatmyself.common.bean.vo.SendServerVO; +import io.netty.channel.Channel; +import io.netty.channel.ChannelConfig; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.Map; + +/** + * Create by UncleCatMySelf in 11:41 2018\12\31 0031 + */ +public interface HttpChannelService { + + void getSize(Channel channel); + + void sendFromServer(Channel channel,SendServerVO serverVO); + + void notFindUri(Channel channel); + + void close(Channel channel); + + void getList(Channel channel); + + void sendInChat(String token, Map msg); + + void sendByInChat(Channel channel,SendInChat sendInChat); + +} diff --git a/src/main/java/com/github/unclecatmyself/bootstrap/channel/http/HttpChannelServiceImpl.java b/src/main/java/com/github/unclecatmyself/bootstrap/channel/http/HttpChannelServiceImpl.java new file mode 100644 index 0000000..1bfcd8a --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/bootstrap/channel/http/HttpChannelServiceImpl.java @@ -0,0 +1,135 @@ +package com.github.unclecatmyself.bootstrap.channel.http; + +import com.alibaba.fastjson.JSONObject; +import com.github.unclecatmyself.auto.ConfigFactory; +import com.github.unclecatmyself.bootstrap.channel.cache.WsCacheMap; +import com.github.unclecatmyself.common.bean.SendInChat; +import com.github.unclecatmyself.common.bean.vo.*; +import com.github.unclecatmyself.common.constant.HttpConstant; +import com.github.unclecatmyself.common.constant.LogConstant; +import com.github.unclecatmyself.common.constant.NotInChatConstant; +import com.github.unclecatmyself.common.utils.HttpUtil; +import com.github.unclecatmyself.common.utils.RedisUtil; +import com.google.gson.Gson; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; +import io.netty.handler.codec.http.*; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; +import io.netty.util.CharsetUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.UnsupportedEncodingException; +import java.util.Date; +import java.util.Map; + +/** + * Create by UncleCatMySelf in 11:41 2018\12\31 0031 + */ +public class HttpChannelServiceImpl implements HttpChannelService { + + private static final Logger log = LoggerFactory.getLogger(HttpChannelServiceImpl.class); + + private static FromServerService fromServerService = ConfigFactory.fromServerService; + + @Override + public void getSize(Channel channel) { + FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); + response.headers().set(HttpConstant.CONTENT_TYPE,HttpConstant.APPLICATION_JSON); + GetSizeVO getSizeVO = new GetSizeVO(WsCacheMap.getSize(),new Date()); + ResultVO resultVO = new ResultVO<>(HttpResponseStatus.OK.code(),getSizeVO); + Gson gson = new Gson(); + ByteBuf buf = Unpooled.copiedBuffer(gson.toJson(resultVO), CharsetUtil.UTF_8); + response.content().writeBytes(buf); + channel.writeAndFlush(response); + close(channel); + } + + @Override + public void sendFromServer(Channel channel, SendServerVO serverVO) { + if (serverVO.getToken() == ""){ + notFindUri(channel); + } + Channel userChannel = WsCacheMap.getByToken(serverVO.getToken()); + if (userChannel == null){ + log.info(LogConstant.HTTPCHANNELSERVICEIMPL_NOTFINDLOGIN); + notFindToken(channel); + } + String value = fromServerService.findByCode(Integer.parseInt(serverVO.getValue())); + SendServer sendServer = new SendServer(value); + try { + userChannel.writeAndFlush(new TextWebSocketFrame(JSONObject.toJSONString(sendServer))); + sendServer(channel, NotInChatConstant.SEND_SUCCESS); + }catch (Exception e){ + log.info(LogConstant.HTTPCHANNELSERVICEIMPL_SEND_EXCEPTION); + } + } + + private void sendServer(Channel channel,String msg){ + FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST); + response.headers().set(HttpConstant.CONTENT_TYPE,HttpConstant.APPLICATION_JSON); + NotFindUriVO notFindUriVO = new NotFindUriVO(msg); + ResultVO resultVO = new ResultVO<>(HttpResponseStatus.BAD_REQUEST.code(),notFindUriVO); + Gson gson = new Gson(); + ByteBuf buf = Unpooled.copiedBuffer(gson.toJson(resultVO), CharsetUtil.UTF_8); + response.content().writeBytes(buf); + channel.writeAndFlush(response); + close(channel); + } + + private void notFindToken(Channel channel) { + sendServer(channel,NotInChatConstant.NOT_FIND_LOGIN); + } + + @Override + public void notFindUri(Channel channel) { + sendServer(channel,NotInChatConstant.NOT_FIND_URI); + } + + @Override + public void close(Channel channel) { + log.info(LogConstant.HTTPCHANNELSERVICEIMPL_CLOSE); + channel.close(); + } + + @Override + public void getList(Channel channel) { + FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); + response.headers().set(HttpConstant.CONTENT_TYPE,HttpConstant.APPLICATION_JSON); + GetListVO getListVO = new GetListVO(WsCacheMap.getTokenList()); + ResultVO resultVO = new ResultVO<>(HttpResponseStatus.OK.code(),getListVO); + Gson gson = new Gson(); + ByteBuf buf = Unpooled.copiedBuffer(gson.toJson(resultVO), CharsetUtil.UTF_8); + response.content().writeBytes(buf); + channel.writeAndFlush(response); + close(channel); + } + + @Override + public void sendInChat(String token, Map msg) { + String address = RedisUtil.getAddress(RedisUtil.convertMD5(WsCacheMap.getByJedis(token))); + System.out.println(address); + String[] str = address.split(":"); + try { + HttpClient.getInstance().send(str[0],Integer.parseInt(str[1]),token,msg); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void sendByInChat(Channel channel, SendInChat sendInChat) { + Gson gson = new Gson(); + Channel other = WsCacheMap.getByToken(sendInChat.getToken()); + try { + other.writeAndFlush(new TextWebSocketFrame(gson.toJson(sendInChat.getFrame()))); + }catch (NullPointerException e){ + e.printStackTrace(); + } + FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST); + response.headers().set(HttpConstant.CONTENT_TYPE,HttpConstant.APPLICATION_JSON); + channel.writeAndFlush(response); + close(channel); + } +} diff --git a/src/main/java/com/github/unclecatmyself/bootstrap/channel/http/HttpClient.java b/src/main/java/com/github/unclecatmyself/bootstrap/channel/http/HttpClient.java new file mode 100644 index 0000000..7afea51 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/bootstrap/channel/http/HttpClient.java @@ -0,0 +1,81 @@ +package com.github.unclecatmyself.bootstrap.channel.http; + +import com.github.unclecatmyself.common.bean.SendInChat; +import com.github.unclecatmyself.common.constant.HttpConstant; +import com.google.gson.Gson; +import io.netty.buffer.Unpooled; +import io.netty.channel.*; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.codec.http.*; +import io.netty.util.CharsetUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.URI; +import java.util.Map; + +/** + * Create by UncleCatMySelf in 17:47 2019\1\5 0005 + */ +public class HttpClient { + + private static final Logger log = LoggerFactory.getLogger(HttpClient.class); + + private static HttpClient instance = new HttpClient(); + + public static Bootstrap bootstrap; + + private HttpClient(){ + EventLoopGroup workerGroup = new NioEventLoopGroup(); + Bootstrap b = new Bootstrap(); + b.group(workerGroup); + b.channel(NioSocketChannel.class); + b.option(ChannelOption.SO_KEEPALIVE, true); + b.handler(new ChannelInitializer() { + @Override + public void initChannel(SocketChannel ch) throws Exception { + // 客户端接收到的是httpResponse响应,所以要使用HttpResponseDecoder进行解码 + ch.pipeline().addLast(new HttpResponseDecoder()); + // 客户端发送的是httprequest,所以要使用HttpRequestEncoder进行编码 + ch.pipeline().addLast(new HttpRequestEncoder()); + } + }); + this.bootstrap = b; + } + + public static HttpClient getInstance(){ + return instance; + } + + public void send(String host, int port,String token,Map value) throws Exception { + // Start the client. + ChannelFuture f = this.bootstrap.connect(host, port).sync(); + + URI uri = new URI(HttpConstant.URI_SENDINCHAT); + + Gson gson = new Gson(); + String content = gson.toJson(new SendInChat(token,value)); + DefaultFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, + uri.toASCIIString(),Unpooled.wrappedBuffer(content.getBytes(CharsetUtil.UTF_8))); + + // 构建http请求 + request.headers().set(HttpHeaderNames.HOST, host); + request.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE); + request.headers().set(HttpHeaderNames.CONTENT_LENGTH, request.content().readableBytes()); +// request.headers().set(HttpHeaderNames.CONTENT_TYPE,HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED); + + // 发送http请求 + f.channel().write(request); + f.channel().flush(); + f.channel().closeFuture().sync(); + } + +// public static void main(String[] args) throws Exception { +// HttpClient client = new HttpClient(); +// client.connect("192.168.1.121",8090); +// } + +} diff --git a/src/main/java/com/github/unclecatmyself/bootstrap/channel/ws/WebSocketChannelService.java b/src/main/java/com/github/unclecatmyself/bootstrap/channel/ws/WebSocketChannelService.java new file mode 100644 index 0000000..f5ad892 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/bootstrap/channel/ws/WebSocketChannelService.java @@ -0,0 +1,51 @@ +package com.github.unclecatmyself.bootstrap.channel.ws; + +import com.google.gson.Gson; +import com.github.unclecatmyself.bootstrap.channel.cache.WsCacheMap; +import io.netty.channel.Channel; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.Map; + +/** + * Created by MySelf on 2018/11/26. + */ +public class WebSocketChannelService implements WsChannelService { + + @Override + public void loginWsSuccess(Channel channel, String token) { + WsCacheMap.saveWs(token,channel); + WsCacheMap.saveAd(channel.remoteAddress().toString(),token); + } + + @Override + public boolean hasOther(String otherOne) { + return WsCacheMap.hasToken(otherOne); + } + + @Override + public Channel getChannel(String otherOne) { + return WsCacheMap.getByToken(otherOne); + } + + @Override + public void close(Channel channel) { + String token = WsCacheMap.getByAddress(channel.remoteAddress().toString()); + WsCacheMap.deleteAd(channel.remoteAddress().toString()); + WsCacheMap.deleteWs(token); + channel.close(); + } + + @Override + public boolean sendFromServer(Channel channel, Map map) { + Gson gson = new Gson(); + try { + channel.writeAndFlush(new TextWebSocketFrame(gson.toJson(map))); + return true; + }catch (Exception e){ + return false; + } + } + + +} diff --git a/src/main/java/com/github/unclecatmyself/bootstrap/channel/ws/WsChannelService.java b/src/main/java/com/github/unclecatmyself/bootstrap/channel/ws/WsChannelService.java new file mode 100644 index 0000000..e3b8113 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/bootstrap/channel/ws/WsChannelService.java @@ -0,0 +1,47 @@ +package com.github.unclecatmyself.bootstrap.channel.ws; + +import io.netty.channel.Channel; + +import java.util.Map; + +/** + * WebSocket 聊天业务消息处理 + * Created by MySelf on 2018/11/26. + */ +public interface WsChannelService { + + /** + * 登录成功存储到本地缓存 + * @param channel {@link Channel} 链接实例 + * @param token {@link String} 用户标识 + */ + void loginWsSuccess(Channel channel, String token); + + /** + * 判断是否存在当前在线用户 + * @param otherOne {@link String} 某人的用户标识 + * @return {@link Boolean} 是否存在 + */ + boolean hasOther(String otherOne); + + /** + * 获取某人的链接实例 + * @param otherOne {@link String} 用户唯一标识 + * @return {@link Channel} 链接实例 + */ + Channel getChannel(String otherOne); + + /** + * 删除链接与本地存储信息 + * @param channel {@link Channel} 链接实例 + */ + void close(Channel channel); + + /** + * 以服务端API调用向链接发送信息 + * @param channel {@link } + * @param map + * @return + */ + boolean sendFromServer(Channel channel, Map map); +} diff --git a/src/main/java/com/github/unclecatmyself/bootstrap/data/InChatToDataBaseService.java b/src/main/java/com/github/unclecatmyself/bootstrap/data/InChatToDataBaseService.java new file mode 100644 index 0000000..623f7ca --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/bootstrap/data/InChatToDataBaseService.java @@ -0,0 +1,14 @@ +package com.github.unclecatmyself.bootstrap.data; + +import com.github.unclecatmyself.common.bean.InChatMessage; + +import java.util.Map; + +/** + * Created by MySelf on 2018/12/3. + */ +public interface InChatToDataBaseService { + + Boolean writeMessage(InChatMessage message); + +} diff --git a/src/main/java/com/github/unclecatmyself/bootstrap/handler/DefaultHandler.java b/src/main/java/com/github/unclecatmyself/bootstrap/handler/DefaultHandler.java new file mode 100644 index 0000000..2a84277 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/bootstrap/handler/DefaultHandler.java @@ -0,0 +1,138 @@ +package com.github.unclecatmyself.bootstrap.handler; + +import com.alibaba.fastjson.JSON; +import com.github.unclecatmyself.common.base.Handler; +import com.github.unclecatmyself.common.base.HandlerApi; +import com.github.unclecatmyself.common.base.HandlerService; +import com.github.unclecatmyself.common.bean.vo.SendServerVO; +import com.github.unclecatmyself.common.constant.Constans; +import com.github.unclecatmyself.common.constant.HttpConstant; +import com.github.unclecatmyself.common.constant.LogConstant; +import com.github.unclecatmyself.common.constant.NotInChatConstant; +import com.github.unclecatmyself.common.exception.NoFindHandlerException; +import com.github.unclecatmyself.common.utils.HttpUtil; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.*; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; +import io.netty.handler.codec.http.websocketx.WebSocketFrame; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.UnsupportedEncodingException; +import java.util.Date; +import java.util.Map; + +/** + * Create by UncleCatMySelf in 2018/12/06 + */ +@ChannelHandler.Sharable +public class DefaultHandler extends Handler { + + private final Logger log = LoggerFactory.getLogger(DefaultHandler.class); + + private final HandlerApi handlerApi; + + public DefaultHandler(HandlerApi handlerApi) { + super(handlerApi); + this.handlerApi = handlerApi; + } + + @Override + protected void webdoMessage(ChannelHandlerContext ctx, WebSocketFrame msg) { + //实现图片处理 + + } + + @Override + protected void httpdoMessage(ChannelHandlerContext ctx, FullHttpRequest msg) { + Channel channel = ctx.channel(); + HandlerService httpHandlerService; + if (handlerApi instanceof HandlerService){ + httpHandlerService = (HandlerService)handlerApi; + }else { + throw new NoFindHandlerException(NotInChatConstant.NOT_HANDLER); + } + switch (HttpUtil.checkType(msg)){ + case HttpConstant.GETSIZE: + log.info(LogConstant.DEFAULTWEBSOCKETHANDLER_GETSIZE); + httpHandlerService.getSize(channel); + break; + case HttpConstant.SENDFROMSERVER: + log.info(LogConstant.DEFAULTWEBSOCKETHANDLER_SENDFROMSERVER); + SendServerVO serverVO = null; + try { + serverVO = HttpUtil.getToken(msg); + } catch (UnsupportedEncodingException e) { + log.error(e.getMessage()); + } + httpHandlerService.sendFromServer(channel,serverVO); + break; + case HttpConstant.GETLIST: + log.info(LogConstant.DEFAULTWEBSOCKETHANDLER_GETLIST); + httpHandlerService.getList(channel); + break; + case HttpConstant.SENDINCHAT: + log.info(LogConstant.DEFAULTWEBSOCKETHANDLER_SENDINCHAT); + httpHandlerService.sendInChat(channel,msg); + break; + case HttpConstant.NOTFINDURI: + log.info(LogConstant.DEFAULTWEBSOCKETHANDLER_NOTFINDURI); + httpHandlerService.notFindUri(channel); + break; + default: + break; + } + } + + @Override + protected void textdoMessage(ChannelHandlerContext ctx, TextWebSocketFrame msg) { + Channel channel = ctx.channel(); + HandlerService handlerService; + if (handlerApi instanceof HandlerService){ + handlerService = (HandlerService)handlerApi; + }else{ + throw new NoFindHandlerException(NotInChatConstant.NOT_HANDLER); + } + Map maps = (Map) JSON.parse(msg.text()); + maps.put(Constans.TIME, new Date()); + switch ((String)maps.get(Constans.TYPE)){ + case Constans.LOGIN: + log.info(LogConstant.DEFAULTWEBSOCKETHANDLER_LOGIN); + handlerService.login(channel,maps); + break; + //针对个人,发送给自己 + case Constans.SENDME: + log.info(LogConstant.DEFAULTWEBSOCKETHANDLER_SENDME); + handlerService.verify(channel,maps); + handlerService.sendMeText(channel,maps); + break; + //针对个人,发送给某人 + case Constans.SENDTO: + log.info(LogConstant.DefaultWebSocketHandler_SENDTO); + handlerService.verify(channel,maps); + handlerService.sendToText(channel,maps); + break; + //发送给群组 + case Constans.SENDGROUP: + log.info(LogConstant.DEFAULTWEBSOCKETHANDLER_SENDGROUP); + handlerService.verify(channel,maps); + handlerService.sendGroupText(channel,maps); + break; + default: + break; + } + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + log.info(LogConstant.CHANNELACTIVE+ctx.channel().remoteAddress().toString()+LogConstant.CHANNEL_SUCCESS); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception{ +// log.error("exception",cause); + log.info(LogConstant.EXCEPTIONCAUGHT+ctx.channel().remoteAddress().toString()+LogConstant.DISCONNECT); + ctx.close(); + } +} diff --git a/src/main/java/com/github/unclecatmyself/bootstrap/redisclient/testApplication.java b/src/main/java/com/github/unclecatmyself/bootstrap/redisclient/testApplication.java new file mode 100644 index 0000000..afcbcc0 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/bootstrap/redisclient/testApplication.java @@ -0,0 +1,22 @@ +package com.github.unclecatmyself.bootstrap.redisclient; + +import redis.clients.jedis.Jedis; + +/** + * Create by UncleCatMySelf in 23:02 2019\1\4 0004 + */ +public class testApplication { + + public static void main(String[] args) { + //连接redis服务 + Jedis jedis = new Jedis("192.168.12.129"); + System.out.println("连接成功"); + //设置redis字符串数据 + //jedis.set("token","inchat"); + //查看服务是否运行 + System.out.println("服务正在运行:"+jedis.ping()); + //获取存储的数据并输出 + System.out.println("redis存储的字符串为:"+jedis.get("token")); + } + +} diff --git a/src/main/java/com/github/unclecatmyself/bootstrap/verify/InChatVerifyService.java b/src/main/java/com/github/unclecatmyself/bootstrap/verify/InChatVerifyService.java new file mode 100644 index 0000000..0854bfd --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/bootstrap/verify/InChatVerifyService.java @@ -0,0 +1,15 @@ +package com.github.unclecatmyself.bootstrap.verify; + +import com.alibaba.fastjson.JSONArray; + +/** + * 用户校验层 + * Created by MySelf on 2018/11/22. + */ +public interface InChatVerifyService { + + boolean verifyToken(String token); + + JSONArray getArrayByGroupId(String groupId); + +} \ No newline at end of file diff --git a/src/main/java/com/github/unclecatmyself/common/base/Handler.java b/src/main/java/com/github/unclecatmyself/common/base/Handler.java new file mode 100644 index 0000000..c72e945 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/common/base/Handler.java @@ -0,0 +1,61 @@ +package com.github.unclecatmyself.common.base; + +import com.github.unclecatmyself.common.constant.LogConstant; +import com.github.unclecatmyself.common.exception.NotFindLoginChannlException; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; +import io.netty.handler.codec.http.websocketx.WebSocketFrame; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Netty实现初始层 + * Create by UncleCatMySelf in 2018/12/06 + */ +public abstract class Handler extends SimpleChannelInboundHandler { + + private static final Logger log = LoggerFactory.getLogger(Handler.class); + + HandlerApi handlerApi; + + public Handler(HandlerApi handlerApi){ + this.handlerApi = handlerApi; + } + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { + if (msg instanceof TextWebSocketFrame){ + textdoMessage(ctx,(TextWebSocketFrame)msg); + }else if (msg instanceof WebSocketFrame){ + webdoMessage(ctx,(WebSocketFrame)msg); + }else if (msg instanceof FullHttpRequest){ + httpdoMessage(ctx,(FullHttpRequest)msg); + } + } + + protected abstract void webdoMessage(ChannelHandlerContext ctx, WebSocketFrame msg); + + protected abstract void textdoMessage(ChannelHandlerContext ctx, TextWebSocketFrame msg); + + protected abstract void httpdoMessage(ChannelHandlerContext ctx, FullHttpRequest msg); + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + log.info(LogConstant.CHANNELINACTIVE+ctx.channel().localAddress().toString()+LogConstant.CLOSE_SUCCESS); + try { + handlerApi.close(ctx.channel()); + }catch (NotFindLoginChannlException e){ + log.error(LogConstant.NOTFINDLOGINCHANNLEXCEPTION); + } + } + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { +// if(evt instanceof IdleStateEvent){ +// webSocketHandlerApi.doTimeOut(ctx.channel(),(IdleStateEvent)evt); +// } + super.userEventTriggered(ctx, evt); + } +} diff --git a/src/main/java/com/github/unclecatmyself/common/base/HandlerApi.java b/src/main/java/com/github/unclecatmyself/common/base/HandlerApi.java new file mode 100644 index 0000000..536c0ad --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/common/base/HandlerApi.java @@ -0,0 +1,14 @@ +package com.github.unclecatmyself.common.base; + +import io.netty.channel.Channel; + +import java.util.Map; + +/** + * Create by UncleCatMySelf in 2018/12/06 + */ +public interface HandlerApi { + + void close(Channel channel); + +} diff --git a/src/main/java/com/github/unclecatmyself/common/base/HandlerService.java b/src/main/java/com/github/unclecatmyself/common/base/HandlerService.java new file mode 100644 index 0000000..009ece3 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/common/base/HandlerService.java @@ -0,0 +1,83 @@ +package com.github.unclecatmyself.common.base; + +import com.github.unclecatmyself.common.bean.vo.SendServerVO; +import io.netty.channel.Channel; +import io.netty.handler.codec.http.FullHttpMessage; + +import java.util.Map; + +/** + * 业务层伪接口 + * Created by MySelf on 2018/11/21. + */ +public abstract class HandlerService implements HandlerApi { + + /** + * HTTP获取在线用户标签列表 + * @param channel {@link Channel} 链接实例 + */ + public abstract void getList(Channel channel); + + /** + * HTTP获取在线用户数 + * @param channel {@link Channel} 链接实例 + */ + public abstract void getSize(Channel channel); + + /** + * HTTP以服务端向指定用户发送通知 + * @param channel {@link Channel} 链接实例 + * @param sendServerVO {@link SendServerVO} 用户标识 + */ + public abstract void sendFromServer(Channel channel,SendServerVO sendServerVO); + + /** + * HTTP以服务端处理发送 + * @param channel + */ + public abstract void sendInChat(Channel channel, FullHttpMessage msg); + + /** + * 用户未找到匹配Uri + * @param channel {@link Channel} 链接实例 + */ + public abstract void notFindUri(Channel channel); + + /** + * 登录类型 + * @param channel {@link Channel} 链接实例 + * @param map {@link Map} 数据信息 + * @return {@link Boolean} 成功失败 + */ + public abstract boolean login(Channel channel, Map map); + + /** + * 发送给自己 + * @param channel {@link Channel} 链接实例 + * @param maps {@link Map} 数据信息 + */ + public abstract void sendMeText(Channel channel,Map maps); + + /** + * 发送给某人 + * @param channel {@link Channel} 链接实例 + * @param maps {@link Map} 数据信息 + */ + public abstract void sendToText(Channel channel, Map maps); + + /** + * 发送给群聊 + * @param channel {@link Channel} 链接实例 + * @param maps {@link Map} 数据信息 + */ + public abstract void sendGroupText(Channel channel, Map maps); + + /** + * 登录校验 + * @param channel {@link Channel} 链接实例 + * @param maps {@link Map} 数据信息 + */ + public abstract void verify(Channel channel, Map maps); + + +} diff --git a/src/main/java/com/github/unclecatmyself/common/bean/InChatMessage.java b/src/main/java/com/github/unclecatmyself/common/bean/InChatMessage.java new file mode 100644 index 0000000..847e74a --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/common/bean/InChatMessage.java @@ -0,0 +1,113 @@ +package com.github.unclecatmyself.common.bean; + +import java.util.ArrayList; +import java.util.Date; + +/** + * 用户层消息Bean封装 + * Created by MySelf on 2018/12/19. + */ +public class InChatMessage { + + /** 消息时间 */ + private Date time; + + /** 消息类型 */ + private String type; + + /** 消息值 */ + private String value; + + /** 用户标识 */ + private String token; + + /** 群聊Id */ + private String groudId; + + /** 是否在线-个人 */ + private String online; + + /** 是否在线-群聊 */ + private ArrayList onlineGroup; + + /** 消息接收人标识 */ + private String one; + + public ArrayList getOnlineGroup() { + return onlineGroup; + } + + public void setOnlineGroup(ArrayList onlineGroup) { + this.onlineGroup = onlineGroup; + } + + public Date getTime() { + return time; + } + + public void setTime(Date time) { + this.time = time; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public String getGroudId() { + return groudId; + } + + public void setGroudId(String groudId) { + this.groudId = groudId; + } + + public String getOnline() { + return online; + } + + public void setOnline(String online) { + this.online = online; + } + + public String getOne() { + return one; + } + + public void setOne(String one) { + this.one = one; + } + + @Override + public String toString() { + return "InChatMessage{" + + "time=" + time + + ", type='" + type + '\'' + + ", value='" + value + '\'' + + ", token='" + token + '\'' + + ", groudId='" + groudId + '\'' + + ", online='" + online + '\'' + + ", onlineGroup=" + onlineGroup + + ", one='" + one + '\'' + + '}'; + } +} diff --git a/src/main/java/com/github/unclecatmyself/common/bean/InitNetty.java b/src/main/java/com/github/unclecatmyself/common/bean/InitNetty.java new file mode 100644 index 0000000..08ca2f3 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/common/bean/InitNetty.java @@ -0,0 +1,201 @@ +package com.github.unclecatmyself.common.bean; + +import com.github.unclecatmyself.bootstrap.handler.DefaultHandler; + +/** + * 初始化Netty配置 + * Create by UncleCatMySelf in 2018/12/06 + */ +public class InitNetty { + + private int webport = 8090; + + private int bossThread = 1; + + private int workerThread = 2; + + private boolean keepalive = true; + + private int backlog = 1024; + + private boolean nodelay = true; + + private boolean reuseaddr = true; + + private int sndbuf = 10485760; + + private int revbuf = 10485760; + + private int heart = 180; + + private int period = 10; + + private String serverName = "iot-netty-chat"; + + private int initalDelay = 10; + + private int maxContext = 65536; + + private String webSocketPath = "/ws"; + + private Boolean isDistributed = false; + + private Class webSocketHandler = DefaultHandler.class; + + public Boolean getDistributed() { + return isDistributed; + } + + public void setDistributed(Boolean distributed) { + isDistributed = distributed; + } + + /** + * 返回WebSocket启动监听端口 + * @return {@link Integer} WebSocket端口 + */ + public int getWebport() { + return webport; + } + + /** + * 返回Netty核心线程个数 + * @return {@link Integer} Netty线程个数 + */ + public int getBossThread() { + return bossThread; + } + + public void setBossThread(int bossThread) { + this.bossThread = bossThread; + } + + /** + * 返回Netty工作线程个数 + * @return {@link Integer} Netty工作线程个数 + */ + public int getWorkerThread() { + return workerThread; + } + + public void setWorkerThread(int workerThread) { + this.workerThread = workerThread; + } + + /** + * 是否保持链接 + * @return {@link Boolean} 是否保持链接 + */ + public boolean isKeepalive() { + return keepalive; + } + + /** + * 服务端接受连接的队列长度,如果队列已满,客户端连接将被拒绝 + * @return {@link Integer} 服务端接受连接的队列长度 + */ + public int getBacklog() { + return backlog; + } + + public void setBacklog(int backlog) { + this.backlog = backlog; + } + + /** + * TCP参数,立即发送数据,默认值为Ture(Netty默认为True而操作系统默认为False)。 + * 该值设置Nagle算法的启用,改算法将小的碎片数据连接成更大的报文来最小化所发送的报文的数量, + * 如果需要发送一些较小的报文,则需要禁用该算法。Netty默认禁用该算法,从而最小化报文传输延时。 + * @return {@link Boolean} Nagle算法是否启用 + */ + public boolean isNodelay() { + return nodelay; + } + + /** + * 地址复用,默认值False。有四种情况可以使用: + * (1).当有一个有相同本地地址和端口的socket1处于TIME_WAIT状态时,而你希望启动的程序的socket2要占用该地址和端口,比如重启服务且保持先前端口。 + * (2).有多块网卡或用IP Alias技术的机器在同一端口启动多个进程,但每个进程绑定的本地IP地址不能相同。 + * (3).单个进程绑定相同的端口到多个socket上,但每个socket绑定的ip地址不同。 + * (4).完全相同的地址和端口的重复绑定。但这只用于UDP的多播,不用于TCP。 + * @return {@link Boolean} 地址复用 + */ + public boolean isReuseaddr() { + return reuseaddr; + } + + + /** + * TCP数据接收缓冲区大小。 + * @return {@link Integer} TCP数据接收缓冲区大小。 + */ + public int getRevbuf() { + return revbuf; + } + + public void setRevbuf(int revbuf) { + this.revbuf = revbuf; + } + + /** + * 读超时时间 + * @return {@link Integer} 读超时时间 + */ + public int getHeart() { + return heart; + } + + public void setHeart(int heart) { + this.heart = heart; + } + + /** + * 消息 重发周期 + * @return {@link Integer} 消息重发周期 + */ + public int getPeriod() { + return period; + } + + public void setPeriod(int period) { + this.period = period; + } + + /** + * 服务名称 + * @return {@link String} 服务名称 + */ + public String getServerName() { + return serverName; + } + + /** + * 消息 重发延迟 + * @return {@link Integer} 消息重发延迟 + */ + public int getInitalDelay() { + return initalDelay; + } + + public void setInitalDelay(int initalDelay) { + this.initalDelay = initalDelay; + } + + public int getMaxContext() { + return maxContext; + } + + /** + * WebSocket URL 后缀地址 + * @return {@link String} WebSocket URL 后缀地址 + */ + public String getWebSocketPath() { + return webSocketPath; + } + + + public Class getWebSocketHandler() { + return webSocketHandler; + } + +} diff --git a/src/main/java/com/github/unclecatmyself/common/bean/SendInChat.java b/src/main/java/com/github/unclecatmyself/common/bean/SendInChat.java new file mode 100644 index 0000000..3946077 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/common/bean/SendInChat.java @@ -0,0 +1,39 @@ +package com.github.unclecatmyself.common.bean; + +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +import java.util.Map; + +/** + * Create by UncleCatMySelf in 16:06 2019\1\5 0005 + */ +public class SendInChat { + + private String token; + + private Map frame; + + public SendInChat() { + } + + public SendInChat(String token, Map frame) { + this.token = token; + this.frame = frame; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public Map getFrame() { + return frame; + } + + public void setFrame(Map frame) { + this.frame = frame; + } +} diff --git a/src/main/java/com/github/unclecatmyself/common/bean/vo/GetListVO.java b/src/main/java/com/github/unclecatmyself/common/bean/vo/GetListVO.java new file mode 100644 index 0000000..43abe08 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/common/bean/vo/GetListVO.java @@ -0,0 +1,25 @@ +package com.github.unclecatmyself.common.bean.vo; + +import java.util.Set; + +/** + * Create by UncleCatMySelf in 12:26 2018\12\31 0031 + */ +public class GetListVO { + + + + private Set tokens; + + public GetListVO(Set tokens) { + this.tokens = tokens; + } + + public Set getTokens() { + return tokens; + } + + public void setTokens(Set tokens) { + this.tokens = tokens; + } +} diff --git a/src/main/java/com/github/unclecatmyself/common/bean/vo/GetSizeVO.java b/src/main/java/com/github/unclecatmyself/common/bean/vo/GetSizeVO.java new file mode 100644 index 0000000..691da26 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/common/bean/vo/GetSizeVO.java @@ -0,0 +1,34 @@ +package com.github.unclecatmyself.common.bean.vo; + +import java.util.Date; + +/** + * Create by UncleCatMySelf in 11:13 2018\12\31 0031 + */ +public class GetSizeVO { + + private Integer online; + + private Date time; + + public GetSizeVO(Integer online, Date time) { + this.online = online; + this.time = time; + } + + public Integer getOnline() { + return online; + } + + public void setOnline(Integer online) { + this.online = online; + } + + public Date getTime() { + return time; + } + + public void setTime(Date time) { + this.time = time; + } +} diff --git a/src/main/java/com/github/unclecatmyself/common/bean/vo/NotFindUriVO.java b/src/main/java/com/github/unclecatmyself/common/bean/vo/NotFindUriVO.java new file mode 100644 index 0000000..b4fadba --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/common/bean/vo/NotFindUriVO.java @@ -0,0 +1,21 @@ +package com.github.unclecatmyself.common.bean.vo; + +/** + * Create by UncleCatMySelf in 11:21 2018\12\31 0031 + */ +public class NotFindUriVO { + + private String message; + + public NotFindUriVO(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/src/main/java/com/github/unclecatmyself/common/bean/vo/ResultVO.java b/src/main/java/com/github/unclecatmyself/common/bean/vo/ResultVO.java new file mode 100644 index 0000000..db52fa8 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/common/bean/vo/ResultVO.java @@ -0,0 +1,40 @@ +package com.github.unclecatmyself.common.bean.vo; + +/** + * Create by UncleCatMySelf in 11:11 2018\12\31 0031 + */ +public class ResultVO { + + private int code; + + private T data; + + public ResultVO(int code, T data) { + this.code = code; + this.data = data; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } + + @Override + public String toString() { + return "ResultVO{" + + "code=" + code + + ", data=" + data + + '}'; + } +} diff --git a/src/main/java/com/github/unclecatmyself/common/bean/vo/SendServer.java b/src/main/java/com/github/unclecatmyself/common/bean/vo/SendServer.java new file mode 100644 index 0000000..e03a0ef --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/common/bean/vo/SendServer.java @@ -0,0 +1,33 @@ +package com.github.unclecatmyself.common.bean.vo; + +import com.github.unclecatmyself.common.constant.Constans; + +/** + * Created by MySelf on 2019/1/3. + */ +public class SendServer { + + private String type = Constans.SERVER; + + private String value; + + public SendServer(String value) { + this.value = value; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/src/main/java/com/github/unclecatmyself/common/bean/vo/SendServerVO.java b/src/main/java/com/github/unclecatmyself/common/bean/vo/SendServerVO.java new file mode 100644 index 0000000..f5c66fb --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/common/bean/vo/SendServerVO.java @@ -0,0 +1,27 @@ +package com.github.unclecatmyself.common.bean.vo; + +/** + * Created by MySelf on 2019/1/2. + */ +public class SendServerVO { + + private String token; + + private String value; + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/src/main/java/com/github/unclecatmyself/common/constant/BootstrapConstant.java b/src/main/java/com/github/unclecatmyself/common/constant/BootstrapConstant.java new file mode 100644 index 0000000..9060cbf --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/common/constant/BootstrapConstant.java @@ -0,0 +1,16 @@ +package com.github.unclecatmyself.common.constant; + +/** + * Created by MySelf on 2019/1/3. + */ +public class BootstrapConstant { + + public static final String HTTPCODE = "httpCode"; + + public static final String AGGREGATOR = "aggregator"; + + public static final String CHUNKEDWRITE = "chunkedWrite"; + + public static final String WEBSOCKETHANDLER = "webSocketHandler"; + +} diff --git a/src/main/java/com/github/unclecatmyself/common/constant/Constans.java b/src/main/java/com/github/unclecatmyself/common/constant/Constans.java new file mode 100644 index 0000000..03d64f8 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/common/constant/Constans.java @@ -0,0 +1,41 @@ +package com.github.unclecatmyself.common.constant; + +/** + * Created by MySelf on 2018/12/5. + */ +public class Constans { + + public static final String TOKEN = "token"; + + public static final String VALUE = "value"; + + public static final String ONE = "one"; + + public static final String ON_ONLINE = "on_online"; + + public static final String ONLINE_GROUP = "online_group"; + + public static final String GROUPID = "groupId"; + + public static final String TYPE = "type"; + + public static final String LOGIN = "login"; + + public static final String SUCCESS = "success"; + + public static final String TRUE = "true"; + + public static final String FALSE = "false"; + + public static final String SENDME = "sendMe"; + + public static final String SENDTO = "sendTo"; + + public static final String FROM = "from"; + + public static final String SENDGROUP = "sendGroup"; + + public static final String TIME = "time"; + + public static final String SERVER = "server"; +} diff --git a/src/main/java/com/github/unclecatmyself/common/constant/HttpConstant.java b/src/main/java/com/github/unclecatmyself/common/constant/HttpConstant.java new file mode 100644 index 0000000..971d94e --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/common/constant/HttpConstant.java @@ -0,0 +1,33 @@ +package com.github.unclecatmyself.common.constant; + +/** + * Create by UncleCatMySelf in 22:49 2018\12\30 0030 + */ +public class HttpConstant { + + public static final String GET = "GET"; + + public static final String POST = "POST"; + + public static final String GETSIZE = "get_size"; + + public static final String GETLIST = "get_list"; + + public static final String SENDINCHAT = "send_inchat"; + + public static final String SENDFROMSERVER = "send_from_server"; + + public static final String NOTFINDURI = "not_find_uri"; + + public static final String URI_GETSIZE = "/get_size"; + + public static final String URI_GETLIST = "/get_list"; + + public static final String URI_SENDINCHAT = "/send_inchat"; + + public static final String URI_SENDFROMSERVER = "/send_from_server"; + + public static final String CONTENT_TYPE = "Content-Type"; + + public static final String APPLICATION_JSON = "application/json;charset=UTF-8"; +} diff --git a/src/main/java/com/github/unclecatmyself/common/constant/LogConstant.java b/src/main/java/com/github/unclecatmyself/common/constant/LogConstant.java new file mode 100644 index 0000000..87f667e --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/common/constant/LogConstant.java @@ -0,0 +1,53 @@ +package com.github.unclecatmyself.common.constant; + +/** + * Created by MySelf on 2019/1/3. + */ +public class LogConstant { + + public static final String HTTPCHANNELSERVICEIMPL_NOTFINDLOGIN = "[HttpChannelServiceImpl.sendFromServer] 未找到用户在线标识"; + + public static final String HTTPCHANNELSERVICEIMPL_CLOSE = "[HttpChannelServiceImpl.close] 关闭HTTP通道连接"; + + public static final String HTTPCHANNELSERVICEIMPL_SEND_EXCEPTION = "[HttpChannelServiceImpl.sendFromServer] 发送通知异常"; + + public static final String DEFAULTWEBSOCKETHANDLER_GETSIZE = "[DefaultWebSocketHandler.httpdoMessage.GETSIZE]"; + + public static final String DEFAULTWEBSOCKETHANDLER_SENDFROMSERVER = "[DefaultWebSocketHandler.httpdoMessage.SENDFROMSERVER]"; + + public static final String DEFAULTWEBSOCKETHANDLER_NOTFINDURI = "[DefaultWebSocketHandler.httpdoMessage.NOTFINDURI]"; + + public static final String DEFAULTWEBSOCKETHANDLER_GETLIST = "[DefaultWebSocketHandler.httpdoMessage.GETLIST]"; + + public static final String DEFAULTWEBSOCKETHANDLER_SENDINCHAT = "[DefaultWebSocketHandler.httpdoMessage.SENDINCHAT]"; + + public static final String DEFAULTWEBSOCKETHANDLER_LOGIN = "[DefaultWebSocketHandler.textdoMessage.LOGIN]"; + + public static final String DEFAULTWEBSOCKETHANDLER_SENDME = "[DefaultWebSocketHandler.textdoMessage.SENDME]"; + + public static final String DefaultWebSocketHandler_SENDTO = "[DefaultWebSocketHandler.textdoMessage.SENDTO]"; + + public static final String DEFAULTWEBSOCKETHANDLER_SENDGROUP = "[DefaultWebSocketHandler.textdoMessage.SENDGROUP]"; + + public static final String CHANNELACTIVE = "[DefaultWebSocketHandler.channelActive]"; + + public static final String CHANNEL_SUCCESS = "链接成功"; + + public static final String DISCONNECT = "异常断开"; + + public static final String EXCEPTIONCAUGHT = "[DefaultWebSocketHandler.exceptionCaught]"; + + public static final String CHANNELINACTIVE = "[Handler:channelInactive]"; + + public static final String CLOSE_SUCCESS = "关闭成功"; + + public static final String NOTFINDLOGINCHANNLEXCEPTION = "[捕获异常:NotFindLoginChannlException]-[Handler:channelInactive] 关闭未正常注册链接!"; + + public static final String DATAASYNCHRONOUSTASK_01 = "[DataAsynchronousTask.writeData]:数据外抛异常"; + + public static final String DATAASYNCHRONOUSTASK_02 = "[DataAsynchronousTask.writeData]:数据外抛异常"; + + public static final String DATAASYNCHRONOUSTASK_03 = "[DataAsynchronousTask.writeData]:线程任务执行异常"; + + public static final String REDIS_START = "[RedisConfig.getJedis]:连接成功,测试连接PING->"; +} diff --git a/src/main/java/com/github/unclecatmyself/common/constant/NotInChatConstant.java b/src/main/java/com/github/unclecatmyself/common/constant/NotInChatConstant.java new file mode 100644 index 0000000..5da4693 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/common/constant/NotInChatConstant.java @@ -0,0 +1,18 @@ +package com.github.unclecatmyself.common.constant; + +/** + * Created by MySelf on 2019/1/3. + */ +public class NotInChatConstant { + + public static final String Not_Login = "未找到正常注册的连接"; + + public static final String SEND_SUCCESS = "通知发送成功"; + + public static final String NOT_FIND_LOGIN = "未找到在线用户标识"; + + public static final String NOT_FIND_URI = "未找到匹配任务URI"; + + public static final String NOT_HANDLER = "Server Handler 不匹配"; + +} diff --git a/src/main/java/com/github/unclecatmyself/common/exception/NoFindHandlerException.java b/src/main/java/com/github/unclecatmyself/common/exception/NoFindHandlerException.java new file mode 100644 index 0000000..99cf181 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/common/exception/NoFindHandlerException.java @@ -0,0 +1,15 @@ +package com.github.unclecatmyself.common.exception; + +/** + * 找不到对应处理类 + * Create by UncleCatMySelf in 2018/12/06 + **/ +public class NoFindHandlerException extends RuntimeException { + + private static final long serialVersionUID = 6724478022966267728L; + + public NoFindHandlerException(String message) { + super(message); + } + +} diff --git a/src/main/java/com/github/unclecatmyself/common/exception/NotFindLoginChannlException.java b/src/main/java/com/github/unclecatmyself/common/exception/NotFindLoginChannlException.java new file mode 100644 index 0000000..7670a6c --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/common/exception/NotFindLoginChannlException.java @@ -0,0 +1,14 @@ +package com.github.unclecatmyself.common.exception; + +/** + * 未找到正常注册的连接异常 + * Create by UncleCatMySelf in 13:58 2018\12\30 0030 + */ +public class NotFindLoginChannlException extends RuntimeException { + + private static final long serialVersionUID = -2614068393411382075L; + + public NotFindLoginChannlException(String message) { + super(message); + } +} diff --git a/src/main/java/com/myself/nettychat/common/ip/IpUtils.java b/src/main/java/com/github/unclecatmyself/common/ip/IpUtils.java similarity index 91% rename from src/main/java/com/myself/nettychat/common/ip/IpUtils.java rename to src/main/java/com/github/unclecatmyself/common/ip/IpUtils.java index 4ccfc3d..b06e994 100644 --- a/src/main/java/com/myself/nettychat/common/ip/IpUtils.java +++ b/src/main/java/com/github/unclecatmyself/common/ip/IpUtils.java @@ -1,68 +1,66 @@ -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(); - } - -} +package com.github.unclecatmyself.common.ip; + +import java.net.Inet4Address; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.util.Enumeration; + +/** + * Create by UncleCatMySelf in 2018/12/06 + **/ +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/pool/DefaultThreadFactory.java b/src/main/java/com/github/unclecatmyself/common/pool/DefaultThreadFactory.java similarity index 90% rename from src/main/java/com/myself/nettychat/common/pool/DefaultThreadFactory.java rename to src/main/java/com/github/unclecatmyself/common/pool/DefaultThreadFactory.java index b6c776f..014999d 100644 --- a/src/main/java/com/myself/nettychat/common/pool/DefaultThreadFactory.java +++ b/src/main/java/com/github/unclecatmyself/common/pool/DefaultThreadFactory.java @@ -1,43 +1,41 @@ -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; - } -} +package com.github.unclecatmyself.common.pool; + +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Create by UncleCatMySelf in 2018/12/06 + **/ +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/github/unclecatmyself/common/pool/ExecutorQueue.java similarity index 88% rename from src/main/java/com/myself/nettychat/common/pool/ExecutorQueue.java rename to src/main/java/com/github/unclecatmyself/common/pool/ExecutorQueue.java index 0217bc1..89cde71 100644 --- a/src/main/java/com/myself/nettychat/common/pool/ExecutorQueue.java +++ b/src/main/java/com/github/unclecatmyself/common/pool/ExecutorQueue.java @@ -1,57 +1,56 @@ -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); - } - -} +package com.github.unclecatmyself.common.pool; + +import java.util.concurrent.LinkedTransferQueue; +import java.util.concurrent.RejectedExecutionException; + +/** + * LinkedTransferQueue 能保证更高性能,相比与LinkedBlockingQueue有明显提升 + * 不过LinkedTransferQueue的缺点是没有队列长度控制,需要在外层协助控制 + * Create by UncleCatMySelf in 2018/12/06 + **/ +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/StandardThreadExecutor.java b/src/main/java/com/github/unclecatmyself/common/pool/StandardThreadExecutor.java similarity index 94% rename from src/main/java/com/myself/nettychat/common/pool/StandardThreadExecutor.java rename to src/main/java/com/github/unclecatmyself/common/pool/StandardThreadExecutor.java index 8172d49..6fdab50 100644 --- a/src/main/java/com/myself/nettychat/common/pool/StandardThreadExecutor.java +++ b/src/main/java/com/github/unclecatmyself/common/pool/StandardThreadExecutor.java @@ -1,100 +1,98 @@ -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(); - } -} +package com.github.unclecatmyself.common.pool; + +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Create by UncleCatMySelf in 2018/12/06 + * 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/github/unclecatmyself/common/utils/HttpUtil.java b/src/main/java/com/github/unclecatmyself/common/utils/HttpUtil.java new file mode 100644 index 0000000..f9fd8e9 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/common/utils/HttpUtil.java @@ -0,0 +1,63 @@ +package com.github.unclecatmyself.common.utils; + +import com.alibaba.fastjson.JSONObject; +import com.github.unclecatmyself.common.bean.vo.SendServerVO; +import com.github.unclecatmyself.common.constant.Constans; +import com.github.unclecatmyself.common.constant.HttpConstant; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.util.CharsetUtil; + +import java.io.*; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Map; + +/** + * HTTP接口处理方法 + * Create by UncleCatMySelf in 22:43 2018\12\30 0030 + */ +public class HttpUtil { + + public static String checkType(FullHttpRequest msg){ + msg.retain(); + String url = msg.uri(); + System.out.println(url); + HttpMethod method = msg.method(); + String meName = method.name(); + if (url.equals(HttpConstant.URI_GETSIZE) && meName.equals(HttpConstant.GET)){ + return HttpConstant.GETSIZE; + }else if (url.equals(HttpConstant.URI_SENDFROMSERVER) && meName.equals(HttpConstant.POST)){ + return HttpConstant.SENDFROMSERVER; + }else if (url.equals(HttpConstant.URI_GETLIST) && meName.equals(HttpConstant.GET)){ + return HttpConstant.GETLIST; + }else if (url.equals(HttpConstant.URI_SENDINCHAT) && meName.equals(HttpConstant.POST)){ + return HttpConstant.SENDINCHAT; + }else { + return HttpConstant.NOTFINDURI; + } + } + + public static SendServerVO getToken(FullHttpRequest msg) throws UnsupportedEncodingException { + msg.retain(); + SendServerVO sendServerVO = new SendServerVO(); + String content = msg.content().toString(CharsetUtil.UTF_8); + String[] stars = content.split("&"); + for (int i=0,len=stars.length;i maps){ + InChatMessage message = new InChatMessage(); + if (maps.containsKey(Constans.TOKEN)){ + message.setToken((String) maps.get(Constans.TOKEN)); + } + if (maps.containsKey(Constans.TIME)){ + message.setTime((Date) maps.get(Constans.TIME)); + } + if (maps.containsKey(Constans.VALUE)){ + message.setValue((String)maps.get(Constans.VALUE)); + } + if (maps.containsKey(Constans.TYPE)){ + message.setType((String)maps.get(Constans.TYPE)); + } + if (maps.containsKey(Constans.ONE)){ + message.setOne((String)maps.get(Constans.ONE)); + } + if (maps.containsKey(Constans.GROUPID)){ + message.setGroudId((String)maps.get(Constans.GROUPID)); + } + if (maps.containsKey(Constans.ON_ONLINE)){ + message.setOnline((String)maps.get(Constans.ON_ONLINE)); + } + if (maps.containsKey(Constans.ONLINE_GROUP)){ + message.setOnlineGroup((ArrayList)maps.get(Constans.ONLINE_GROUP)); + } + return message; + } + +} diff --git a/src/main/java/com/github/unclecatmyself/common/utils/RedisUtil.java b/src/main/java/com/github/unclecatmyself/common/utils/RedisUtil.java new file mode 100644 index 0000000..722f3a7 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/common/utils/RedisUtil.java @@ -0,0 +1,69 @@ +package com.github.unclecatmyself.common.utils; + +import java.security.MessageDigest; + +/** + * Create by UncleCatMySelf in 15:13 2019\1\5 0005 + */ +public class RedisUtil { + + private static final String STAL = "InChat"; + + public static String string2MD5(String inStr) { + MessageDigest md5 = null; + try { + md5 = MessageDigest.getInstance("MD5"); + } catch (Exception e) { + System.out.println(e.toString()); + e.printStackTrace(); + return ""; + } + char[] charArray = inStr.toCharArray(); + byte[] byteArray = new byte[charArray.length]; + for (int i = 0; i < charArray.length; i++) byteArray[i] = (byte) charArray[i]; + byte[] md5Bytes = md5.digest(byteArray); + StringBuffer hexValue = new StringBuffer(); + for (int i = 0; i < md5Bytes.length; i++) { + int val = ((int) md5Bytes[i]) & 0xff; + if (val < 16) + hexValue.append("0"); + hexValue.append(Integer.toHexString(val)); + } + return hexValue.toString(); + } + + public static String convertMD5(String address,String token){ + String inStr = address+"&"+token+"%"+STAL; + char[] a = inStr.toCharArray(); + for (int i = 0; i < a.length; i++){ + a[i] = (char) (a[i] ^ 't'); + } + String s = new String(a); + return s; + } + + public static String convertMD5(String inStr){ + char[] a = inStr.toCharArray(); + for (int i = 0; i < a.length; i++){ + a[i] = (char) (a[i] ^ 't'); + } + String s = new String(a); + return s; + } + + public static String getAddress(String s) { + String[] stars = s.split("&"); + return stars[0]; + } + +// public static void main(String[] args) { +// String s = new String("inchat"); +// System.out.println("原始:" + s); +// System.out.println("MD5后:" + string2MD5(s)); +//// System.out.println("原始:" + s); +//// System.out.println("加密后:" + convertMD5(s)); +//// System.out.println("原始:" + s); +//// System.out.println("解密后:" + convertMD5(convertMD5(s))); +// } + +} diff --git a/src/main/java/com/myself/nettychat/common/utils/RemotingUtil.java b/src/main/java/com/github/unclecatmyself/common/utils/RemotingUtil.java similarity index 96% rename from src/main/java/com/myself/nettychat/common/utils/RemotingUtil.java rename to src/main/java/com/github/unclecatmyself/common/utils/RemotingUtil.java index 27ca76c..c2c72b7 100644 --- a/src/main/java/com/myself/nettychat/common/utils/RemotingUtil.java +++ b/src/main/java/com/github/unclecatmyself/common/utils/RemotingUtil.java @@ -1,187 +1,187 @@ -package com.myself.nettychat.common.utils; - -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.lang.reflect.Method; -import java.net.*; -import java.nio.channels.Selector; -import java.nio.channels.SocketChannel; -import java.nio.channels.spi.SelectorProvider; -import java.util.ArrayList; -import java.util.Enumeration; - -public class RemotingUtil { - - public static final String OS_NAME = System.getProperty("os.name"); - - private static final Logger log = LoggerFactory.getLogger(RemotingUtil.class); - private static boolean isLinuxPlatform = false; - private static boolean isWindowsPlatform = false; - - static { - if (OS_NAME != null && OS_NAME.toLowerCase().contains("linux")) { - isLinuxPlatform = true; - } - - if (OS_NAME != null && OS_NAME.toLowerCase().contains("windows")) { - isWindowsPlatform = true; - } - } - - public static boolean isWindowsPlatform() { - return isWindowsPlatform; - } - - public static Selector openSelector() throws IOException { - Selector result = null; - - if (isLinuxPlatform()) { - try { - final Class providerClazz = Class.forName("sun.nio.ch.EPollSelectorProvider"); - if (providerClazz != null) { - try { - final Method method = providerClazz.getMethod("provider"); - if (method != null) { - final SelectorProvider selectorProvider = (SelectorProvider) method.invoke(null); - if (selectorProvider != null) { - result = selectorProvider.openSelector(); - } - } - } catch (final Exception e) { - log.warn("Open ePoll Selector for linux platform exception", e); - } - } - } catch (final Exception e) { - // ignore - } - } - - if (result == null) { - result = Selector.open(); - } - - return result; - } - - public static boolean isLinuxPlatform() { - return isLinuxPlatform; - } - - public static String getLocalAddress() { - try { - // Traversal Network interface to get the first non-loopback and non-private address - Enumeration enumeration = NetworkInterface.getNetworkInterfaces(); - ArrayList ipv4Result = new ArrayList(); - ArrayList ipv6Result = new ArrayList(); - while (enumeration.hasMoreElements()) { - final NetworkInterface networkInterface = enumeration.nextElement(); - final Enumeration en = networkInterface.getInetAddresses(); - while (en.hasMoreElements()) { - final InetAddress address = en.nextElement(); - if (!address.isLoopbackAddress()) { - if (address instanceof Inet6Address) { - ipv6Result.add(normalizeHostAddress(address)); - } else { - ipv4Result.add(normalizeHostAddress(address)); - } - } - } - } - - // prefer ipv4 - if (!ipv4Result.isEmpty()) { - for (String ip : ipv4Result) { - if (ip.startsWith("127.0") || ip.startsWith("192.168")) { - continue; - } - - return ip; - } - - return ipv4Result.get(ipv4Result.size() - 1); - } else if (!ipv6Result.isEmpty()) { - return ipv6Result.get(0); - } - //If failed to find,fall back to localhost - final InetAddress localHost = InetAddress.getLocalHost(); - return normalizeHostAddress(localHost); - } catch (Exception e) { - log.error("Failed to obtain local address", e); - } - - return null; - } - - public static String normalizeHostAddress(final InetAddress localHost) { - if (localHost instanceof Inet6Address) { - return "[" + localHost.getHostAddress() + "]"; - } else { - return localHost.getHostAddress(); - } - } - - public static SocketAddress string2SocketAddress(final String addr) { - String[] s = addr.split(":"); - InetSocketAddress isa = new InetSocketAddress(s[0], Integer.parseInt(s[1])); - return isa; - } - - public static String socketAddress2String(final SocketAddress addr) { - StringBuilder sb = new StringBuilder(); - InetSocketAddress inetSocketAddress = (InetSocketAddress) addr; - sb.append(inetSocketAddress.getAddress().getHostAddress()); - sb.append(":"); - sb.append(inetSocketAddress.getPort()); - return sb.toString(); - } - - public static SocketChannel connect(SocketAddress remote) { - return connect(remote, 1000 * 5); - } - - public static SocketChannel connect(SocketAddress remote, final int timeoutMillis) { - SocketChannel sc = null; - try { - sc = SocketChannel.open(); - sc.configureBlocking(true); - sc.socket().setSoLinger(false, -1); - sc.socket().setTcpNoDelay(true); - sc.socket().setReceiveBufferSize(1024 * 64); - sc.socket().setSendBufferSize(1024 * 64); - sc.socket().connect(remote, timeoutMillis); - sc.configureBlocking(false); - return sc; - } catch (Exception e) { - if (sc != null) { - try { - sc.close(); - } catch (IOException e1) { - e1.printStackTrace(); - } - } - } - - return null; - } - - -} +package com.github.unclecatmyself.common.utils; + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.*; +import java.nio.channels.Selector; +import java.nio.channels.SocketChannel; +import java.nio.channels.spi.SelectorProvider; +import java.util.ArrayList; +import java.util.Enumeration; + +public class RemotingUtil { + + public static final String OS_NAME = System.getProperty("os.name"); + + private static final Logger log = LoggerFactory.getLogger(RemotingUtil.class); + private static boolean isLinuxPlatform = false; + private static boolean isWindowsPlatform = false; + + static { + if (OS_NAME != null && OS_NAME.toLowerCase().contains("linux")) { + isLinuxPlatform = true; + } + + if (OS_NAME != null && OS_NAME.toLowerCase().contains("windows")) { + isWindowsPlatform = true; + } + } + + public static boolean isWindowsPlatform() { + return isWindowsPlatform; + } + + public static Selector openSelector() throws IOException { + Selector result = null; + + if (isLinuxPlatform()) { + try { + final Class providerClazz = Class.forName("sun.nio.ch.EPollSelectorProvider"); + if (providerClazz != null) { + try { + final Method method = providerClazz.getMethod("provider"); + if (method != null) { + final SelectorProvider selectorProvider = (SelectorProvider) method.invoke(null); + if (selectorProvider != null) { + result = selectorProvider.openSelector(); + } + } + } catch (final Exception e) { + log.warn("Open ePoll Selector for linux platform exception", e); + } + } + } catch (final Exception e) { + // ignore + } + } + + if (result == null) { + result = Selector.open(); + } + + return result; + } + + public static boolean isLinuxPlatform() { + return isLinuxPlatform; + } + + public static String getLocalAddress() { + try { + // Traversal Network interface to get the first non-loopback and non-private address + Enumeration enumeration = NetworkInterface.getNetworkInterfaces(); + ArrayList ipv4Result = new ArrayList(); + ArrayList ipv6Result = new ArrayList(); + while (enumeration.hasMoreElements()) { + final NetworkInterface networkInterface = enumeration.nextElement(); + final Enumeration en = networkInterface.getInetAddresses(); + while (en.hasMoreElements()) { + final InetAddress address = en.nextElement(); + if (!address.isLoopbackAddress()) { + if (address instanceof Inet6Address) { + ipv6Result.add(normalizeHostAddress(address)); + } else { + ipv4Result.add(normalizeHostAddress(address)); + } + } + } + } + + // prefer ipv4 + if (!ipv4Result.isEmpty()) { + for (String ip : ipv4Result) { + if (ip.startsWith("127.0") || ip.startsWith("192.168")) { + continue; + } + + return ip; + } + + return ipv4Result.get(ipv4Result.size() - 1); + } else if (!ipv6Result.isEmpty()) { + return ipv6Result.get(0); + } + //If failed to find,fall back to localhost + final InetAddress localHost = InetAddress.getLocalHost(); + return normalizeHostAddress(localHost); + } catch (Exception e) { + log.error("Failed to obtain local address", e); + } + + return null; + } + + public static String normalizeHostAddress(final InetAddress localHost) { + if (localHost instanceof Inet6Address) { + return "[" + localHost.getHostAddress() + "]"; + } else { + return localHost.getHostAddress(); + } + } + + public static SocketAddress string2SocketAddress(final String addr) { + String[] s = addr.split(":"); + InetSocketAddress isa = new InetSocketAddress(s[0], Integer.parseInt(s[1])); + return isa; + } + + public static String socketAddress2String(final SocketAddress addr) { + StringBuilder sb = new StringBuilder(); + InetSocketAddress inetSocketAddress = (InetSocketAddress) addr; + sb.append(inetSocketAddress.getAddress().getHostAddress()); + sb.append(":"); + sb.append(inetSocketAddress.getPort()); + return sb.toString(); + } + + public static SocketChannel connect(SocketAddress remote) { + return connect(remote, 1000 * 5); + } + + public static SocketChannel connect(SocketAddress remote, final int timeoutMillis) { + SocketChannel sc = null; + try { + sc = SocketChannel.open(); + sc.configureBlocking(true); + sc.socket().setSoLinger(false, -1); + sc.socket().setTcpNoDelay(true); + sc.socket().setReceiveBufferSize(1024 * 64); + sc.socket().setSendBufferSize(1024 * 64); + sc.socket().connect(remote, timeoutMillis); + sc.configureBlocking(false); + return sc; + } catch (Exception e) { + if (sc != null) { + try { + sc.close(); + } catch (IOException e1) { + e1.printStackTrace(); + } + } + } + + return null; + } + + +} diff --git a/src/main/java/com/github/unclecatmyself/task/DataAsynchronousTask.java b/src/main/java/com/github/unclecatmyself/task/DataAsynchronousTask.java new file mode 100644 index 0000000..7714d5e --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/task/DataAsynchronousTask.java @@ -0,0 +1,52 @@ +package com.github.unclecatmyself.task; + +import com.github.unclecatmyself.bootstrap.data.InChatToDataBaseService; +import com.github.unclecatmyself.common.constant.LogConstant; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.FutureTask; + +/** + * 数据异步转移方法 + * Created by MySelf on 2018/12/3. + */ +public class DataAsynchronousTask { + + private final Logger log = LoggerFactory.getLogger(DataAsynchronousTask.class); + + /** 用户读数据接口伪实现 */ + private final InChatToDataBaseService inChatToDataBaseService; + + + public DataAsynchronousTask(InChatToDataBaseService inChatToDataBaseService){ + this.inChatToDataBaseService = inChatToDataBaseService; + } + + /** + * 将Netty数据消息借助这个方法已新线程发送给用户实现读方法 + * @param maps {@link Map} 传递消息 + */ + public void writeData(Map maps){ + Boolean result = false; + ExecutorService service = Executors.newCachedThreadPool(); + final FutureTask future = new FutureTask(new DataCallable(inChatToDataBaseService,maps)); + service.execute(future); + try { + result = future.get(); + } catch (InterruptedException e) { + e.printStackTrace(); + log.error(LogConstant.DATAASYNCHRONOUSTASK_01); + } catch (ExecutionException e) { + log.error(LogConstant.DATAASYNCHRONOUSTASK_02); + } + if (!result){ + log.error(LogConstant.DATAASYNCHRONOUSTASK_03); + } + } + +} diff --git a/src/main/java/com/github/unclecatmyself/task/DataCallable.java b/src/main/java/com/github/unclecatmyself/task/DataCallable.java new file mode 100644 index 0000000..902b71b --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/task/DataCallable.java @@ -0,0 +1,30 @@ +package com.github.unclecatmyself.task; + +import com.github.unclecatmyself.bootstrap.data.InChatToDataBaseService; +import com.github.unclecatmyself.common.utils.MessageChangeUtil; + +import java.util.Map; +import java.util.concurrent.Callable; + +/** + * 获取结果的异步线程任务 + * Create by UncleCatMySelf in 11:25 2018\12\30 0030 + */ +public class DataCallable implements Callable{ + + /** 用户读数据接口伪实现 */ + private final InChatToDataBaseService inChatToDataBaseService; + /** 消息数据 */ + private final Map maps; + + DataCallable(InChatToDataBaseService inChatToDataBaseService,Map maps) { + this.inChatToDataBaseService = inChatToDataBaseService; + this.maps = maps; + } + + @Override + public Boolean call() throws Exception { + inChatToDataBaseService.writeMessage(MessageChangeUtil.Change(maps)); + return true; + } +} diff --git a/src/main/java/com/github/unclecatmyself/user/DataBaseServiceImpl.java b/src/main/java/com/github/unclecatmyself/user/DataBaseServiceImpl.java new file mode 100644 index 0000000..781bb42 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/user/DataBaseServiceImpl.java @@ -0,0 +1,15 @@ +package com.github.unclecatmyself.user; + +import com.github.unclecatmyself.bootstrap.data.InChatToDataBaseService; +import com.github.unclecatmyself.common.bean.InChatMessage; + +/** + * Created by MySelf on 2019/1/3. + */ +public class DataBaseServiceImpl implements InChatToDataBaseService { + //获取消息 + public Boolean writeMessage(InChatMessage inChatMessage) { + System.out.println(inChatMessage.toString()); + return true; + } +} diff --git a/src/main/java/com/github/unclecatmyself/user/FromServerServiceImpl.java b/src/main/java/com/github/unclecatmyself/user/FromServerServiceImpl.java new file mode 100644 index 0000000..d9b4aed --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/user/FromServerServiceImpl.java @@ -0,0 +1,49 @@ +package com.github.unclecatmyself.user; + +import com.github.unclecatmyself.bootstrap.channel.http.FromServerService; + +/** + * Created by MySelf on 2019/1/3. + */ +public enum FromServerServiceImpl implements FromServerService { + + TYPE1(1,"【系统通知】您的账号存在异常,请注意安全保密信息。"), + TYPE2(2,"【系统通知】恭喜您连续登录超过5天,奖励5积分。"); + + private Integer code; + + private String message; + + FromServerServiceImpl(Integer code, String message){ + this.code = code; + this.message = message; + } + + public Integer getCode() { + return code; + } + + public String findByCode(Object code) { + Integer codes = (Integer)code; + for (FromServerServiceImpl item: FromServerServiceImpl.values()) { + if (item.code == codes){ + return item.message; + } + } + return null; + } + + public void setCode(Integer code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + +} diff --git a/src/main/java/com/github/unclecatmyself/user/MyInit.java b/src/main/java/com/github/unclecatmyself/user/MyInit.java new file mode 100644 index 0000000..0009ad8 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/user/MyInit.java @@ -0,0 +1,19 @@ +package com.github.unclecatmyself.user; + +import com.github.unclecatmyself.common.bean.InitNetty; + +/** + * Created by MySelf on 2019/1/3. + */ +public class MyInit extends InitNetty { + + @Override + public int getWebport() { + return 8070; + } + + @Override + public Boolean getDistributed() { + return true; + } +} diff --git a/src/main/java/com/github/unclecatmyself/user/VerifyServiceImpl.java b/src/main/java/com/github/unclecatmyself/user/VerifyServiceImpl.java new file mode 100644 index 0000000..f0fa0c3 --- /dev/null +++ b/src/main/java/com/github/unclecatmyself/user/VerifyServiceImpl.java @@ -0,0 +1,21 @@ +package com.github.unclecatmyself.user; + +import com.alibaba.fastjson.JSONArray; +import com.github.unclecatmyself.bootstrap.verify.InChatVerifyService; + +/** + * Created by MySelf on 2019/1/3. + */ +public class VerifyServiceImpl implements InChatVerifyService { + + + public boolean verifyToken(String token) { + return true; + } + + + public JSONArray getArrayByGroupId(String groupId) { + JSONArray jsonArray = JSONArray.parseArray("[\"1111\",\"2222\",\"3333\"]"); + return jsonArray; + } +} 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 deleted file mode 100644 index 9c679bd..0000000 --- a/src/main/java/com/myself/nettychat/NettychatApplication.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.myself.nettychat; - -import com.myself.nettychat.config.NettyConfig; -import com.myself.nettychat.config.NettyTcpConfig; -import com.myself.nettychat.config.TCPServer; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.EnableAspectJAutoProxy; -import org.springframework.scheduling.annotation.EnableScheduling; -import springfox.documentation.swagger2.annotations.EnableSwagger2; - -@SpringBootApplication -@EnableScheduling //定时任务支持 -@EnableAspectJAutoProxy //注解开启对aspectJ的支持 -@EnableSwagger2 //Swagger自动生成文档 -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); - TCPServer tcpServer = context.getBean(TCPServer.class); - new Thread(new Runnable() { - @Override - public void run() { - try { - System.out.println("Web端Netty通信服务端启动成功!端口:8090"); - tcpServer.startWeb(); - }catch (Exception e){ - e.printStackTrace(); - } - } - }).start(); - new Thread(new Runnable() { - @Override - public void run() { - try { - System.out.println("TCP端Netty通信服务端启动成功!端口:8092"); - tcpServer.startTcp(); - }catch (Exception e){ - e.printStackTrace(); - } - } - }).start(); - } - -} 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 50d4513..0000000 --- a/src/main/java/com/myself/nettychat/auto/ServerAutoConfigure.java +++ /dev/null @@ -1,83 +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.getWebport(),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); - } - 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/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/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/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/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/properties/InitNetty.java b/src/main/java/com/myself/nettychat/common/properties/InitNetty.java deleted file mode 100644 index ad88014..0000000 --- a/src/main/java/com/myself/nettychat/common/properties/InitNetty.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.myself.nettychat.common.properties; - -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 - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 10:54 2018\8\14 0014 - */ -@Data -@ConfigurationProperties(prefix = "netty") -public class InitNetty { - - private int webport; - - private int bossThread; - - private int workerThread; - - private boolean keepalive; - - private int backlog; - - private int sndbuf; - - private int revbuf; - - private int heart; - - private int period; - - private String serverName; - - private int initalDelay; - -} 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/ByteBufUtil.java b/src/main/java/com/myself/nettychat/common/utils/ByteBufUtil.java deleted file mode 100644 index ae5cc58..0000000 --- a/src/main/java/com/myself/nettychat/common/utils/ByteBufUtil.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.myself.nettychat.common.utils; - - -import io.netty.buffer.ByteBuf; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 跨线程情况下 byteBuf 需要转换成byte[] - **/ -public class ByteBufUtil { - - public static byte[] copyByteBuf(ByteBuf byteBuf){ - byte[] bytes = new byte[byteBuf.readableBytes()]; - byteBuf.readBytes(bytes); - return bytes; - } - -} diff --git a/src/main/java/com/myself/nettychat/common/utils/CRC16MySelf.java b/src/main/java/com/myself/nettychat/common/utils/CRC16MySelf.java deleted file mode 100644 index f9f9eaa..0000000 --- a/src/main/java/com/myself/nettychat/common/utils/CRC16MySelf.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.myself.nettychat.common.utils; - -import java.math.BigInteger; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 19:31 2018\9\20 0020 - */ -public class CRC16MySelf { - - /** - * 生成指定格式的传输数据 - * @param ChannelId - * @param type - * @param data - * @return - */ - public static String getAllString(String ChannelId,String type,String data){ - String test = ChannelId + type + data; - String crcString = getCRC(test.getBytes()); - String result = Const.HEAD + test + crcString + Const.TAIL; - return result; - } - - /** - * 计算CRC16校验码 - * - * @param bytes 字节数组 - * @return {@link String} 校验码 - * @since 1.0 - */ - public static String getCRC(byte[] bytes) { - int CRC = 0x0000ffff; - int POLYNOMIAL = 0x0000a001; - int i, j; - for (i = 0; i < bytes.length; i++) { - CRC ^= ((int) bytes[i] & 0x000000ff); - for (j = 0; j < 8; j++) { - if ((CRC & 0x00000001) != 0) { - CRC >>= 1; - CRC ^= POLYNOMIAL; - } else { - CRC >>= 1; - } - } - } - return Integer.toHexString(CRC); - } - - /** - * 将16进制单精度浮点型转换为10进制浮点型 - * - * @return float - * @since 1.0 - */ - private float parseHex2Float(String hexStr) { - BigInteger bigInteger = new BigInteger(hexStr, 16); - return Float.intBitsToFloat(bigInteger.intValue()); - } - - /** - * 将十进制浮点型转换为十六进制浮点型 - * - * @return String - * @since 1.0 - */ - private String parseFloat2Hex(float data) { - return Integer.toHexString(Float.floatToIntBits(data)); - } - -} diff --git a/src/main/java/com/myself/nettychat/common/utils/CallBackMessage.java b/src/main/java/com/myself/nettychat/common/utils/CallBackMessage.java deleted file mode 100644 index b3a773c..0000000 --- a/src/main/java/com/myself/nettychat/common/utils/CallBackMessage.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.myself.nettychat.common.utils; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; - -import java.nio.charset.Charset; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 19:30 2018\9\20 0020 - */ -public class CallBackMessage { - - public static final ByteBuf SUCCESS = Unpooled.unreleasableBuffer( - Unpooled.copiedBuffer("success", Charset.forName("UTF-8"))); - - public static final ByteBuf ERROR = Unpooled.unreleasableBuffer( - Unpooled.copiedBuffer("error", Charset.forName("UTF-8"))); - - public static final ByteBuf Check1_test = Unpooled.unreleasableBuffer( - Unpooled.copiedBuffer("Check1\r", Charset.forName("UTF-8"))); - - public static final ByteBuf Check2 = Unpooled.unreleasableBuffer( - Unpooled.copiedBuffer("Check2", Charset.forName("UTF-8"))); - - - public static ByteBuf sendString(String send){ - return Unpooled.unreleasableBuffer( - Unpooled.copiedBuffer(send, Charset.forName("UTF-8"))); - } - - -} diff --git a/src/main/java/com/myself/nettychat/common/utils/Const.java b/src/main/java/com/myself/nettychat/common/utils/Const.java deleted file mode 100644 index 63189b7..0000000 --- a/src/main/java/com/myself/nettychat/common/utils/Const.java +++ /dev/null @@ -1,181 +0,0 @@ -package com.myself.nettychat.common.utils; - -import io.netty.channel.Channel; - -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 19:30 2018\9\20 0020 - */ -public class Const { - - //帧头 - public static final String HEAD = "gz"; - //帧尾 - public static final String TAIL = "xr"; - //控制锁状态 - public static final String CONTROL_TYPE = "s"; - //24锁 全部关闭状态 - public static final String LOCKS = "nnnnnnnnnnnnnnnnnnnnnnnn"; - //开锁标识 - public static final char OPEN = 'y'; - //客户端执行结果 - public static final String RESULT_TYPE = "j"; - //客户端执行测试结果 - public static final String RESULT_TEXT = "t"; - //服务器执行结果 - public static final String SUCCESS = "yyyyyyyyyyyyyyyyyyyyyyyy"; - public static final String ERROR = "nnnnnnnnnnnnnnnnnnnnnnnn"; - - private static Map map = new ConcurrentHashMap(); - - /** - * Netty连接池添加连接 - * @param clientId 连接ID - * @param channel 连接实例 - */ - public static void add(String clientId,Channel channel){ - SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - System.out.println("add ChannelId: " + clientId + " " + formatter.format(new Date())); - map.put(clientId,channel); - } - - /** - * 判断是否存在该连接ID实例 - * @param channelID 连接Id - * @return - */ - public static boolean hasChannelID(String channelID){ - boolean state = map.containsKey(channelID); - return state; - } - - /** - * 根据连接ID 获取连接实例 - * @param clientId 链接Id - * @return - */ - public static Channel get(String clientId){ - return map.get(clientId); - } - - /** - * 根据链接实例移除链接实例 - * @param channel 链接实例 - */ - public static void remove(Channel channel){ - for (Map.Entry entry:map.entrySet()){ - if (entry.getValue()==channel){ - map.remove(entry.getKey()); - } - } - } - - /** - * 获取链接数组个数 - * @return - */ - public static int getSzie(){ - return map.size(); - } - - /** - * 获取链接数组Id - * @return - */ - public static Set getIdList(){ - return map.keySet(); - } - - /** - * 获取连接池数据信息 - */ - public static void mapInfo(){ - System.out.println("channel size : " + map.size()); - for (Map.Entry entry:map.entrySet()){ - System.out.println("clientId: " + entry.getKey()); - } - } - - /** - * 链接实例是否存在链接池中 - * @param channel 链接实例 - * @return 链接Id - */ - public static String isChannel(Channel channel){ - String clientId = null; - for (Map.Entry entry:map.entrySet()){ - if (entry.getValue() == channel){ - clientId = (String) entry.getKey(); - } - } - return clientId; - } - - /** - * 更新链接实例Id - * @param clientId 原始ID - * @param newID 新的连接ID - */ - public static void ChangeClientId(String clientId,String newID){ - for (Map.Entry entry:map.entrySet()){ - if (entry.getKey()==clientId){ - Channel channel = (Channel) entry.getValue(); - map.remove(entry.getKey()); - map.put(newID,channel); - } - } - } - - public static void changeChannel(String channelID, Channel channel) { - map.remove(channelID); - map.put(channelID,channel); - } - - public enum StateEnum{ - SUCCESS(1,"ok"), - FALID(2,"no"); - private int state; - - private String stateInfo; - - StateEnum(int state, String stateInfo) { - this.state = state; - this.stateInfo = stateInfo; - } - - public int getState() { - return state; - } - - public void setState(int state) { - this.state = state; - } - - public String getStateInfo() { - return stateInfo; - } - - public void setStateInfo(String stateInfo) { - this.stateInfo = stateInfo; - } - - public static StateEnum stateOf(int index){ - for (StateEnum item:values()){ - if (item.getState() == index){ - return item; - } - } - return null; - } - } - - -} diff --git a/src/main/java/com/myself/nettychat/common/utils/CookieUtil.java b/src/main/java/com/myself/nettychat/common/utils/CookieUtil.java deleted file mode 100644 index 8bf761a..0000000 --- a/src/main/java/com/myself/nettychat/common/utils/CookieUtil.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.myself.nettychat.common.utils; - -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.HashMap; -import java.util.Map; - -/** - * cookie工具类 - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 12:06 2018\6\13 0013 - */ -public class CookieUtil { - /** - * 设置cookie - * @param response - * @param name - * @param value - * @param maxAge - */ - public static void set(HttpServletResponse response, - String name, - String value, - int maxAge){ - Cookie cookie = new Cookie(name,value); - cookie.setPath("/"); - cookie.setMaxAge(maxAge); - response.addCookie(cookie); - } - - /** - * 获取cookie - * @param request - * @param name - * @return - */ - public static Cookie get(HttpServletRequest request, - String name){ - Map cookieMap = readCookieMap(request); - if (cookieMap.containsKey(name)){ - return cookieMap.get(name); - }else{ - return null; - } - } - - /** - * 将cookie封装成Map - * @param request - * @return - */ - private static Map readCookieMap(HttpServletRequest request){ - Map cookieMap = new HashMap<>(); - Cookie[] cookies = request.getCookies(); - if (cookies != null){ - for (Cookie cookie:cookies){ - cookieMap.put(cookie.getName(),cookie); - } - } - return cookieMap; - } -} diff --git a/src/main/java/com/myself/nettychat/common/utils/DataResction.java b/src/main/java/com/myself/nettychat/common/utils/DataResction.java deleted file mode 100644 index 8d6a30f..0000000 --- a/src/main/java/com/myself/nettychat/common/utils/DataResction.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.myself.nettychat.common.utils; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 19:32 2018\9\20 0020 - */ -public class DataResction { - - /** - * 切除符合协议的帧头帧尾 - * @param data 原始通信数据 - * @return - */ - public static String ResctionHeadAndFeet(String data){ - return data.substring(2,data.length()-2); - } - - /** - * 切除符合协议的帧头帧尾————本地测试方法 - * @param data - * @return - */ - public static String ResctionHeadAndFeet_test(String data){ - return data.substring(2,data.length()-4); - } - - /** - * 返回通信CRC校验码 - * @param data - * @return - */ - public static String ResctionCRCCode(String data){ - return data.substring(39,data.length()); - } - - /** - * 返回通信内容,除去CRC校验码 - * @param data - * @return - */ - public static String ResctionData(String data){ - return data.substring(0,39); - } - - public static String ResctionDataNoID(String data){ - return data.substring(14); - } - - /** - * 返回设备唯一ID - * @param data - * @return - */ - public static String ResctionID(String data){ - return data.substring(0,14); - } - - /** - * 返回数据类型 - * @param data - * @return - */ - public static String ResctionType(String data){ - return data.substring(0,1); - } - - /** - * 返回实际内容值 - * @param data - * @return - */ - public static String ResctionRealData(String data){ - return data.substring(1); - } - - /** - * 截取电量信息,并返回 - * @param data - * @return - */ - public static String ResctionPower(String data){ - return data.substring(0,4); - } - - /** - * 截取纬度信息,并返回 - * @param data - * @return - */ - public static String ResctionLatitude(String data){ - return data.substring(3,11); - } - - /** - * 截取经度信息,并返回 - * @param data - * @return - */ - public static String ResctionLongitude(String data){ - return data.substring(14,data.length()); - } - - -} diff --git a/src/main/java/com/myself/nettychat/common/utils/DataValida.java b/src/main/java/com/myself/nettychat/common/utils/DataValida.java deleted file mode 100644 index 5d0c882..0000000 --- a/src/main/java/com/myself/nettychat/common/utils/DataValida.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.myself.nettychat.common.utils; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 19:32 2018\9\20 0020 - */ -public class DataValida { - - /** - * 校验数据帧头帧尾是否符合协议规范 - * @param data 通信原始数据 - * @return - */ - public static boolean ValidateHeadAndFeet(String data){ - boolean state = false; - if (Const.HEAD.equals(data.substring(0,2)) && Const.TAIL.equals(data.substring(data.length()-2,data.length()))){ - return true; - } - return state; - } - - /** - * 校验数据帧头是否符合协议数据规范————本地测试 - * @param data - * @return - */ - public static boolean ValidateHeadAndFeet_test(String data){ - boolean state = false; - if (Const.HEAD.equals(data.substring(0,2)) && Const.TAIL.equals(data.substring(data.length()-4,data.length()-2))){ - return true; - } - return state; - } - - /** - * CRC16校验 - * @param data 内容数据 - * @param crcCode 附带CRC校验码 - * @return - */ - public static boolean ValidateCRCCode(String data,String crcCode){ - boolean state = false; - if (crcCode.equals(CRC16MySelf.getCRC(data.getBytes()))){ - return true; - } - return state; - } - -} diff --git a/src/main/java/com/myself/nettychat/common/utils/IdWorker.java b/src/main/java/com/myself/nettychat/common/utils/IdWorker.java deleted file mode 100644 index 8e45b4f..0000000 --- a/src/main/java/com/myself/nettychat/common/utils/IdWorker.java +++ /dev/null @@ -1,150 +0,0 @@ -package com.myself.nettychat.common.utils; - -import java.lang.management.ManagementFactory; -import java.net.InetAddress; -import java.net.NetworkInterface; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 全局id生成器 - **/ -public class IdWorker { - - // 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动) - private final static long twepoch = 1288834974657L; - // 机器标识位数 - private final static long workerIdBits = 5L; - // 数据中心标识位数 - private final static long datacenterIdBits = 5L; - // 机器ID最大值 - private final static long maxWorkerId = -1L ^ (-1L << workerIdBits); - // 数据中心ID最大值 - private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); - // 毫秒内自增位 - private final static long sequenceBits = 12L; - // 机器ID偏左移12位 - private final static long workerIdShift = sequenceBits; - // 数据中心ID左移17位 - private final static long datacenterIdShift = sequenceBits + workerIdBits; - // 时间毫秒左移22位 - private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; - - private final static long sequenceMask = -1L ^ (-1L << sequenceBits); - /* 上次生产id时间戳 */ - private static long lastTimestamp = -1L; - // 0,并发控制 - private long sequence = 0L; - - private final long workerId; - // 数据标识id部分 - private final long datacenterId; - - public IdWorker(){ - this.datacenterId = getDatacenterId(maxDatacenterId); - this.workerId = getMaxWorkerId(datacenterId, maxWorkerId); - } - /** - * @param workerId - * 工作机器ID - * @param datacenterId - * 序列号 - */ - public IdWorker(long workerId, long datacenterId) { - if (workerId > maxWorkerId || workerId < 0) { - throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); - } - if (datacenterId > maxDatacenterId || datacenterId < 0) { - throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); - } - this.workerId = workerId; - this.datacenterId = datacenterId; - } - /** - * 获取下一个ID - * - * @return - */ - public synchronized long nextId() { - long timestamp = timeGen(); - if (timestamp < lastTimestamp) { - throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); - } - - if (lastTimestamp == timestamp) { - // 当前毫秒内,则+1 - sequence = (sequence + 1) & sequenceMask; - if (sequence == 0) { - // 当前毫秒内计数满了,则等待下一秒 - timestamp = tilNextMillis(lastTimestamp); - } - } else { - sequence = 0L; - } - lastTimestamp = timestamp; - // ID偏移组合生成最终的ID,并返回ID - long nextId = ((timestamp - twepoch) << timestampLeftShift) - | (datacenterId << datacenterIdShift) - | (workerId << workerIdShift) | sequence; - - return nextId; - } - - private long tilNextMillis(final long lastTimestamp) { - long timestamp = this.timeGen(); - while (timestamp <= lastTimestamp) { - timestamp = this.timeGen(); - } - return timestamp; - } - - private long timeGen() { - return System.currentTimeMillis(); - } - - /** - *

- * 获取 maxWorkerId - *

- */ - protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) { - StringBuffer mpid = new StringBuffer(); - mpid.append(datacenterId); - String name = ManagementFactory.getRuntimeMXBean().getName(); - if (!name.isEmpty()) { - /* - * GET jvmPid - */ - mpid.append(name.split("@")[0]); - } - /* - * MAC + PID 的 hashcode 获取16个低位 - */ - return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1); - } - - /** - *

- * 数据标识id部分 - *

- */ - protected static long getDatacenterId(long maxDatacenterId) { - long id = 0L; - try { - InetAddress ip = InetAddress.getLocalHost(); - NetworkInterface network = NetworkInterface.getByInetAddress(ip); - if (network == null) { - id = 1L; - } else { - byte[] mac = network.getHardwareAddress(); - id = ((0x000000FF & (long) mac[mac.length - 1]) - | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6; - id = id % (maxDatacenterId + 1); - } - } catch (Exception e) { - System.out.println(" getDatacenterId: " + e.getMessage()); - } - return id; - } - -} diff --git a/src/main/java/com/myself/nettychat/common/utils/MessageId.java b/src/main/java/com/myself/nettychat/common/utils/MessageId.java deleted file mode 100644 index a6b21f8..0000000 --- a/src/main/java/com/myself/nettychat/common/utils/MessageId.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.myself.nettychat.common.utils; - -import java.util.concurrent.atomic.AtomicInteger; - -/** - * @author MySelf - * @create 2018/9/22 - * @desc 生成messageId - **/ -public class MessageId { - - private static AtomicInteger index = new AtomicInteger(1); - /** - * 获取messageId - * @return id - */ - public static int messageId(){ - for (;;) { - int current = index.get(); - int next = (current >= Integer.MAX_VALUE ? 0: current + 1); - if (index.compareAndSet(current, next)) { - return current; - } - } - } - -} diff --git a/src/main/java/com/myself/nettychat/common/utils/RandomNameUtil.java b/src/main/java/com/myself/nettychat/common/utils/RandomNameUtil.java deleted file mode 100644 index f9e2b19..0000000 --- a/src/main/java/com/myself/nettychat/common/utils/RandomNameUtil.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.myself.nettychat.common.utils; - -import java.util.Random; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 11:48 2018\8\14 0014 - */ -public class RandomNameUtil { - - private static Random ran = new Random(); - private final static int delta = 0x9fa5 - 0x4e00 + 1; - - public static char getName(){ - return (char)(0x4e00 + ran.nextInt(delta)); - } - -} diff --git a/src/main/java/com/myself/nettychat/common/utils/ResultVOUtil.java b/src/main/java/com/myself/nettychat/common/utils/ResultVOUtil.java deleted file mode 100644 index b2b678d..0000000 --- a/src/main/java/com/myself/nettychat/common/utils/ResultVOUtil.java +++ /dev/null @@ -1,30 +0,0 @@ -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 deleted file mode 100644 index c902996..0000000 --- a/src/main/java/com/myself/nettychat/common/utils/SendUtil.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.myself.nettychat.common.utils; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; -import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; - -import java.nio.charset.Charset; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 19:32 2018\9\20 0020 - */ -public class SendUtil { - - public boolean send(Integer item, Channel channel, String channelID, String type){ - try { - if (item != null && channel != null){ - String items = IntegerToString(item); - String result = CRC16MySelf.getAllString(channelID,type,items); - 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; - } - - /** - * 广播发送事件 - * @param items - * @param channel - * @param channelID - * @param type - * @return - */ - public void sendAll(String items, Channel channel, String channelID, String type){ - try { - if (items != null && channel != null){ - String result = CRC16MySelf.getAllString(channelID,type,items); - ByteBuf msg = Unpooled.unreleasableBuffer( - Unpooled.copiedBuffer(result, Charset.forName("UTF-8"))); - channel.writeAndFlush(msg.duplicate()); - } - }catch (Exception e){ - e.printStackTrace(); - System.out.println(e.getMessage()); - } - } - - public String IntegerToString(Integer item){ - char[] locks_char = Const.LOCKS.toCharArray(); - for (int i=0;i T getBean(Class clazz){ - return getApplicationContext().getBean(clazz); - } - - //通过name,以及Clazz返回指定的Bean - public static T getBean(String name,Class clazz){ - return getApplicationContext().getBean(name, clazz); - } - -} diff --git a/src/main/java/com/myself/nettychat/common/utils/StringUtil.java b/src/main/java/com/myself/nettychat/common/utils/StringUtil.java deleted file mode 100644 index bd4741d..0000000 --- a/src/main/java/com/myself/nettychat/common/utils/StringUtil.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.myself.nettychat.common.utils; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 15:55 2018\8\20 0020 - */ -public class StringUtil { - - public static String getName(String str){ - int nameIndex = str.indexOf("-"); - return str.substring(0,nameIndex); - } - - - public static String getMsg(String str){ - int nameIndex = str.indexOf("-"); - return str.substring(nameIndex + 1,str.length()); - } -} 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/NettyConfig.java b/src/main/java/com/myself/nettychat/config/NettyConfig.java deleted file mode 100644 index 2648087..0000000 --- a/src/main/java/com/myself/nettychat/config/NettyConfig.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.myself.nettychat.config; - -import com.myself.nettychat.common.properties.InitNetty; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.ChannelOption; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import io.netty.handler.logging.LogLevel; -import io.netty.handler.logging.LoggingHandler; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.context.annotation.Bean; -import org.springframework.stereotype.Component; - -import java.net.InetSocketAddress; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 11:00 2018\8\14 0014 - */ -@Component -public class NettyConfig { - - @Autowired - private InitNetty nettyAccountConfig; - - @Bean(name = "bossGroup", destroyMethod = "shutdownGracefully") - public NioEventLoopGroup bossGroup(){ - return new NioEventLoopGroup(nettyAccountConfig.getBossThread()); - } - - @Bean(name = "workerGroup", destroyMethod = "shutdownGracefully") - public NioEventLoopGroup workerGroup(){ - return new NioEventLoopGroup(nettyAccountConfig.getWorkerThread()); - } - - @Bean(name = "webSocketAddress") - public InetSocketAddress tcpPost(){ - return new InetSocketAddress(nettyAccountConfig.getWebport()); - } - - @Bean(name = "tcpChannelOptions") - public Map, Object> tcpChannelOptions(){ - Map, Object> options = new HashMap, Object>(); - options.put(ChannelOption.TCP_NODELAY,nettyAccountConfig.isNodelay()); - options.put(ChannelOption.SO_KEEPALIVE, nettyAccountConfig.isKeepalive()); - options.put(ChannelOption.SO_BACKLOG, nettyAccountConfig.getBacklog()); - options.put(ChannelOption.SO_REUSEADDR,nettyAccountConfig.isReuseaddr()); - return options; - } - - @Autowired - @Qualifier("somethingChannelInitializer") - private NettyWebSocketChannelInitializer nettyWebSocketChannelInitializer; - - @Bean(name = "serverBootstrap") - public ServerBootstrap bootstrap(){ - ServerBootstrap b = new ServerBootstrap(); - b.group(bossGroup(), workerGroup()) - .channel(NioServerSocketChannel.class) - .handler(new LoggingHandler(LogLevel.DEBUG)) - .childHandler(nettyWebSocketChannelInitializer); - Map, Object> tcpChannelOptions = tcpChannelOptions(); - Set> keySet = tcpChannelOptions.keySet(); - for (@SuppressWarnings("rawtypes") ChannelOption option : keySet) { - b.option(option, tcpChannelOptions.get(option)); - } - return b; - } -} diff --git a/src/main/java/com/myself/nettychat/config/NettyTcpChannelInitializer.java b/src/main/java/com/myself/nettychat/config/NettyTcpChannelInitializer.java deleted file mode 100644 index ceb8ed9..0000000 --- a/src/main/java/com/myself/nettychat/config/NettyTcpChannelInitializer.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.myself.nettychat.config; - -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.SocketChannel; -import io.netty.handler.codec.LineBasedFrameDecoder; -import io.netty.handler.codec.string.StringDecoder; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.stereotype.Component; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 19:26 2018\9\20 0020 - */ -@Component -@Qualifier("tcpChannelInitializer") -public class NettyTcpChannelInitializer extends ChannelInitializer { - - @Autowired - @Qualifier("tcpServerHandler") - private TCPServerHandler tcpServerHandler; - - @Override - public void initChannel(SocketChannel ch) throws Exception { - ChannelPipeline pipeline = ch.pipeline(); - pipeline.addLast(new LineBasedFrameDecoder(1024)); - pipeline.addLast(new StringDecoder()); - pipeline.addLast(tcpServerHandler); - } - -} \ No newline at end of file diff --git a/src/main/java/com/myself/nettychat/config/NettyTcpConfig.java b/src/main/java/com/myself/nettychat/config/NettyTcpConfig.java deleted file mode 100644 index f6ce2d2..0000000 --- a/src/main/java/com/myself/nettychat/config/NettyTcpConfig.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.myself.nettychat.config; - -import com.myself.nettychat.common.properties.InitNetty; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.ChannelOption; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import io.netty.handler.logging.LogLevel; -import io.netty.handler.logging.LoggingHandler; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.context.annotation.Bean; -import org.springframework.stereotype.Component; - -import java.net.InetSocketAddress; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 19:27 2018\9\20 0020 - */ -@Component -public class NettyTcpConfig { - - @Autowired - private InitNetty nettyAccountConfig; - - @Bean(name = "bossGroup", destroyMethod = "shutdownGracefully") - public NioEventLoopGroup bossGroup(){ - return new NioEventLoopGroup(nettyAccountConfig.getBossThread()); - } - - @Bean(name = "workerGroup", destroyMethod = "shutdownGracefully") - public NioEventLoopGroup workerGroup(){ - return new NioEventLoopGroup(nettyAccountConfig.getWorkerThread()); - } - - @Bean(name = "tcpSocketAddress") - public InetSocketAddress tcpPost(){ - return new InetSocketAddress(nettyAccountConfig.getTcpport()); - } - - @Bean(name = "tcpChannelOptions") - public Map, Object> tcpChannelOptions(){ - Map, Object> options = new HashMap<>(); - options.put(ChannelOption.TCP_NODELAY,nettyAccountConfig.isNodelay()); - options.put(ChannelOption.SO_KEEPALIVE, nettyAccountConfig.isKeepalive()); - options.put(ChannelOption.SO_BACKLOG, nettyAccountConfig.getBacklog()); - options.put(ChannelOption.SO_REUSEADDR,nettyAccountConfig.isReuseaddr()); - return options; - } - - @Autowired - @Qualifier("tcpChannelInitializer") - private NettyTcpChannelInitializer nettyTcpChannelInitializer; - - @Bean(name = "tcpServerBootstrap") - public ServerBootstrap bootstrap(){ - ServerBootstrap b = new ServerBootstrap(); - b.group(bossGroup(), workerGroup()) - .channel(NioServerSocketChannel.class) - .handler(new LoggingHandler(LogLevel.DEBUG)) - .childHandler(nettyTcpChannelInitializer); - Map, Object> tcpChannelOptions = tcpChannelOptions(); - Set> keySet = tcpChannelOptions.keySet(); - for (@SuppressWarnings("rawtypes") ChannelOption option : keySet) { - b.option(option, tcpChannelOptions.get(option)); - } - return b; - } - -} diff --git a/src/main/java/com/myself/nettychat/config/NettyWebSocketChannelInitializer.java b/src/main/java/com/myself/nettychat/config/NettyWebSocketChannelInitializer.java deleted file mode 100644 index a2f2eb4..0000000 --- a/src/main/java/com/myself/nettychat/config/NettyWebSocketChannelInitializer.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.myself.nettychat.config; - -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.SocketChannel; -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.stream.ChunkedWriteHandler; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.stereotype.Component; - - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 11:00 2018\8\14 0014 - */ -@Component -@Qualifier("somethingChannelInitializer") -public class NettyWebSocketChannelInitializer extends ChannelInitializer { - - @Autowired - private TextWebSocketFrameHandler textWebSocketFrameHandler; - - @Override - public void initChannel(SocketChannel ch) throws Exception { - ChannelPipeline pipeline = ch.pipeline(); - - pipeline.addLast(new HttpServerCodec()); - pipeline.addLast(new HttpObjectAggregator(65536)); - pipeline.addLast(new ChunkedWriteHandler()); - pipeline.addLast(new WebSocketServerProtocolHandler("/ws")); - pipeline.addLast(textWebSocketFrameHandler); //这里不能使用new,不然在handler中不能注入依赖 - - } - -} diff --git a/src/main/java/com/myself/nettychat/config/TCPServer.java b/src/main/java/com/myself/nettychat/config/TCPServer.java deleted file mode 100644 index ae478f4..0000000 --- a/src/main/java/com/myself/nettychat/config/TCPServer.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.myself.nettychat.config; - -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.Channel; -import lombok.Data; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.stereotype.Component; - -import javax.annotation.PreDestroy; -import java.net.InetSocketAddress; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 11:00 2018\8\14 0014 - */ -@Data -@Component -public class TCPServer { - - @Autowired - @Qualifier("serverBootstrap") - private ServerBootstrap serverBootstrap; - - @Autowired - @Qualifier("tcpServerBootstrap") - private ServerBootstrap tcpServerBootstrap; - - @Autowired - @Qualifier("webSocketAddress") - private InetSocketAddress webPort; - - @Autowired - @Qualifier("tcpSocketAddress") - private InetSocketAddress tcpTcpPort; - - private Channel serverChannel; - - private Channel tcpServerChannel; - - public void startWeb() throws Exception { - serverChannel = serverBootstrap.bind(webPort).sync().channel().closeFuture().sync().channel(); - } - - public void startTcp() throws Exception { - tcpServerChannel = tcpServerBootstrap.bind(tcpTcpPort).sync().channel().closeFuture().sync().channel(); - } - - @PreDestroy - public void stop() throws Exception { - serverChannel.close(); - serverChannel.parent().close(); - tcpServerChannel.close(); - tcpServerChannel.parent().close(); - } -} diff --git a/src/main/java/com/myself/nettychat/config/TCPServerHandler.java b/src/main/java/com/myself/nettychat/config/TCPServerHandler.java deleted file mode 100644 index f5afdfc..0000000 --- a/src/main/java/com/myself/nettychat/config/TCPServerHandler.java +++ /dev/null @@ -1,260 +0,0 @@ -package com.myself.nettychat.config; - -import com.myself.nettychat.common.utils.*; -import io.netty.channel.Channel; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.channel.group.ChannelGroup; -import io.netty.channel.group.DefaultChannelGroup; -import io.netty.util.ReferenceCountUtil; -import io.netty.util.concurrent.GlobalEventExecutor; -import io.netty.util.concurrent.ScheduledFuture; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.stereotype.Component; - -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.TimeUnit; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 19:29 2018\9\20 0020 - */ -@Component -@Qualifier("tcpServerHandler") -@ChannelHandler.Sharable -public class TCPServerHandler extends ChannelInboundHandlerAdapter { - - static final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - String ChannelID = null; - 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()); - } - 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(); - } - }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(); - ctx.close(); - System.out.println(cause.getMessage()); - } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - Const.add(String.valueOf(UUID.randomUUID()),ctx.channel()); - channels.add(ctx.channel()); - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - System.out.println("Disconnected client " + ctx.channel().remoteAddress()); - Const.remove(ctx.channel()); - } -} - diff --git a/src/main/java/com/myself/nettychat/config/TextWebSocketFrameHandler.java b/src/main/java/com/myself/nettychat/config/TextWebSocketFrameHandler.java deleted file mode 100644 index a47c5aa..0000000 --- a/src/main/java/com/myself/nettychat/config/TextWebSocketFrameHandler.java +++ /dev/null @@ -1,141 +0,0 @@ -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 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 - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 11:01 2018\8\14 0014 - */ -@Component -@Qualifier("textWebSocketFrameHandler") -@ChannelHandler.Sharable -public class TextWebSocketFrameHandler extends SimpleChannelInboundHandler{ - - public static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); - - @Autowired - private LikeRedisTemplate redisTemplate; - @Autowired - private LikeSomeCacheTemplate cacheTemplate; - @Autowired - private MsgAsyncTesk msgAsyncTesk; - - @Override - protected void channelRead0(ChannelHandlerContext ctx, - Object msg) throws Exception { - if(msg instanceof TextWebSocketFrame){ - textWebSocketFrame(ctx, (TextWebSocketFrame) msg); - }else if(msg instanceof WebSocketFrame){ //websocket帧类型 已连接 - handleWebSocketFrame(ctx, (WebSocketFrame) msg); - } - } - - private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) { - if(frame instanceof BinaryWebSocketFrame){ - //返回客户端 - BinaryWebSocketFrame imgBack= (BinaryWebSocketFrame) frame.copy(); - for (Channel channel : channels){ - channel.writeAndFlush(imgBack.retain()); - } - //保存服务器 - BinaryWebSocketFrame img= (BinaryWebSocketFrame) frame; - ByteBuf byteBuf=img.content(); - try { - FileOutputStream outputStream=new FileOutputStream("D:\\a.jpg"); - byteBuf.readBytes(outputStream,byteBuf.capacity()); - byteBuf.clear(); - }catch (Exception e){ - e.printStackTrace(); - } - } - } - - private void textWebSocketFrame(ChannelHandlerContext ctx, TextWebSocketFrame msg) { - Channel incoming = ctx.channel(); - String rName = StringUtil.getName(msg.text()); - String rMsg = StringUtil.getMsg(msg.text()); - if (rMsg.equals("")){ - return; - } - //用户登录判断 - if (redisTemplate.check(incoming.id(),rName)){ - //临时存储聊天数据 - cacheTemplate.save(rName,rMsg); - //存储随机链接ID与对应登录用户名 - redisTemplate.save(incoming.id(),rName); - //存储登录用户名与链接实例,方便API调用链接实例 - redisTemplate.saveChannel(rName,incoming); - }else{ - incoming.writeAndFlush(new TextWebSocketFrame("存在二次登陆,系统已为你自动断开本次链接")); - channels.remove(ctx.channel()); - ctx.close(); - return; - } - for (Channel channel : channels) { - //将当前每个聊天内容进行存储 - if (channel != incoming){ - channel.writeAndFlush(new TextWebSocketFrame( "[" + rName + "]" + rMsg)); - } else { - channel.writeAndFlush(new TextWebSocketFrame(rMsg + "[" + rName + "]" )); - } - } - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { - System.out.println(ctx.channel().remoteAddress()); - channels.add(ctx.channel()); - } - - @Override - public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { - //删除存储池对应实例 - String name = (String) redisTemplate.getName(ctx.channel().id()); - redisTemplate.deleteChannel(name); - //删除默认存储对应关系 - redisTemplate.delete(ctx.channel().id()); - channels.remove(ctx.channel()); - } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - //在线 - } - - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - //掉线 - msgAsyncTesk.saveChatMsgTask(); - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) - throws Exception { - //异常 - cause.printStackTrace(); - ctx.close(); - } -} diff --git a/src/main/java/com/myself/nettychat/constont/CookieConstant.java b/src/main/java/com/myself/nettychat/constont/CookieConstant.java deleted file mode 100644 index 14cb499..0000000 --- a/src/main/java/com/myself/nettychat/constont/CookieConstant.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.myself.nettychat.constont; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 18:09 2018\8\13 0013 - */ -public interface CookieConstant { - - String TOKEN = "token"; - - Integer EXPIRE = 3600;//半小时 - -} diff --git a/src/main/java/com/myself/nettychat/constont/H5Constant.java b/src/main/java/com/myself/nettychat/constont/H5Constant.java deleted file mode 100644 index d5fc6da..0000000 --- a/src/main/java/com/myself/nettychat/constont/H5Constant.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.myself.nettychat.constont; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 15:58 2018\8\13 0013 - */ -public interface H5Constant { - //登录页面 - String LOGIN = "login/login"; - //登录页面 - String LOGIN_SUI = "login/loginSui"; - - //首页2 - String HOME = "home/home"; - //首页 - String INDEX = "index"; - //聊天界面 - //String CHAT = "h5"; - - String ME = "me/me"; - - String FIND = "find/find"; - - String CHAT = "chat/chat"; - - String ALLCHAT = "chat/allchat"; -} diff --git a/src/main/java/com/myself/nettychat/constont/LikeRedisTemplate.java b/src/main/java/com/myself/nettychat/constont/LikeRedisTemplate.java deleted file mode 100644 index f9d3ad3..0000000 --- a/src/main/java/com/myself/nettychat/constont/LikeRedisTemplate.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.myself.nettychat.constont; - -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -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 11:46 2018\8\14 0014 - */ -@Component -public class LikeRedisTemplate { - - private Map 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 deleted file mode 100644 index 579cd9e..0000000 --- a/src/main/java/com/myself/nettychat/controller/NCBackController.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.myself.nettychat.controller; - -import com.myself.nettychat.common.utils.ResultVOUtil; -import com.myself.nettychat.common.utils.SendUtil; -import com.myself.nettychat.constont.LikeRedisTemplate; -import com.myself.nettychat.vo.ResultVo; -import io.netty.channel.Channel; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; - -/** - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 20:55 2018\10\7 0007 - */ -@RestController -@RequestMapping("/back") -public class NCBackController { - - @Autowired - private LikeRedisTemplate redisTemplate; - - /** - * 获取在线用户数 - * @return {@link ResultVo} - */ - @GetMapping("/size") - public ResultVo getSize(){ - return ResultVOUtil.success(redisTemplate.getSize()); - } - - /** - * 获取在线用户列表 - * @return {@link ResultVo} - */ - @GetMapping("/online") - public ResultVo getOnline(){ - return ResultVOUtil.success(redisTemplate.getOnline()); - } - - /** - * API调用向在线用户发送消息 - * @param name 用户名 - * @param msg 消息 - * @return {@link ResultVo} - */ - @PostMapping("/send") - public ResultVo send(@RequestParam String name,@RequestParam String msg){ - Channel channel = (Channel) redisTemplate.getChannel(name); - if (channel == null){ - return ResultVOUtil.error(555,"当前用户连接已断开"); - } - String result = SendUtil.sendTest(msg,channel); - return ResultVOUtil.success(result); - } - -} 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/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/CRC16myself.java b/src/main/java/com/myself/nettychat/tcptest/CRC16myself.java deleted file mode 100644 index 9f50137..0000000 --- a/src/main/java/com/myself/nettychat/tcptest/CRC16myself.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.myself.nettychat.tcptest; - -import java.math.BigInteger; - -/** - * 获取数据格式,请勿乱更改test的值或长度 - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 19:39 2018\9\20 0020 - */ -public class CRC16myself { - - public static void main(String[] args) { - String test = "F5690137563CC8syyyyyyyyyyyyyyyyynnnnnnn"; - System.out.println("原始内容字符串:" + test); - String crcString = getCRC(test.getBytes()); - System.out.println("str:" + crcString); - int crc = getCRCInt(test.getBytes()); - System.out.println("hex:" + crc); - CRC16myself myself = new CRC16myself(); - float crc16 = myself.parseHex2Float(crcString); - System.out.println("10进制浮点型:" + crc16); - String crc16String = myself.parseFloat2Hex(crc16); - System.out.println("十六进制浮点型:" + crc16String); - System.out.println("输出字符串:" + "gz" + test + crcString + "xr"); - } - - /** - * 计算CRC16校验码 - * - * @param bytes 字节数组 - * @return {@link String} 校验码 - * @since 1.0 - */ - public static String getCRC(byte[] bytes) { - int CRC = 0x0000ffff; - int POLYNOMIAL = 0x0000a001; - int i, j; - for (i = 0; i < bytes.length; i++) { - CRC ^= ((int) bytes[i] & 0x000000ff); - for (j = 0; j < 8; j++) { - if ((CRC & 0x00000001) != 0) { - CRC >>= 1; - CRC ^= POLYNOMIAL; - } else { - CRC >>= 1; - } - } - } - return Integer.toHexString(CRC); - } - - - /** - * 计算CRC16校验码 - * - * @param bytes 字节数组 - * @return {@link String} 校验码 - * @since 1.0 - */ - public static Integer getCRCInt(byte[] bytes) { - int CRC = 0x0000ffff; - int POLYNOMIAL = 0x0000a001; - int i, j; - for (i = 0; i < bytes.length; i++) { - CRC ^= ((int) bytes[i] & 0x000000ff); - for (j = 0; j < 8; j++) { - if ((CRC & 0x00000001) != 0) { - CRC >>= 1; - CRC ^= POLYNOMIAL; - } else { - CRC >>= 1; - } - } - } - return CRC; - } - - /** - * 将16进制单精度浮点型转换为10进制浮点型 - * - * @return float - * @since 1.0 - */ - private float parseHex2Float(String hexStr) { - BigInteger bigInteger = new BigInteger(hexStr, 16); - return Float.intBitsToFloat(bigInteger.intValue()); - } - - /** - * 将十进制浮点型转换为十六进制浮点型 - * - * @return String - * @since 1.0 - */ - private String parseFloat2Hex(float data) { - return Integer.toHexString(Float.floatToIntBits(data)); - } - -} diff --git a/src/main/java/com/myself/nettychat/tcptest/TCPTestClient.java b/src/main/java/com/myself/nettychat/tcptest/TCPTestClient.java deleted file mode 100644 index 083983a..0000000 --- a/src/main/java/com/myself/nettychat/tcptest/TCPTestClient.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.myself.nettychat.tcptest; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintStream; -import java.net.Socket; -import java.net.SocketTimeoutException; - -/** - * 先去同包下CRC16myself下执行获取数据,数据格式有规定 - * TCP端测试模拟,建议放置在另一个项目 - * @Author:UncleCatMySelf - * @Email:zhupeijie_java@126.com - * @QQ:1341933031 - * @Date:Created in 19:40 2018\9\20 0020 - */ -public class TCPTestClient { - - public static void main(String[] args) throws IOException { - //10万测试 - for (int i = 0;i<100000;i++){ - new Thread(new Runnable() { - @Override - public void run() { - try { - runtest(); - }catch (Exception e){ - e.printStackTrace(); - } - } - }).start(); - sleep(100); - } - } - - private static void runtest() throws IOException{ - //客户端请求与本机在18866端口建立TCP连接 - Socket client = new Socket("127.0.0.1", 8092); - client.setSoTimeout(10000); - //获取键盘输入 - BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); - //获取Socket的输出流,用来发送数据到服务端 - PrintStream out = new PrintStream(client.getOutputStream()); - //获取Socket的输入流,用来接收从服务端发送过来的数据 - BufferedReader buf = new BufferedReader(new InputStreamReader(client.getInputStream())); - 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"); - } - } - sleep(5000); - } - input.close(); - if(client != null){ - //如果构造函数建立起了连接,则关闭套接字,如果没有建立起连接,自然不用关闭 - client.close(); //只关闭socket,其关联的输入输出流也会被关闭 - } - } - - private static void sleep(Integer time){ - try { - Thread.sleep(time); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } -} diff --git a/src/main/java/com/myself/nettychat/vo/ResultVo.java b/src/main/java/com/myself/nettychat/vo/ResultVo.java deleted file mode 100644 index a83c84e..0000000 --- a/src/main/java/com/myself/nettychat/vo/ResultVo.java +++ /dev/null @@ -1,28 +0,0 @@ -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; - -} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml deleted file mode 100644 index d941b0c..0000000 --- a/src/main/resources/application.yml +++ /dev/null @@ -1,20 +0,0 @@ -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 -netty: - webport: 8090 # Websocket port - bossThread: 1 - workerThread: 2 - keepalive: true # Socket parameter, connection warranty, default value is False. When this feature is enabled, TCP proactively detects the validity of idle connections. You can consider this feature as a heartbeat mechanism for TCP, and it is important to note that the default heartbeat interval is 7200s, or 2 hours. Netty Turn off this feature by default - backlog: 1024 # Socket parameter, server accepts the queue length of the connection, and if the queue is full, the client connection will be rejected - sndbuf: 10485760 # TCP data send buffer size. - revbuf: 10485760 # TCP data receive buffer size. - heart: 180 # Read timeout - period: 10 # Cycle of re-hair - serverName: iot-netty-chat - initalDelay: 10 # Reset delay \ No newline at end of file diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties new file mode 100644 index 0000000..30185a7 --- /dev/null +++ b/src/main/resources/log4j.properties @@ -0,0 +1,17 @@ +log4j.rootLogger=debug, stdout + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout + +log4j.appender.stdout.layout.ConversionPattern=%5p - %m%n + +#log4j.appender.R=org.apache.log4j.RollingFileAppender +#log4j.appender.R.File=firestorm.log + +log4j.appender.R.MaxFileSize=100KB +log4j.appender.R.MaxBackupIndex=1 + +log4j.appender.R.layout=org.apache.log4j.PatternLayout +log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n + +log4j.logger.com.codefutures=DEBUG \ No newline at end of file diff --git a/src/main/resources/securesocket.jks b/src/main/resources/securesocket.jks deleted file mode 100644 index 2a9d8c0..0000000 Binary files a/src/main/resources/securesocket.jks and /dev/null differ diff --git a/src/test/java/com/myself/nettychat/NettychatApplicationTests.java b/src/test/java/com/myself/nettychat/NettychatApplicationTests.java deleted file mode 100644 index 9c04bf0..0000000 --- a/src/test/java/com/myself/nettychat/NettychatApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.myself.nettychat; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class NettychatApplicationTests { - - @Test - public void contextLoads() { - } - -}