├── .gitignore
├── .idea
├── .name
├── compiler.xml
├── encodings.xml
├── misc.xml
├── vcs.xml
└── workspace.xml
├── .mvn
└── wrapper
│ ├── MavenWrapperDownloader.java
│ ├── maven-wrapper.jar
│ └── maven-wrapper.properties
├── MobileFrontEnd
└── weChat
│ ├── .project
│ ├── chatlist.html
│ ├── chatting.html
│ ├── contact.html
│ ├── css
│ ├── chat.css
│ ├── header.css
│ ├── mui.css
│ ├── mui.indexedlist.css
│ ├── mui.min.css
│ └── registLogin
│ │ ├── default.png
│ │ ├── main.css
│ │ └── util.css
│ ├── discover.html
│ ├── fonts
│ └── mui.ttf
│ ├── image
│ ├── addfriends.png
│ ├── bg.png
│ ├── download.png
│ ├── error.png
│ ├── face-default-cat.png
│ ├── friends.png
│ ├── givememoney.png
│ ├── good.png
│ ├── qrcode.png
│ ├── scanscan.png
│ ├── success.png
│ └── upload.png
│ ├── index.html
│ ├── js
│ ├── app.js
│ ├── mui.indexedlist.js
│ ├── mui.js
│ ├── mui.min.js
│ └── nickname.js
│ ├── login.html
│ ├── manifest.json
│ ├── me.html
│ ├── mp3
│ ├── di_didi.mp3
│ ├── msn.mp3
│ └── send.mp3
│ ├── myface.html
│ ├── mynickname.html
│ ├── plugin
│ ├── cropper
│ │ ├── css
│ │ │ ├── cropper.css
│ │ │ └── main.css
│ │ ├── images
│ │ │ └── picture.jpg
│ │ ├── index.html
│ │ ├── js
│ │ │ ├── cropper.js
│ │ │ └── main.js
│ │ └── uploader.html
│ └── v3.1.6
│ │ ├── css
│ │ ├── cropper.css
│ │ └── main.css
│ │ ├── images
│ │ └── picture.jpg
│ │ ├── index.html
│ │ ├── js
│ │ ├── cropper.js
│ │ └── main.js
│ │ └── myface-uploader.html
│ ├── searchFriends.html
│ ├── searchFriendsResult.html
│ └── unpackage
│ ├── .confirmed_dependencies
│ └── .dependencies
├── README.md
├── im-distributed-client
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── ycw
│ │ │ └── im
│ │ │ └── imdistributedclient
│ │ │ └── ImDistributedClientApplication.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── ycw
│ └── im
│ └── imdistributedclient
│ └── ImDistributedClientApplicationTests.java
├── im-distributed-com
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── com
│ │ └── ycw
│ │ └── im
│ │ └── imdistributedcom
│ │ ├── algorithm
│ │ └── route
│ │ │ ├── handle
│ │ │ └── ConsistentHashHandle.java
│ │ │ └── routeHandler.java
│ │ ├── constant
│ │ └── Constants.java
│ │ ├── enums
│ │ └── StatusEnum.java
│ │ ├── pojo
│ │ ├── ChatMsg.java
│ │ └── UserInfo.java
│ │ ├── protocol
│ │ ├── RequestProtocol.java
│ │ ├── ResponseProtocol.java
│ │ └── chat.proto
│ │ ├── util
│ │ └── NettyAttrUtil.java
│ │ └── vo
│ │ ├── req
│ │ └── BaseRequest.java
│ │ └── resp
│ │ └── BaseResponse.java
│ └── resources
│ └── application.properties
├── im-distributed-route
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── ycw
│ │ │ └── im
│ │ │ └── imdistributedroute
│ │ │ ├── ImDistributedRouteApplication.java
│ │ │ ├── config
│ │ │ ├── AppConfig.java
│ │ │ ├── BeanConfig.java
│ │ │ └── SwaggerConfig.java
│ │ │ ├── controller
│ │ │ └── RouteController.java
│ │ │ ├── service
│ │ │ ├── AccountSerice.java
│ │ │ ├── UserLocalCacheService.java
│ │ │ └── impl
│ │ │ │ ├── AccountServiceImpl.java
│ │ │ │ └── UserLocalCacheImpl.java
│ │ │ ├── tool
│ │ │ ├── ServerRouteCache.java
│ │ │ ├── SpringBeanFactory.java
│ │ │ ├── ZkListenServerList.java
│ │ │ └── Zktool.java
│ │ │ └── vo
│ │ │ ├── req
│ │ │ ├── LoginReq.java
│ │ │ ├── OffLoginReq.java
│ │ │ ├── P2pChatMsg.java
│ │ │ └── RegisterReq.java
│ │ │ └── resp
│ │ │ ├── RegistorResp.java
│ │ │ └── ServerInfoResp.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── ycw
│ └── im
│ └── imdistributedroute
│ └── ImDistributedRouteApplicationTests.java
├── im-distributed-server
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── ycw
│ │ │ └── im
│ │ │ └── imdistributedserver
│ │ │ ├── ImDistributedServerApplication.java
│ │ │ ├── config
│ │ │ ├── AppConfiguration.java
│ │ │ ├── BeanConfig.java
│ │ │ └── SwaggerConfig.java
│ │ │ ├── controller
│ │ │ └── ChatController.java
│ │ │ ├── dao
│ │ │ └── ChatDao.java
│ │ │ ├── handle
│ │ │ └── ChatHandler.java
│ │ │ ├── init
│ │ │ └── ServerNettyInit.java
│ │ │ ├── server
│ │ │ └── Server.java
│ │ │ ├── service
│ │ │ └── ChatService.java
│ │ │ ├── tool
│ │ │ ├── RegistorZkTool.java
│ │ │ └── ZKTool.java
│ │ │ ├── util
│ │ │ ├── SessionChannelHolder.java
│ │ │ └── SpringFactory.java
│ │ │ └── vo
│ │ │ ├── request
│ │ │ └── SendMsgReqVo.java
│ │ │ └── response
│ │ │ └── SendMsgResVo.java
│ └── resources
│ │ ├── application.properties
│ │ └── mapper
│ │ └── ChatMsgMapper.xml
│ └── test
│ └── java
│ └── com
│ └── ycw
│ └── im
│ └── imdistributedserver
│ └── ImDistributedServerApplicationTests.java
├── im-distributed-zk
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── ycw
│ │ │ └── im
│ │ │ └── imdistributedzk
│ │ │ ├── ImDistributedZkApplication.java
│ │ │ ├── cache
│ │ │ └── ServerCache.java
│ │ │ ├── config
│ │ │ ├── AppConfig.java
│ │ │ └── SwaggerConfig.java
│ │ │ ├── controller
│ │ │ └── IndexController.java
│ │ │ ├── thread
│ │ │ └── RegistryZK.java
│ │ │ └── util
│ │ │ ├── AppConfiguration.java
│ │ │ ├── SpringBeanFactory.java
│ │ │ └── ZKit.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── ycw
│ └── im
│ └── imdistributedzk
│ └── ImDistributedZkApplicationTests.java
├── im-netty.iml
├── im-singel
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── ycw
│ │ │ └── im
│ │ │ └── imsingel
│ │ │ ├── Mobilewechat
│ │ │ ├── controller
│ │ │ │ ├── ChatController.java
│ │ │ │ ├── FriendController.java
│ │ │ │ ├── TestController.java
│ │ │ │ └── UserController.java
│ │ │ ├── enums
│ │ │ │ ├── AddFriendRequstEnum.java
│ │ │ │ └── MsgStateEnum.java
│ │ │ ├── mapper
│ │ │ │ ├── ChatMsgMapper.java
│ │ │ │ ├── FriendsRequestMapper.java
│ │ │ │ ├── MyFriendsMapper.java
│ │ │ │ └── UsersMapper.java
│ │ │ ├── netty
│ │ │ │ ├── ChatHandler.java
│ │ │ │ ├── Initial.java
│ │ │ │ ├── Server.java
│ │ │ │ ├── UserChannels.java
│ │ │ │ ├── pojo
│ │ │ │ │ ├── ChatMsgVo.java
│ │ │ │ │ └── DataContent.java
│ │ │ │ └── strategy
│ │ │ │ │ ├── Context.java
│ │ │ │ │ ├── Strategy.java
│ │ │ │ │ ├── StrategyFactory.java
│ │ │ │ │ └── impl
│ │ │ │ │ ├── ChatStrategy.java
│ │ │ │ │ ├── CloseStrategy.java
│ │ │ │ │ ├── ConnectStrategy.java
│ │ │ │ │ ├── HeartCheckStrategy.java
│ │ │ │ │ └── SignStrategy.java
│ │ │ ├── plugin
│ │ │ │ ├── FileConst.java
│ │ │ │ ├── QiNiuApi.java
│ │ │ │ └── QiniuUploadType.java
│ │ │ ├── pojo
│ │ │ │ ├── ChatMsg.java
│ │ │ │ ├── DataResult.java
│ │ │ │ ├── FriendsRequest.java
│ │ │ │ ├── MyFriends.java
│ │ │ │ ├── Users.java
│ │ │ │ ├── bo
│ │ │ │ │ ├── AddFriendRequst.java
│ │ │ │ │ ├── HandleFriendRequest.java
│ │ │ │ │ └── UserBo.java
│ │ │ │ └── vo
│ │ │ │ │ ├── QueryAddFriendRequestVo.java
│ │ │ │ │ ├── QueryAllFriendVo.java
│ │ │ │ │ └── UserVoResult.java
│ │ │ ├── service
│ │ │ │ ├── ChatService.java
│ │ │ │ ├── FriendService.java
│ │ │ │ ├── UserService.java
│ │ │ │ └── impl
│ │ │ │ │ ├── ChatServiceImpl.java
│ │ │ │ │ ├── FriendServiceImpl.java
│ │ │ │ │ └── UserServiceImpl.java
│ │ │ └── utils
│ │ │ │ ├── ImageUploadUtils.java
│ │ │ │ ├── JsonUtils.java
│ │ │ │ ├── MD5Utils.java
│ │ │ │ ├── SpringUtil.java
│ │ │ │ └── TrieTree.java
│ │ │ ├── NettyBoots.java
│ │ │ ├── WebApplication.java
│ │ │ ├── Webwechat
│ │ │ ├── dao
│ │ │ │ ├── GroupInfoDao.java
│ │ │ │ ├── UserInfoDao.java
│ │ │ │ └── impl
│ │ │ │ │ ├── GroupInfoDaoImpl.java
│ │ │ │ │ └── UserInfoDaoImpl.java
│ │ │ ├── model
│ │ │ │ ├── po
│ │ │ │ │ ├── GroupInfo.java
│ │ │ │ │ └── UserInfo.java
│ │ │ │ └── vo
│ │ │ │ │ └── ResponseJson.java
│ │ │ ├── service
│ │ │ │ ├── ChatService.java
│ │ │ │ ├── FileUploadService.java
│ │ │ │ ├── SecurityService.java
│ │ │ │ ├── UserInfoService.java
│ │ │ │ └── impl
│ │ │ │ │ ├── FileUploadServiceImpl.java
│ │ │ │ │ ├── SecurityServiceImpl.java
│ │ │ │ │ ├── UserInfoServiceImpl.java
│ │ │ │ │ └── WebChatServiceImpl.java
│ │ │ ├── util
│ │ │ │ ├── ChatType.java
│ │ │ │ ├── Constant.java
│ │ │ │ ├── FileUtils.java
│ │ │ │ └── JsonMsgHelper.java
│ │ │ └── web
│ │ │ │ ├── config
│ │ │ │ └── WebConfig.java
│ │ │ │ ├── controller
│ │ │ │ ├── ChatroomController.java
│ │ │ │ ├── FileUploadController.java
│ │ │ │ ├── LoginController.java
│ │ │ │ └── common
│ │ │ │ │ └── GlobalExceptionHandler.java
│ │ │ │ ├── interceptor
│ │ │ │ └── UserAuthInteceptor.java
│ │ │ │ └── websocket
│ │ │ │ ├── HttpRequestHandler.java
│ │ │ │ ├── WebSocketChildChannelHandler.java
│ │ │ │ ├── WebSocketServer.java
│ │ │ │ └── WebSocketServerHandler.java
│ │ │ └── learnNettyExample
│ │ │ ├── BrowserAndClient
│ │ │ ├── Init.java
│ │ │ ├── NettyServer.java
│ │ │ └── ResponseHandler.java
│ │ │ ├── ClientAndServer
│ │ │ ├── client
│ │ │ │ ├── NettyClient.java
│ │ │ │ └── handler
│ │ │ │ │ ├── LoginResponseHandler.java
│ │ │ │ │ └── MessageResponseHandler.java
│ │ │ ├── codec
│ │ │ │ ├── Codec.java
│ │ │ │ └── nettyCodec
│ │ │ │ │ ├── PacketDecoder.java
│ │ │ │ │ └── PacketEncoder.java
│ │ │ ├── protocol
│ │ │ │ ├── Packet.java
│ │ │ │ ├── request
│ │ │ │ │ ├── LoginRequest.java
│ │ │ │ │ └── MessageRequest.java
│ │ │ │ ├── response
│ │ │ │ │ ├── LoginResponse.java
│ │ │ │ │ └── MessageResponse.java
│ │ │ │ └── serializer
│ │ │ │ │ ├── JSONSerializer.java
│ │ │ │ │ ├── Serializer.java
│ │ │ │ │ └── SerializerAlogrithm.java
│ │ │ ├── server
│ │ │ │ ├── NettyServer.java
│ │ │ │ └── handler
│ │ │ │ │ ├── AuthHandler.java
│ │ │ │ │ ├── LoginRuqestHandler.java
│ │ │ │ │ └── MessageRequestHandler.java
│ │ │ └── util
│ │ │ │ ├── Command.java
│ │ │ │ ├── LoginUtil.java
│ │ │ │ └── State.java
│ │ │ └── WebSocketAndNetty
│ │ │ ├── ChatHandler.java
│ │ │ ├── Init.java
│ │ │ └── WsServer.java
│ └── resources
│ │ ├── application.properties
│ │ ├── mapper
│ │ ├── ChatMsgMapper.xml
│ │ ├── FriendsRequestMapper.xml
│ │ ├── MyFriendsMapper.xml
│ │ └── UsersMapper.xml
│ │ ├── public
│ │ ├── chatroom.html
│ │ └── login.html
│ │ └── static
│ │ ├── css
│ │ ├── chatroom.css
│ │ ├── common
│ │ │ ├── bootstrap.min.css
│ │ │ ├── fileinput.min.css
│ │ │ ├── font-awesome.css
│ │ │ └── layui.css
│ │ ├── fonts
│ │ │ ├── FontAwesome.otf
│ │ │ ├── fontawesome-webfont.eot
│ │ │ ├── fontawesome-webfont.svg
│ │ │ ├── fontawesome-webfont.ttf
│ │ │ ├── fontawesome-webfont.woff
│ │ │ ├── fontawesome-webfont.woff2
│ │ │ ├── glyphicons-halflings-regular.eot
│ │ │ ├── glyphicons-halflings-regular.svg
│ │ │ ├── glyphicons-halflings-regular.ttf
│ │ │ ├── glyphicons-halflings-regular.woff
│ │ │ └── glyphicons-halflings-regular.woff2
│ │ ├── img
│ │ │ ├── loading-sm.gif
│ │ │ └── loading.gif
│ │ └── login.css
│ │ ├── img
│ │ ├── avatar
│ │ │ ├── Group01.jpg
│ │ │ ├── Member001.jpg
│ │ │ ├── Member002.jpg
│ │ │ ├── Member003.jpg
│ │ │ ├── Member004.jpg
│ │ │ ├── Member005.jpg
│ │ │ ├── Member006.jpg
│ │ │ ├── Member007.jpg
│ │ │ ├── Member008.jpg
│ │ │ └── Member009.jpg
│ │ ├── box_head.jpg
│ │ ├── chat.ico
│ │ ├── chat_bg.jpg
│ │ ├── emoji.jpg
│ │ ├── emoji
│ │ │ ├── emoji_01.png
│ │ │ ├── emoji_02.png
│ │ │ ├── emoji_03.png
│ │ │ ├── emoji_04.png
│ │ │ ├── emoji_05.png
│ │ │ ├── emoji_06.png
│ │ │ ├── emoji_07.png
│ │ │ ├── emoji_08.png
│ │ │ ├── emoji_09.png
│ │ │ ├── emoji_10.png
│ │ │ ├── emoji_11.png
│ │ │ ├── emoji_12.png
│ │ │ ├── emoji_13.png
│ │ │ ├── emoji_14.png
│ │ │ ├── emoji_15.png
│ │ │ ├── emoji_16.png
│ │ │ ├── emoji_17.png
│ │ │ ├── emoji_18.png
│ │ │ ├── emoji_19.png
│ │ │ ├── emoji_20.png
│ │ │ ├── emoji_21.png
│ │ │ ├── emoji_22.png
│ │ │ ├── emoji_23.png
│ │ │ └── emoji_24.png
│ │ ├── login_bg.jpg
│ │ └── upload.jpg
│ │ └── js
│ │ ├── chatroom.js
│ │ └── common
│ │ ├── bootstrap.min.js
│ │ ├── fileinput.min.js
│ │ ├── jquery-1.9.1.min.js
│ │ ├── jquery.actual.min.js
│ │ └── zh.js
│ └── test
│ └── java
│ └── com
│ └── ycw
│ └── im
│ └── imsingel
│ └── ImSingelApplicationTests.java
├── image
├── 1.png
└── 2.png
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── ycw
│ │ └── im
│ │ ├── imdistributedcommon
│ │ └── ImDistributedCommonApplication.java
│ │ ├── imdistributedcommons
│ │ └── ImDistributedCommonsApplication.java
│ │ └── imdistributedroute
│ │ └── ImDistributedRouteApplication.java
└── resources
│ └── application.properties
└── test
└── java
└── com
└── ycw
└── im
├── imdistributedcommon
└── ImDistributedCommonApplicationTests.java
├── imdistributedcommons
└── ImDistributedCommonsApplicationTests.java
└── imdistributedroute
└── ImDistributedRouteApplicationTests.java
/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 |
4 | ### STS ###
5 | .apt_generated
6 | .classpath
7 | .factorypath
8 | .project
9 | .settings
10 | .springBeans
11 | .sts4-cache
12 |
13 | ### IntelliJ IDEA ###
14 | .idea
15 | *.iws
16 | *.iml
17 | *.ipr
18 |
19 | ### NetBeans ###
20 | /nbproject/private/
21 | /nbbuild/
22 | /dist/
23 | /nbdist/
24 | /.nb-gradle/
25 | /build/
26 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | im-root
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
2 |
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | weChat
4 | Create By HBuilder
5 |
6 |
7 |
8 |
9 | com.pandora.projects.ui.MKeyBuilder
10 |
11 |
12 |
13 |
14 | com.aptana.ide.core.unifiedBuilder
15 |
16 |
17 |
18 |
19 |
20 | com.pandora.projects.ui.MKeyNature
21 | com.aptana.projects.webnature
22 |
23 |
24 |
25 | 1543927910469
26 |
27 | 10
28 |
29 | org.eclipse.ui.ide.orFilterMatcher
30 |
31 |
32 | org.eclipse.ui.ide.multiFilter
33 | 1.0-projectRelativePath-matches-false-false-bin
34 |
35 |
36 | org.eclipse.ui.ide.multiFilter
37 | 1.0-projectRelativePath-matches-false-false-setting
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/css/header.css:
--------------------------------------------------------------------------------
1 | .title {
2 | background-color: black;
3 | }
4 |
5 | .title-font {
6 | color: white;
7 | }
8 |
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/css/registLogin/default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/MobileFrontEnd/weChat/css/registLogin/default.png
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/discover.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | -
17 |
19 |
21 | 朋友圈
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | -
30 |
32 |
34 | 添加好友
35 |
36 |
37 | -
38 |
40 |
42 | 扫一扫
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/fonts/mui.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/MobileFrontEnd/weChat/fonts/mui.ttf
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/image/addfriends.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/MobileFrontEnd/weChat/image/addfriends.png
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/image/bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/MobileFrontEnd/weChat/image/bg.png
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/image/download.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/MobileFrontEnd/weChat/image/download.png
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/image/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/MobileFrontEnd/weChat/image/error.png
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/image/face-default-cat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/MobileFrontEnd/weChat/image/face-default-cat.png
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/image/friends.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/MobileFrontEnd/weChat/image/friends.png
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/image/givememoney.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/MobileFrontEnd/weChat/image/givememoney.png
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/image/good.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/MobileFrontEnd/weChat/image/good.png
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/image/qrcode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/MobileFrontEnd/weChat/image/qrcode.png
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/image/scanscan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/MobileFrontEnd/weChat/image/scanscan.png
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/image/success.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/MobileFrontEnd/weChat/image/success.png
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/image/upload.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/MobileFrontEnd/weChat/image/upload.png
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/mp3/di_didi.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/MobileFrontEnd/weChat/mp3/di_didi.mp3
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/mp3/msn.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/MobileFrontEnd/weChat/mp3/msn.mp3
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/mp3/send.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/MobileFrontEnd/weChat/mp3/send.mp3
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/plugin/cropper/images/picture.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/MobileFrontEnd/weChat/plugin/cropper/images/picture.jpg
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/plugin/v3.1.6/images/picture.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/MobileFrontEnd/weChat/plugin/v3.1.6/images/picture.jpg
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/plugin/v3.1.6/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Cropper
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |

28 |
29 |
30 |
31 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/plugin/v3.1.6/js/main.js:
--------------------------------------------------------------------------------
1 | $(function () {
2 |
3 | var $image = $('#image');
4 | var options = {
5 | aspectRatio: 1 / 1,
6 | preview: '.img-preview',
7 | crop: function (e) {
8 | }
9 | };
10 |
11 | // Cropper
12 | $image.cropper(options);
13 |
14 | // Methods
15 | $('.docs-buttons').on('click', '[data-method]', function () {
16 | var cropper = $image.data('cropper');
17 | var result;
18 |
19 | result = $image.cropper("getCroppedCanvas");
20 |
21 | if (result) {
22 | // Bootstrap's Modal
23 | $('#getCroppedCanvasModal').modal().find('.modal-body').html(result);
24 | var base64Url = result.toDataURL();
25 | console.log(base64Url);
26 | }
27 |
28 | });
29 |
30 | });
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/unpackage/.confirmed_dependencies:
--------------------------------------------------------------------------------
1 | null
--------------------------------------------------------------------------------
/MobileFrontEnd/weChat/unpackage/.dependencies:
--------------------------------------------------------------------------------
1 | null
--------------------------------------------------------------------------------
/im-distributed-client/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 |
4 | ### STS ###
5 | .apt_generated
6 | .classpath
7 | .factorypath
8 | .project
9 | .settings
10 | .springBeans
11 | .sts4-cache
12 |
13 | ### IntelliJ IDEA ###
14 | .idea
15 | *.iws
16 | *.iml
17 | *.ipr
18 |
19 | ### NetBeans ###
20 | /nbproject/private/
21 | /nbbuild/
22 | /dist/
23 | /nbdist/
24 | /.nb-gradle/
25 | /build/
26 |
--------------------------------------------------------------------------------
/im-distributed-client/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-distributed-client/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/im-distributed-client/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
2 |
--------------------------------------------------------------------------------
/im-distributed-client/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.ycw.im
7 | im-root
8 | 1.0-SNAPSHOT
9 |
10 |
11 | im-distributed-client
12 | 0.0.1-SNAPSHOT
13 | im-distributed-client
14 |
15 |
16 |
17 | 1.8
18 |
19 |
20 |
21 |
22 | org.springframework.boot
23 | spring-boot-starter
24 |
25 |
26 |
27 | org.springframework.boot
28 | spring-boot-starter-test
29 | test
30 |
31 |
32 |
33 |
34 |
35 |
36 | org.springframework.boot
37 | spring-boot-maven-plugin
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/im-distributed-client/src/main/java/com/ycw/im/imdistributedclient/ImDistributedClientApplication.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedclient;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class ImDistributedClientApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(ImDistributedClientApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/im-distributed-client/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/im-distributed-client/src/test/java/com/ycw/im/imdistributedclient/ImDistributedClientApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedclient;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class ImDistributedClientApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/im-distributed-com/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 |
4 | ### STS ###
5 | .apt_generated
6 | .classpath
7 | .factorypath
8 | .project
9 | .settings
10 | .springBeans
11 | .sts4-cache
12 |
13 | ### IntelliJ IDEA ###
14 | .idea
15 | *.iws
16 | *.iml
17 | *.ipr
18 |
19 | ### NetBeans ###
20 | /nbproject/private/
21 | /nbbuild/
22 | /dist/
23 | /nbdist/
24 | /.nb-gradle/
25 | /build/
26 |
--------------------------------------------------------------------------------
/im-distributed-com/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-distributed-com/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/im-distributed-com/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
2 |
--------------------------------------------------------------------------------
/im-distributed-com/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.ycw.im
7 | im-root
8 | 1.0-SNAPSHOT
9 |
10 |
11 | im-distributed-com
12 | 0.0.1-SNAPSHOT
13 | im-distributed-com
14 |
15 |
16 |
17 | 1.8
18 |
19 |
20 |
21 |
22 | com.google.protobuf
23 | protobuf-java
24 |
25 |
26 |
27 | com.squareup.okhttp3
28 | okhttp
29 |
30 |
31 |
32 | io.springfox
33 | springfox-swagger2
34 | compile
35 |
36 |
37 | io.springfox
38 | springfox-swagger-ui
39 |
40 |
41 |
42 | com.github.sgroschupf
43 | zkclient
44 |
45 |
46 |
47 | io.netty
48 | netty-all
49 |
50 |
51 |
52 | org.projectlombok
53 | lombok
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/im-distributed-com/src/main/java/com/ycw/im/imdistributedcom/algorithm/route/routeHandler.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedcom.algorithm.route;
2 |
3 | import java.util.List;
4 |
5 | public interface routeHandler {
6 |
7 | String getRoute(Listips ,String key);
8 | }
9 |
--------------------------------------------------------------------------------
/im-distributed-com/src/main/java/com/ycw/im/imdistributedcom/constant/Constants.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedcom.constant;
2 |
3 | /**
4 | * @author ycw
5 | */
6 | public class Constants {
7 |
8 |
9 | /**
10 | * 服务端手动 push 次数
11 | */
12 | public static final String COUNTER_SERVER_PUSH_COUNT = "counter.server.push.count";
13 |
14 |
15 | /**
16 | * 客户端手动 push 次数
17 | */
18 | public static final String COUNTER_CLIENT_PUSH_COUNT = "counter.client.push.count";
19 |
20 |
21 | /**
22 | * 自定义报文类型
23 | */
24 | public static class CommandType {
25 | /**
26 | * 登录
27 | */
28 | public static final int LOGIN = 1;
29 | /**
30 | * 业务消息
31 | */
32 | public static final int MSG = 2;
33 |
34 | /**
35 | * ping
36 | */
37 | public static final int PING = 3;
38 | }
39 |
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/im-distributed-com/src/main/java/com/ycw/im/imdistributedcom/enums/StatusEnum.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedcom.enums;
2 |
3 | /**
4 | * @Author yuchunwei
5 | */
6 | public enum StatusEnum {
7 |
8 |
9 | SUCCESS(200, "成功"),
10 | FAIL(-1, "失败"),
11 |
12 | //消息相关
13 | SEND_SUCCESS(201,"发送消息成功"),
14 | SEND_FAIL(202,"发送消息失败"),
15 |
16 |
17 | //登陆相关400起始
18 | LOGIN_SUCCESS(400,"登陆成功"),
19 | REPEAT_LOGIN(401, "重复登陆"),
20 | OFF_LINE(402, "用户下线"),
21 |
22 | //注册相关500起始
23 | REGISTOR_SUCCESS(500,"注册成功"),
24 | REPEAT_USERNAME(501,"注册失败,username重复"),
25 | REPEAT_USERID(502,"注册失败,userid重复"),
26 | NOTREGISTOR(503,"没有注册");
27 |
28 | private int code;
29 | private String description;
30 |
31 | StatusEnum(int code, String description) {
32 | this.code = code;
33 | this.description = description;
34 | }
35 |
36 | public int getCode() {
37 | return code;
38 | }
39 |
40 | public String getDescription() {
41 | return description;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/im-distributed-com/src/main/java/com/ycw/im/imdistributedcom/pojo/ChatMsg.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedcom.pojo;
2 |
3 |
4 | import lombok.Data;
5 |
6 | import java.util.Date;
7 |
8 | @Data
9 | public class ChatMsg {
10 | public ChatMsg(String sendUserId,String acceptUserId,String msg){
11 | this.sendUserId = sendUserId;
12 | this.acceptUserId = acceptUserId;
13 | this.msg = msg;
14 | this.createTime = new Date();
15 | this.signFlag = 1;
16 | }
17 |
18 | private String id;
19 |
20 | private String sendUserId;
21 |
22 | private String acceptUserId;
23 |
24 | private String msg;
25 |
26 | private Integer signFlag;
27 |
28 | private Date createTime;
29 |
30 | }
--------------------------------------------------------------------------------
/im-distributed-com/src/main/java/com/ycw/im/imdistributedcom/pojo/UserInfo.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedcom.pojo;
2 |
3 | import lombok.Data;
4 |
5 | /**
6 | * @Author yuchunwei
7 | */
8 | @Data
9 | public class UserInfo {
10 | private Long userId;
11 | private String userName;
12 |
13 | public UserInfo(Long userId, String userName) {
14 | this.userId = userId;
15 | this.userName = userName;
16 | }
17 |
18 | @Override
19 | public String toString() {
20 | return "UserInfo{" +
21 | "userId=" + userId +
22 | ", userName='" + userName + '\'' +
23 | '}';
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/im-distributed-com/src/main/java/com/ycw/im/imdistributedcom/protocol/chat.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto2";
2 | package protocol ;
3 |
4 | option java_package = "com.ycw.im.imdistributedcom.protocol";
5 | option java_outer_classname = "RequestProtocol";
6 |
7 | message ReqProtocol{
8 | required int64 requestId = 2 ;
9 | required string reqMsg = 1 ;
10 | required int32 type = 3;
11 |
12 | }
13 |
14 |
15 |
--------------------------------------------------------------------------------
/im-distributed-com/src/main/java/com/ycw/im/imdistributedcom/util/NettyAttrUtil.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedcom.util;
2 |
3 | import io.netty.channel.Channel;
4 | import io.netty.util.Attribute;
5 | import io.netty.util.AttributeKey;
6 |
7 | /**
8 | * @Author yuchunwei
9 | */
10 | public class NettyAttrUtil {
11 |
12 | private static final AttributeKey ATTR_KEY_READER_TIME = AttributeKey.valueOf("readerTime");
13 |
14 |
15 | public static void updateReaderTime(Channel channel, Long time) {
16 | channel.attr(ATTR_KEY_READER_TIME).set(time.toString());
17 | }
18 |
19 | public static Long getReaderTime(Channel channel) {
20 | String value = getAttribute(channel, ATTR_KEY_READER_TIME);
21 |
22 | if (value != null) {
23 | return Long.valueOf(value);
24 | }
25 | return null;
26 | }
27 |
28 |
29 | private static String getAttribute(Channel channel, AttributeKey key) {
30 | Attribute attr = channel.attr(key);
31 | return attr.get();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/im-distributed-com/src/main/java/com/ycw/im/imdistributedcom/vo/req/BaseRequest.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedcom.vo.req;
2 |
3 | import io.swagger.annotations.ApiModelProperty;
4 | import lombok.Data;
5 |
6 | /**
7 | * @Author yuchunwei
8 | */
9 | @Data
10 | public class BaseRequest {
11 |
12 | @ApiModelProperty(required = false, value = "唯一请求号", example = "1234567890")
13 | private String reqNo;
14 |
15 | @ApiModelProperty(required = false, value = "当前请求的时间戳", example = "0")
16 | private int timeStamp;
17 |
18 | public BaseRequest() {
19 | this.setTimeStamp((int) System.currentTimeMillis() / 1000);
20 | }
21 |
22 | private void setTimeStamp(int timeStamp) {
23 | this.timeStamp = timeStamp;
24 | }
25 |
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/im-distributed-com/src/main/java/com/ycw/im/imdistributedcom/vo/resp/BaseResponse.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedcom.vo.resp;
2 |
3 | import com.ycw.im.imdistributedcom.enums.StatusEnum;
4 | import lombok.Data;
5 |
6 | import java.io.Serializable;
7 |
8 | /**
9 | * @Author yuchunwei
10 | */
11 |
12 | @Data
13 | public class BaseResponse implements Serializable {
14 | private int status;
15 | private String message;
16 | private String reqNo;
17 | private T dataBody;
18 |
19 | public BaseResponse(){
20 |
21 | }
22 |
23 | public BaseResponse(T dataBody, String message, int status) {
24 | this.dataBody = dataBody;
25 | this.message = message;
26 | this.status = status;
27 | }
28 |
29 | public BaseResponse(T dataBody, String message, int status, String reqNo) {
30 | this.dataBody = dataBody;
31 | this.message = message;
32 | this.status = status;
33 | this.reqNo = reqNo;
34 | }
35 | public static BaseResponse ok(T data, String message,int code) {
36 | return new BaseResponse<>(data, message, code);
37 | }
38 |
39 | public static BaseResponse ok(T data, String message) {
40 | return new BaseResponse<>(data, message, StatusEnum.SUCCESS.getCode());
41 | }
42 | public static BaseResponse error(T data,String message,int status){
43 | return new BaseResponse<>(data,message,status);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/im-distributed-com/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/im-distributed-route/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 |
4 | ### STS ###
5 | .apt_generated
6 | .classpath
7 | .factorypath
8 | .project
9 | .settings
10 | .springBeans
11 | .sts4-cache
12 |
13 | ### IntelliJ IDEA ###
14 | .idea
15 | *.iws
16 | *.iml
17 | *.ipr
18 |
19 | ### NetBeans ###
20 | /nbproject/private/
21 | /nbbuild/
22 | /dist/
23 | /nbdist/
24 | /.nb-gradle/
25 | /build/
26 |
--------------------------------------------------------------------------------
/im-distributed-route/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-distributed-route/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/im-distributed-route/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
2 |
--------------------------------------------------------------------------------
/im-distributed-route/src/main/java/com/ycw/im/imdistributedroute/ImDistributedRouteApplication.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedroute;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class ImDistributedRouteApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(ImDistributedRouteApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/im-distributed-route/src/main/java/com/ycw/im/imdistributedroute/config/AppConfig.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedroute.config;
2 |
3 | import org.springframework.beans.factory.annotation.Value;
4 | import org.springframework.stereotype.Component;
5 |
6 | /**
7 | * @Author yuchunwei
8 | */
9 | @Component
10 | public class AppConfig {
11 | @Value("${app.zk.root}")
12 | private String zkRoot;
13 |
14 | @Value("${app.zk.addr}")
15 | private String zkAddr;
16 |
17 |
18 | @Value("${server.port}")
19 | private int port;
20 |
21 | @Value("${app.zk.connect.timeout}")
22 | private int zkConnectTimeout;
23 |
24 | public int getZkConnectTimeout() {
25 | return zkConnectTimeout;
26 | }
27 |
28 | public int getPort() {
29 | return port;
30 | }
31 |
32 | public void setPort(int port) {
33 | this.port = port;
34 | }
35 |
36 | public String getZkRoot() {
37 | return zkRoot;
38 | }
39 |
40 | public void setZkRoot(String zkRoot) {
41 | this.zkRoot = zkRoot;
42 | }
43 |
44 | public String getZkAddr() {
45 | return zkAddr;
46 | }
47 |
48 | public void setZkAddr(String zkAddr) {
49 | this.zkAddr = zkAddr;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/im-distributed-route/src/main/java/com/ycw/im/imdistributedroute/config/BeanConfig.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedroute.config;
2 |
3 | import com.google.common.cache.CacheBuilder;
4 | import com.google.common.cache.CacheLoader;
5 | import com.google.common.cache.LoadingCache;
6 | import okhttp3.OkHttpClient;
7 | import org.I0Itec.zkclient.ZkClient;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.context.annotation.Bean;
10 | import org.springframework.context.annotation.Configuration;
11 | import org.springframework.data.redis.connection.RedisConnectionFactory;
12 | import org.springframework.data.redis.core.RedisTemplate;
13 | import org.springframework.data.redis.core.StringRedisTemplate;
14 | import org.springframework.data.redis.serializer.StringRedisSerializer;
15 |
16 | import java.util.concurrent.TimeUnit;
17 |
18 | /**
19 | * @Author yuchunwei
20 | */
21 | @Configuration
22 | public class BeanConfig {
23 | @Autowired
24 | private AppConfig config ;
25 |
26 | @Bean
27 | public ZkClient buildZKClient(){
28 | return new ZkClient(config.getZkAddr(), config.getZkConnectTimeout());
29 | }
30 |
31 |
32 | @Bean
33 | public LoadingCache buildCache(){
34 | return CacheBuilder.newBuilder()
35 | .build(new CacheLoader() {
36 | @Override
37 | public String load(String s) throws Exception {
38 | return null;
39 | }
40 | });
41 | }
42 | @Bean
43 | public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
44 | StringRedisTemplate redisTemplate = new StringRedisTemplate(factory);
45 | redisTemplate.setKeySerializer(new StringRedisSerializer());
46 | redisTemplate.setValueSerializer(new StringRedisSerializer());
47 | redisTemplate.afterPropertiesSet();
48 | return redisTemplate;
49 | }
50 |
51 | @Bean
52 | public OkHttpClient okHttpClient() {
53 | OkHttpClient.Builder builder = new OkHttpClient.Builder();
54 | builder.connectTimeout(30, TimeUnit.SECONDS)
55 | .readTimeout(10, TimeUnit.SECONDS)
56 | .writeTimeout(10,TimeUnit.SECONDS)
57 | .retryOnConnectionFailure(true);
58 | return builder.build();
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/im-distributed-route/src/main/java/com/ycw/im/imdistributedroute/config/SwaggerConfig.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedroute.config;
2 |
3 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 | import springfox.documentation.builders.ApiInfoBuilder;
7 | import springfox.documentation.builders.PathSelectors;
8 | import springfox.documentation.builders.RequestHandlerSelectors;
9 | import springfox.documentation.service.ApiInfo;
10 | import springfox.documentation.spi.DocumentationType;
11 | import springfox.documentation.spring.web.plugins.Docket;
12 | import springfox.documentation.swagger2.annotations.EnableSwagger2;
13 |
14 | /**
15 | * @Author yuchunwei
16 | */
17 |
18 | @Configuration
19 | @EnableSwagger2
20 | /** 是否打开swagger **/
21 | @ConditionalOnExpression("'${swagger.enable}' == 'true'")
22 | public class SwaggerConfig {
23 |
24 |
25 | @Bean
26 | public Docket createRestApi() {
27 | return new Docket(DocumentationType.SWAGGER_2)
28 | .apiInfo(apiInfo())
29 | .select()
30 | .apis(RequestHandlerSelectors.basePackage("com.ycw.im.imdistributedroute.controller"))
31 | .paths(PathSelectors.any())
32 | .build();
33 | }
34 |
35 | private ApiInfo apiInfo() {
36 | return new ApiInfoBuilder()
37 | .title("im-route")
38 | .description("im-route api")
39 | .termsOfServiceUrl("")
40 | .contact("ycw")
41 | .version("1.0.0")
42 | .build();
43 | }
44 |
45 | }
--------------------------------------------------------------------------------
/im-distributed-route/src/main/java/com/ycw/im/imdistributedroute/service/AccountSerice.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedroute.service;
2 |
3 | import com.ycw.im.imdistributedcom.vo.resp.BaseResponse;
4 | import com.ycw.im.imdistributedroute.vo.req.LoginReq;
5 | import com.ycw.im.imdistributedroute.vo.req.OffLoginReq;
6 | import com.ycw.im.imdistributedroute.vo.req.P2pChatMsg;
7 | import com.ycw.im.imdistributedroute.vo.req.RegisterReq;
8 | import com.ycw.im.imdistributedroute.vo.resp.ServerInfoResp;
9 |
10 | public interface AccountSerice {
11 | //登陆成功即返回服务器信息
12 | BaseResponse login(LoginReq loginReq);
13 |
14 | //注册用户,由接口调用方(client)提供Id和userName,这里只作去重校验
15 | BaseResponse registor(RegisterReq registerReq);
16 |
17 | BaseResponse p2pChat(P2pChatMsg msg) throws Exception;
18 |
19 | BaseResponse offLogin(OffLoginReq req);
20 | }
21 |
--------------------------------------------------------------------------------
/im-distributed-route/src/main/java/com/ycw/im/imdistributedroute/service/UserLocalCacheService.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedroute.service;
2 |
3 | import com.ycw.im.imdistributedcom.pojo.UserInfo;
4 | import com.ycw.im.imdistributedroute.vo.req.OffLoginReq;
5 |
6 | /**
7 | * @Author yuchunwei
8 | */
9 | public interface UserLocalCacheService {
10 |
11 | boolean isAlreadLogin(Long userId);
12 |
13 | boolean cacheLogin(UserInfo userInfo);
14 |
15 | boolean cacheOffLogin(OffLoginReq req);
16 |
17 | UserInfo getUserInfoById(Long userId);
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/im-distributed-route/src/main/java/com/ycw/im/imdistributedroute/service/impl/UserLocalCacheImpl.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedroute.service.impl;
2 |
3 | import com.ycw.im.imdistributedcom.pojo.UserInfo;
4 | import com.ycw.im.imdistributedroute.service.UserLocalCacheService;
5 | import com.ycw.im.imdistributedroute.vo.req.OffLoginReq;
6 | import org.springframework.stereotype.Service;
7 |
8 | import java.util.Map;
9 | import java.util.concurrent.ConcurrentHashMap;
10 |
11 | /**
12 | * @Author yuchunwei
13 | */
14 | @Service
15 | public class UserLocalCacheImpl implements UserLocalCacheService {
16 | //本地缓存用户在线用户表
17 | private final Map USER_INFO_MAP = new ConcurrentHashMap(128);
18 |
19 | @Override
20 | public boolean cacheLogin(UserInfo userInfo) {
21 | USER_INFO_MAP.put(userInfo.getUserId(),userInfo);
22 | return true ;
23 | }
24 |
25 | @Override
26 | public boolean isAlreadLogin(Long userId) {
27 | if(USER_INFO_MAP.containsKey(userId)){
28 | return true ;
29 | }
30 | else return false;
31 | }
32 |
33 | @Override
34 | public boolean cacheOffLogin(OffLoginReq req) {
35 | if (USER_INFO_MAP.containsKey(req.getUserId())){
36 | USER_INFO_MAP.remove(req.getUserId());
37 | }
38 | return true;
39 | }
40 |
41 | @Override
42 | public UserInfo getUserInfoById(Long userId) {
43 | return USER_INFO_MAP.get(userId);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/im-distributed-route/src/main/java/com/ycw/im/imdistributedroute/tool/ServerRouteCache.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedroute.tool;
2 |
3 | import com.google.common.cache.LoadingCache;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.stereotype.Component;
6 |
7 | import java.util.ArrayList;
8 | import java.util.List;
9 | import java.util.concurrent.atomic.AtomicInteger;
10 |
11 | /**
12 | * @Author yuchunwei
13 | */
14 | //本地缓存存放可用路由信息
15 | @Component
16 | public class ServerRouteCache {
17 | @Autowired
18 | private LoadingCache cache;
19 |
20 | @Autowired
21 | private Zktool zktool;
22 |
23 | private AtomicInteger index = new AtomicInteger(0);
24 |
25 | public void updateCache(List strings){
26 | //删除所有
27 | cache.invalidateAll();
28 |
29 | for(String str : strings){
30 | add(str.split("-")[1]);
31 | }
32 | }
33 |
34 | private void add(String str){
35 | cache.put(str,str);
36 | }
37 |
38 | //如果cache中没有任何服务器,则添加节点至cache中
39 | public List getAll(){
40 | List list = new ArrayList<>(3);
41 | List nodes = zktool.getAllNode();
42 | if(cache.size() == 0){
43 | for(String str : nodes){
44 | String key = str.split("-")[1];
45 | add(key);
46 | }
47 | }
48 | for(String str : nodes){
49 | list.add(str.split("-")[1]);
50 | }
51 | return list;
52 | }
53 |
54 | public String select(){
55 | List allIp = getAll();
56 | if(allIp.size() == 0){
57 | throw new RuntimeException("后台服务器全部没有启动!!");
58 | }
59 | int size = allIp.size();
60 |
61 | //负载均衡算法,有时间可以改成负载均衡随机算法
62 | return allIp.get(index.incrementAndGet() % size);
63 | }
64 |
65 |
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/im-distributed-route/src/main/java/com/ycw/im/imdistributedroute/tool/SpringBeanFactory.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedroute.tool;
2 |
3 | import org.springframework.beans.BeansException;
4 | import org.springframework.context.ApplicationContext;
5 | import org.springframework.context.ApplicationContextAware;
6 | import org.springframework.stereotype.Component;
7 |
8 | /**
9 | * @Author yuchunwei
10 | */
11 |
12 |
13 | @Component
14 | public final class SpringBeanFactory implements ApplicationContextAware {
15 | private static ApplicationContext context;
16 |
17 | public static T getBean(Class c){
18 | return context.getBean(c);
19 | }
20 |
21 |
22 | public static T getBean(String name,Class clazz){
23 | return context.getBean(name,clazz);
24 | }
25 |
26 | @Override
27 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
28 | context = applicationContext;
29 | }
30 |
31 |
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/im-distributed-route/src/main/java/com/ycw/im/imdistributedroute/tool/ZkListenServerList.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedroute.tool;
2 |
3 | import com.ycw.im.imdistributedroute.config.AppConfig;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 |
6 | /**
7 | * @Author yuchunwei
8 | */
9 | public class ZkListenServerList implements Runnable {
10 |
11 | private Zktool zktool ;
12 | private AppConfig config;
13 |
14 | public ZkListenServerList() {
15 | zktool = SpringBeanFactory.getBean(Zktool.class) ;
16 | config = SpringBeanFactory.getBean(AppConfig.class) ;
17 | }
18 |
19 | @Override
20 | public void run() {
21 | zktool.subscribeEvent(config.getZkRoot());
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/im-distributed-route/src/main/java/com/ycw/im/imdistributedroute/tool/Zktool.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedroute.tool;
2 |
3 | import com.ycw.im.imdistributedroute.config.AppConfig;
4 | import org.I0Itec.zkclient.IZkChildListener;
5 | import org.I0Itec.zkclient.ZkClient;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.stereotype.Component;
10 |
11 |
12 | import java.util.List;
13 |
14 | /**
15 | * @Author yuchunwei
16 | */
17 | @Component
18 | public class Zktool {
19 | private static Logger logger = LoggerFactory.getLogger(Zktool.class);
20 |
21 | @Autowired
22 | private AppConfig config;
23 |
24 | @Autowired
25 | private ZkClient buildZKClient;
26 |
27 | @Autowired
28 | private ServerRouteCache cache;
29 |
30 | public void subscribeEvent(String path){
31 | buildZKClient.subscribeChildChanges(path, new IZkChildListener() {
32 | @Override
33 | public void handleChildChange(String s, List list) throws Exception {
34 | //一旦zookeeper列表发生变化,就要更新本地路由缓存
35 | cache.updateCache(list);
36 | logger.info("【{}】路径下可用服务器列表更新为【{}】",path,list.toString());
37 | }
38 | });
39 | }
40 |
41 | public List getAllNode(){
42 | List list = buildZKClient.getChildren(config.getZkRoot());
43 | logger.info("查询可用服务器节点【{}】",list);
44 | return list ;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/im-distributed-route/src/main/java/com/ycw/im/imdistributedroute/vo/req/LoginReq.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedroute.vo.req;
2 |
3 | import com.ycw.im.imdistributedcom.vo.req.BaseRequest;
4 | import lombok.Data;
5 |
6 | /**
7 | * @Author yuchunwei
8 | */
9 | @Data
10 | public class LoginReq extends BaseRequest {
11 | private long userId;
12 | private String userName;
13 | }
14 |
--------------------------------------------------------------------------------
/im-distributed-route/src/main/java/com/ycw/im/imdistributedroute/vo/req/OffLoginReq.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedroute.vo.req;
2 |
3 | import com.ycw.im.imdistributedcom.vo.req.BaseRequest;
4 | import lombok.Data;
5 |
6 | /**
7 | * @Author yuchunwei
8 | */
9 | @Data
10 | public class OffLoginReq extends BaseRequest {
11 | private long userId;
12 | }
13 |
--------------------------------------------------------------------------------
/im-distributed-route/src/main/java/com/ycw/im/imdistributedroute/vo/req/P2pChatMsg.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedroute.vo.req;
2 |
3 | import com.ycw.im.imdistributedcom.vo.req.BaseRequest;
4 | import lombok.Data;
5 |
6 | import javax.annotation.security.DenyAll;
7 |
8 | /**
9 | * @Author yuchunwei
10 | */
11 | @Data
12 | public class P2pChatMsg extends BaseRequest {
13 | private long sendUserId;
14 | private long receiveUserId;
15 | private String msg;
16 | private String userName;
17 | }
18 |
--------------------------------------------------------------------------------
/im-distributed-route/src/main/java/com/ycw/im/imdistributedroute/vo/req/RegisterReq.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedroute.vo.req;
2 |
3 | import com.ycw.im.imdistributedcom.vo.req.BaseRequest;
4 | import lombok.Data;
5 |
6 |
7 | /**
8 | * @Author yuchunwei
9 | */
10 | @Data
11 | public class RegisterReq extends BaseRequest {
12 | private long userId;
13 | private String userName;
14 | }
15 |
--------------------------------------------------------------------------------
/im-distributed-route/src/main/java/com/ycw/im/imdistributedroute/vo/resp/RegistorResp.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedroute.vo.resp;
2 |
3 |
4 | import lombok.Data;
5 |
6 | import java.io.Serializable;
7 |
8 | /**
9 | * @Author yuchunwei
10 | */
11 | @Data
12 | public class RegistorResp implements Serializable {
13 | private long userId;
14 | private String userName;
15 | }
16 |
--------------------------------------------------------------------------------
/im-distributed-route/src/main/java/com/ycw/im/imdistributedroute/vo/resp/ServerInfoResp.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedroute.vo.resp;
2 |
3 | import lombok.Data;
4 |
5 | import java.io.Serializable;
6 |
7 |
8 | /**
9 | * @Author yuchunwei
10 | */
11 | @Data
12 | public class ServerInfoResp implements Serializable {
13 | private String ip;
14 | private int httpPort;
15 | private int nettyPort;
16 | public ServerInfoResp(String ip,int httpPort,int nettyPort){
17 | this.ip = ip;
18 | this.httpPort = httpPort;
19 | this.nettyPort = nettyPort;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/im-distributed-route/src/main/resources/application.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-distributed-route/src/main/resources/application.properties
--------------------------------------------------------------------------------
/im-distributed-route/src/test/java/com/ycw/im/imdistributedroute/ImDistributedRouteApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedroute;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class ImDistributedRouteApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/im-distributed-server/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 |
4 | ### STS ###
5 | .apt_generated
6 | .classpath
7 | .factorypath
8 | .project
9 | .settings
10 | .springBeans
11 | .sts4-cache
12 |
13 | ### IntelliJ IDEA ###
14 | .idea
15 | *.iws
16 | *.iml
17 | *.ipr
18 |
19 | ### NetBeans ###
20 | /nbproject/private/
21 | /nbbuild/
22 | /dist/
23 | /nbdist/
24 | /.nb-gradle/
25 | /build/
26 |
--------------------------------------------------------------------------------
/im-distributed-server/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-distributed-server/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/im-distributed-server/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
2 |
--------------------------------------------------------------------------------
/im-distributed-server/src/main/java/com/ycw/im/imdistributedserver/ImDistributedServerApplication.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedserver;
2 |
3 | import com.ycw.im.imdistributedserver.config.AppConfiguration;
4 | import com.ycw.im.imdistributedserver.tool.RegistorZkTool;
5 | import org.mybatis.spring.annotation.MapperScan;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.beans.factory.annotation.Value;
10 | import org.springframework.boot.CommandLineRunner;
11 | import org.springframework.boot.SpringApplication;
12 | import org.springframework.boot.autoconfigure.SpringBootApplication;
13 |
14 | import java.net.InetAddress;
15 |
16 | @SpringBootApplication
17 | @MapperScan(basePackages = "com.ycw.im.imdistributedserver.dao")
18 | public class ImDistributedServerApplication implements CommandLineRunner {
19 |
20 | private final static Logger LOGGER = LoggerFactory.getLogger(ImDistributedServerApplication.class);
21 |
22 | @Autowired
23 | private AppConfiguration appConfiguration;
24 |
25 | @Value("${server.port}")
26 | private int httpPort;
27 |
28 | public static void main(String[] args) {
29 | SpringApplication.run(ImDistributedServerApplication.class, args);
30 | LOGGER.info("服务端开始启动");
31 | }
32 |
33 |
34 | @Override
35 | public void run(String... args) throws Exception {
36 | String localAdree = InetAddress.getLocalHost().getHostAddress();
37 | Thread thread = new Thread(new RegistorZkTool(localAdree, appConfiguration.getImServerPort(), httpPort));
38 | thread.setName("registry-zk");
39 | thread.start();
40 | ;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/im-distributed-server/src/main/java/com/ycw/im/imdistributedserver/config/AppConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedserver.config;
2 |
3 | import lombok.Data;
4 | import org.springframework.beans.factory.annotation.Value;
5 | import org.springframework.stereotype.Component;
6 |
7 |
8 | /**
9 | * @Author yuchunwei
10 | */
11 | @Component
12 | @Data
13 | public class AppConfiguration {
14 |
15 | @Value("${app.zk.root}")
16 | private String zkRoot;
17 |
18 | @Value("${app.zk.addr}")
19 | private String zkAddr;
20 |
21 | @Value("${app.zk.switch}")
22 | private boolean zkSwitch;
23 |
24 | @Value("${im.server.port}")
25 | private int imServerPort;
26 |
27 | @Value("${im.clear.route.request.url}")
28 | private String clearRouteUrl;
29 |
30 | @Value("${im.heartbeat.time}")
31 | private long heartBeatTime;
32 |
33 | @Value("${app.zk.connect.timeout}")
34 | private int zkConnectTimeout;
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/im-distributed-server/src/main/java/com/ycw/im/imdistributedserver/config/BeanConfig.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedserver.config;
2 |
3 | import com.ycw.im.imdistributedcom.constant.Constants;
4 | import com.ycw.im.imdistributedcom.protocol.RequestProtocol;
5 | import org.I0Itec.zkclient.ZkClient;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.context.annotation.Configuration;
9 |
10 | /**
11 | * @Author yuchunwei
12 | */
13 | @Configuration
14 | public class BeanConfig {
15 |
16 | @Autowired
17 | private AppConfiguration appConfiguration;
18 |
19 | @Bean
20 | public RequestProtocol.ReqProtocol heartbeat() {
21 | RequestProtocol.ReqProtocol heart = RequestProtocol.ReqProtocol.newBuilder()
22 | .setRequestId(0L)
23 | .setSendId(0L)
24 | .setReqMsg("服务端pong")
25 | .setType(Constants.CommandType.PING)
26 | .build();
27 | return heart;
28 | }
29 |
30 | @Bean
31 | public ZkClient zkClient() {
32 | return new ZkClient(appConfiguration.getZkAddr(), appConfiguration.getZkConnectTimeout());
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/im-distributed-server/src/main/java/com/ycw/im/imdistributedserver/config/SwaggerConfig.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedserver.config;
2 |
3 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 | import springfox.documentation.builders.ApiInfoBuilder;
7 | import springfox.documentation.builders.PathSelectors;
8 | import springfox.documentation.builders.RequestHandlerSelectors;
9 | import springfox.documentation.service.ApiInfo;
10 | import springfox.documentation.spi.DocumentationType;
11 | import springfox.documentation.spring.web.plugins.Docket;
12 | import springfox.documentation.swagger2.annotations.EnableSwagger2;
13 |
14 | /**
15 | * @Author yuchunwei
16 | */
17 |
18 | @Configuration
19 | @EnableSwagger2
20 | /** 是否打开swagger **/
21 | @ConditionalOnExpression("'${swagger.enable}' == 'true'")
22 | public class SwaggerConfig {
23 |
24 |
25 | @Bean
26 | public Docket createRestApi() {
27 | return new Docket(DocumentationType.SWAGGER_2)
28 | .apiInfo(apiInfo())
29 | .select()
30 | .apis(RequestHandlerSelectors.basePackage("com.ycw.im.imdistributedserver.controller"))
31 | .paths(PathSelectors.any())
32 | .build();
33 | }
34 |
35 | private ApiInfo apiInfo() {
36 | return new ApiInfoBuilder()
37 | .title("Server api")
38 | .description("test server api")
39 | .termsOfServiceUrl("")
40 | .contact("ycw")
41 | .version("1.0.0")
42 | .build();
43 | }
44 |
45 | }
--------------------------------------------------------------------------------
/im-distributed-server/src/main/java/com/ycw/im/imdistributedserver/controller/ChatController.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedserver.controller;
2 |
3 | import com.ycw.im.imdistributedcom.vo.resp.BaseResponse;
4 | import com.ycw.im.imdistributedserver.server.Server;
5 | import com.ycw.im.imdistributedserver.vo.request.SendMsgReqVo;
6 | import io.swagger.annotations.ApiOperation;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.stereotype.Controller;
9 | import org.springframework.web.bind.annotation.RequestBody;
10 | import org.springframework.web.bind.annotation.RequestMapping;
11 | import org.springframework.web.bind.annotation.RequestMethod;
12 | import org.springframework.web.bind.annotation.ResponseBody;
13 |
14 |
15 | /**
16 | * @Author yuchunwei
17 | */
18 | @Controller
19 | @RequestMapping("/")
20 | public class ChatController {
21 | @Autowired
22 | private Server server;
23 |
24 | @ApiOperation("服务端发送消息")
25 | @RequestMapping(value = "sendMsg",method = RequestMethod.POST)
26 | @ResponseBody
27 | public BaseResponse sendMsg(@RequestBody SendMsgReqVo sendMsgReqVO){
28 | return server.sendMsg(sendMsgReqVO);
29 | }
30 |
31 |
32 |
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/im-distributed-server/src/main/java/com/ycw/im/imdistributedserver/dao/ChatDao.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedserver.dao;
2 |
3 | import com.ycw.im.imdistributedcom.pojo.ChatMsg;
4 | import org.springframework.stereotype.Repository;
5 |
6 | /**
7 | * @Author yuchunwei
8 | */
9 | @Repository
10 | public interface ChatDao {
11 | void insertMsg(ChatMsg msg);
12 | }
13 |
--------------------------------------------------------------------------------
/im-distributed-server/src/main/java/com/ycw/im/imdistributedserver/init/ServerNettyInit.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedserver.init;
2 |
3 | import com.ycw.im.imdistributedcom.protocol.RequestProtocol;
4 | import com.ycw.im.imdistributedserver.handle.ChatHandler;
5 | import io.netty.channel.Channel;
6 | import io.netty.channel.ChannelInitializer;
7 | import io.netty.handler.codec.protobuf.ProtobufDecoder;
8 | import io.netty.handler.codec.protobuf.ProtobufEncoder;
9 | import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
10 | import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
11 | import io.netty.handler.timeout.IdleStateHandler;
12 |
13 | /**
14 | * @Author yuchunwei
15 | */
16 | public class ServerNettyInit extends ChannelInitializer {
17 | @Override
18 | protected void initChannel(Channel channel) throws Exception {
19 |
20 | channel.pipeline()
21 | .addLast(new IdleStateHandler(11, 0, 0))
22 | // google Protobuf 编解码
23 | .addLast(new ProtobufVarint32FrameDecoder())
24 | .addLast(new ProtobufDecoder(RequestProtocol.ReqProtocol.getDefaultInstance()))
25 | .addLast(new ProtobufVarint32LengthFieldPrepender())
26 | .addLast(new ProtobufEncoder())
27 | .addLast(new ChatHandler());
28 | }
29 |
30 | public static void main(String[] args) {
31 |
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/im-distributed-server/src/main/java/com/ycw/im/imdistributedserver/service/ChatService.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedserver.service;
2 |
3 | import com.ycw.im.imdistributedcom.pojo.ChatMsg;
4 | import com.ycw.im.imdistributedcom.protocol.RequestProtocol;
5 | import com.ycw.im.imdistributedserver.dao.ChatDao;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.stereotype.Service;
8 |
9 | /**
10 | * @Author yuchunwei
11 | */
12 | @Service
13 | public class ChatService {
14 | @Autowired
15 | private ChatDao chatDao;
16 |
17 | public void insertMsg(RequestProtocol.ReqProtocol protocol){
18 | ChatMsg chatMsg = new ChatMsg(String.valueOf(protocol.getSendId()),String.valueOf(protocol.getRequestId()),protocol.getReqMsg());
19 | chatDao.insertMsg(chatMsg);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/im-distributed-server/src/main/java/com/ycw/im/imdistributedserver/tool/RegistorZkTool.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedserver.tool;
2 |
3 | import com.ycw.im.imdistributedserver.config.AppConfiguration;
4 | import com.ycw.im.imdistributedserver.util.SpringFactory;
5 | import javafx.application.Application;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 | import org.springframework.stereotype.Component;
9 |
10 |
11 | /**
12 | * @Author yuchunwei
13 | */
14 | public class RegistorZkTool implements Runnable {
15 |
16 | private static Logger logger = LoggerFactory.getLogger(RegistorZkTool.class);
17 |
18 | private String ip;
19 | private int nettyPort;
20 | private int httpPort;
21 |
22 |
23 | private AppConfiguration config;
24 |
25 | private ZKTool zkTool;
26 |
27 | public RegistorZkTool(String ip, int nettyPort, int httpPort) {
28 | this.ip = ip;
29 | this.httpPort = httpPort;
30 | this.nettyPort = nettyPort;
31 | config = SpringFactory.getBean(AppConfiguration.class);
32 | zkTool = SpringFactory.getBean(ZKTool.class);
33 | }
34 |
35 |
36 | @Override
37 | public void run() {
38 | zkTool.createRootNode();
39 | if (config.isZkSwitch()) {
40 | String path = config.getZkRoot() + "/ip-" + ip + ":" + httpPort + ":" + nettyPort;
41 | zkTool.createNode(path);
42 | logger.info("服务端注册到zookeeper成功,节点信息为{}", path);
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/im-distributed-server/src/main/java/com/ycw/im/imdistributedserver/tool/ZKTool.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedserver.tool;
2 |
3 | import com.ycw.im.imdistributedserver.config.AppConfiguration;
4 | import javafx.application.Application;
5 | import org.I0Itec.zkclient.ZkClient;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.stereotype.Component;
8 |
9 | /**
10 | * @Author yuchunwei
11 | */
12 | @Component
13 | public class ZKTool {
14 |
15 | @Autowired
16 | private ZkClient zkClient;
17 |
18 | @Autowired
19 | private AppConfiguration config;
20 |
21 |
22 | //写根节点
23 | public void createRootNode() {
24 | boolean exits = zkClient.exists(config.getZkRoot());
25 | if (exits) {
26 | return;
27 | }
28 | zkClient.createPersistent(config.getZkRoot());
29 | }
30 |
31 | //创建临时节点
32 | public void createNode(String path) {
33 | zkClient.createEphemeral(path);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/im-distributed-server/src/main/java/com/ycw/im/imdistributedserver/util/SessionChannelHolder.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedserver.util;
2 |
3 |
4 | import com.ycw.im.imdistributedcom.pojo.UserInfo;
5 | import io.netty.channel.socket.nio.NioSocketChannel;
6 |
7 | import java.util.Map;
8 | import java.util.concurrent.ConcurrentHashMap;
9 |
10 | /**
11 | * @Author yuchunwei
12 | */
13 | public class SessionChannelHolder {
14 | private final static Map channelMap = new ConcurrentHashMap<>(16);
15 | private final static Map SessionMap = new ConcurrentHashMap<>(16);
16 |
17 |
18 | static {
19 | channelMap.put(201903071130L,new NioSocketChannel());
20 | SessionMap.put(201903071130L,"ycw");
21 | }
22 | //保存用户及用户名
23 | public static void saveSession(Long userId, String userName) {
24 | SessionMap.put(userId, userName);
25 | }
26 |
27 | public static void removeSession(Long userId) {
28 | SessionMap.remove(userId);
29 | }
30 |
31 | //保存在线channel及删除
32 | public static void putChannel(Long userId, NioSocketChannel channel) {
33 | channelMap.put(userId, channel);
34 | }
35 |
36 | public static NioSocketChannel getChannel(Long userId) {
37 | return channelMap.get(userId);
38 | }
39 |
40 | public static void removeChannel(NioSocketChannel channel) {
41 | channelMap.entrySet().stream().filter(entry -> entry.getValue() == channel).forEach(entry -> channelMap.remove(entry.getKey()));
42 | }
43 |
44 | public static Map getChannelMap() {
45 | return channelMap;
46 | }
47 |
48 | //通过channel获取用户信息
49 | public static UserInfo getUserInfo(NioSocketChannel channel) {
50 | for (Map.Entry map : channelMap.entrySet()) {
51 | if (map.getValue() == channel) {
52 | Long userId = map.getKey();
53 | String userName = SessionMap.get(userId);
54 | UserInfo userInfo = new UserInfo(userId, userName);
55 | return userInfo;
56 | }
57 | }
58 | return null;
59 | }
60 |
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/im-distributed-server/src/main/java/com/ycw/im/imdistributedserver/util/SpringFactory.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedserver.util;
2 |
3 | import org.springframework.beans.BeansException;
4 | import org.springframework.context.ApplicationContext;
5 | import org.springframework.context.ApplicationContextAware;
6 | import org.springframework.stereotype.Component;
7 |
8 | /**
9 | * @Author yuchunwei
10 | * 如果注册到spring容器中的类是实现了ApplicationContextAware接口的话,在
11 | * 加载spring配置文件时,会自动调用setApplicationContext方法,获得springcontent
12 | * 这样做的好处是,可以动态的通过spring容器获得spring容器中的bean
13 | */
14 | @Component
15 | public class SpringFactory implements ApplicationContextAware {
16 | private static ApplicationContext context;
17 |
18 | public static T getBean(Class clazz) {
19 | return context.getBean(clazz);
20 | }
21 |
22 | public static T getBean(String name, Class clazz) {
23 | return context.getBean(name, clazz);
24 | }
25 |
26 | @Override
27 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
28 | context = applicationContext;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/im-distributed-server/src/main/java/com/ycw/im/imdistributedserver/vo/request/SendMsgReqVo.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedserver.vo.request;
2 |
3 | import com.ycw.im.imdistributedcom.vo.req.BaseRequest;
4 | import lombok.Data;
5 | import io.swagger.annotations.ApiModelProperty;
6 |
7 |
8 | /**
9 | * @Author yuchunwei
10 | */
11 | @Data
12 | public class SendMsgReqVo extends BaseRequest {
13 |
14 | @ApiModelProperty(required = true, value = "msg", example = "hello")
15 | private String msg;
16 |
17 | @ApiModelProperty(required = true, value = "userId", example = "11")
18 | private Long userId;
19 |
20 | @ApiModelProperty(required = true, value = "sendId", example = "11")
21 | private Long sendId;
22 |
23 | @Override
24 | public String toString() {
25 | return "SendMsgReqVO{" +
26 | "msg='" + msg + '\'' +
27 | ", userId=" + userId + '\'' +
28 | ", sendId=" + sendId +
29 | "} " + super.toString();
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/im-distributed-server/src/main/java/com/ycw/im/imdistributedserver/vo/response/SendMsgResVo.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedserver.vo.response;
2 |
3 |
4 | /**
5 | * @Author yuchunwei
6 | */
7 | public class SendMsgResVo {
8 | private String msg;
9 |
10 | public String getMsg() {
11 | return msg;
12 | }
13 |
14 | public void setMsg(String msg) {
15 | this.msg = msg;
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/im-distributed-server/src/main/resources/application.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-distributed-server/src/main/resources/application.properties
--------------------------------------------------------------------------------
/im-distributed-server/src/main/resources/mapper/ChatMsgMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
15 | INSERT INTO chat_msg(send_user_id,accept_user_id,msg,sign_flag,create_time)
16 | values(#{sendUserId},#{acceptUserId},#{msg},#{signFlag},#{createTime})
17 |
18 |
--------------------------------------------------------------------------------
/im-distributed-server/src/test/java/com/ycw/im/imdistributedserver/ImDistributedServerApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedserver;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class ImDistributedServerApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/im-distributed-zk/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 |
4 | ### STS ###
5 | .apt_generated
6 | .classpath
7 | .factorypath
8 | .project
9 | .settings
10 | .springBeans
11 | .sts4-cache
12 |
13 | ### IntelliJ IDEA ###
14 | .idea
15 | *.iws
16 | *.iml
17 | *.ipr
18 |
19 | ### NetBeans ###
20 | /nbproject/private/
21 | /nbbuild/
22 | /dist/
23 | /nbdist/
24 | /.nb-gradle/
25 | /build/
26 |
--------------------------------------------------------------------------------
/im-distributed-zk/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-distributed-zk/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/im-distributed-zk/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
2 |
--------------------------------------------------------------------------------
/im-distributed-zk/src/main/java/com/ycw/im/imdistributedzk/ImDistributedZkApplication.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedzk;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class ImDistributedZkApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(ImDistributedZkApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/im-distributed-zk/src/main/java/com/ycw/im/imdistributedzk/cache/ServerCache.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedzk.cache;
2 |
3 | import com.ycw.im.imdistributedzk.util.ZKit;
4 | import com.google.common.cache.LoadingCache;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.stereotype.Component;
7 |
8 | import java.util.ArrayList;
9 | import java.util.List;
10 | import java.util.Map;
11 | import java.util.concurrent.atomic.AtomicLong;
12 |
13 | /**
14 | * Function: 服务器节点缓存
15 | *
16 | * @author ycw
17 | * :
18 | * @since JDK 1.8
19 | */
20 | @Component
21 | public class ServerCache {
22 |
23 |
24 | @Autowired
25 | private LoadingCache cache;
26 |
27 | @Autowired
28 | private ZKit zkUtil;
29 |
30 | private AtomicLong index = new AtomicLong();
31 |
32 |
33 | public void addCache(String key) {
34 | cache.put(key, key);
35 | }
36 |
37 |
38 | /**
39 | * 更新所有缓存/先删除 再新增
40 | *
41 | * @param currentChilds
42 | */
43 | public void updateCache(List currentChilds) {
44 | cache.invalidateAll();
45 | for (String currentChild : currentChilds) {
46 | String key = currentChild.split("-")[1];
47 | addCache(key);
48 | }
49 | }
50 |
51 |
52 | /**
53 | * 获取所有的服务列表
54 | *
55 | * @return
56 | */
57 | public List getAll() {
58 |
59 | List list = new ArrayList<>();
60 |
61 | if (cache.size() == 0) {
62 | List allNode = zkUtil.getAllNode();
63 | for (String node : allNode) {
64 | String key = node.split("-")[1];
65 | addCache(key);
66 | }
67 | }
68 | for (Map.Entry entry : cache.asMap().entrySet()) {
69 | list.add(entry.getKey());
70 | }
71 | return list;
72 |
73 | }
74 |
75 | /**
76 | * 选取服务器
77 | *
78 | * @return
79 | */
80 | public String selectServer() {
81 | List all = getAll();
82 | if (all.size() == 0) {
83 | throw new RuntimeException("路由列表为空");
84 | }
85 | Long position = index.incrementAndGet() % all.size();
86 | if (position < 0) {
87 | position = 0L;
88 | }
89 |
90 | return all.get(position.intValue());
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/im-distributed-zk/src/main/java/com/ycw/im/imdistributedzk/config/AppConfig.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedzk.config;
2 |
3 | import com.ycw.im.imdistributedzk.util.AppConfiguration;
4 | import com.google.common.cache.CacheBuilder;
5 | import com.google.common.cache.CacheLoader;
6 | import com.google.common.cache.LoadingCache;
7 | import org.I0Itec.zkclient.ZkClient;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.context.annotation.Bean;
10 | import org.springframework.context.annotation.Configuration;
11 |
12 | /**
13 | * Function:
14 | *
15 | * @author ycw
16 | * @since JDK 1.8
17 | */
18 | @Configuration
19 | public class AppConfig {
20 |
21 | @Autowired
22 | private AppConfiguration appConfiguration;
23 |
24 | @Bean
25 | public ZkClient buildZKClient() {
26 | return new ZkClient(appConfiguration.getZkAddr(), 5000);
27 | }
28 |
29 |
30 | @Bean
31 | public LoadingCache buildCache() {
32 | return CacheBuilder.newBuilder()
33 | .build(new CacheLoader() {
34 | @Override
35 | public String load(String s) throws Exception {
36 | return null;
37 | }
38 | });
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/im-distributed-zk/src/main/java/com/ycw/im/imdistributedzk/config/SwaggerConfig.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedzk.config;
2 |
3 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 | import springfox.documentation.builders.ApiInfoBuilder;
7 | import springfox.documentation.builders.PathSelectors;
8 | import springfox.documentation.builders.RequestHandlerSelectors;
9 | import springfox.documentation.service.ApiInfo;
10 | import springfox.documentation.spi.DocumentationType;
11 | import springfox.documentation.spring.web.plugins.Docket;
12 | import springfox.documentation.swagger2.annotations.EnableSwagger2;
13 |
14 |
15 | @Configuration
16 | @EnableSwagger2
17 | /** 是否打开swagger **/
18 | @ConditionalOnExpression("'${swagger.enable}' == 'true'")
19 | public class SwaggerConfig {
20 |
21 |
22 | @Bean
23 | public Docket createRestApi() {
24 | return new Docket(DocumentationType.SWAGGER_2)
25 | .apiInfo(apiInfo())
26 | .select()
27 | .apis(RequestHandlerSelectors.basePackage("com.crossoverjie.netty.action.zk.controller"))
28 | .paths(PathSelectors.any())
29 | .build();
30 | }
31 |
32 | private ApiInfo apiInfo() {
33 | return new ApiInfoBuilder()
34 | .title("netty-action-zk api")
35 | .description("netty-action-zk api")
36 | .termsOfServiceUrl("https://crossoverJie.top")
37 | .contact("crossoverJie")
38 | .version("1.0.0")
39 | .build();
40 | }
41 |
42 | }
--------------------------------------------------------------------------------
/im-distributed-zk/src/main/java/com/ycw/im/imdistributedzk/controller/IndexController.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedzk.controller;
2 |
3 |
4 | import com.ycw.im.imdistributedzk.cache.ServerCache;
5 | import io.swagger.annotations.ApiOperation;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.stereotype.Controller;
8 | import org.springframework.web.bind.annotation.RequestMapping;
9 | import org.springframework.web.bind.annotation.RequestMethod;
10 | import org.springframework.web.bind.annotation.ResponseBody;
11 |
12 | import java.util.List;
13 |
14 | /**
15 | * Function:
16 | *
17 | * @author ycw
18 | * @since JDK 1.8
19 | */
20 | @Controller
21 | @RequestMapping("/")
22 | public class IndexController {
23 |
24 |
25 | @Autowired
26 | private ServerCache serverCache;
27 |
28 | /**
29 | * 获取所有路由节点
30 | *
31 | * @return
32 | */
33 | // @ApiOperation("获取所有路由节点")
34 | // @RequestMapping(value = "getAllRoute", method = RequestMethod.POST)
35 | // @ResponseBody()
36 | // public BaseResponse> getAllRoute() {
37 | // BaseResponse> res = new BaseResponse();
38 | // List all = serverCache.getAll();
39 | // res.setDataBody(all);
40 | // res.setCode(StatusEnum.SUCCESS.getCode());
41 | // res.setMessage(StatusEnum.SUCCESS.getMessage());
42 | // return res;
43 | // }
44 |
45 | /**
46 | * 获取所有路由节点
47 | *
48 | * @return
49 | */
50 | // @ApiOperation("获取所有路由节点")
51 | // @RequestMapping(value = "getOneOfRoute", method = RequestMethod.POST)
52 | // @ResponseBody()
53 | // public BaseResponse getOneOfRoute() {
54 | // BaseResponse res = new BaseResponse();
55 | // String server = serverCache.selectServer();
56 | // res.setDataBody(server);
57 | // res.setCode(StatusEnum.SUCCESS.getCode());
58 | // res.setMessage(StatusEnum.SUCCESS.getMessage());
59 | // return res;
60 | // }
61 |
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/im-distributed-zk/src/main/java/com/ycw/im/imdistributedzk/thread/RegistryZK.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedzk.thread;
2 |
3 | import com.ycw.im.imdistributedzk.util.AppConfiguration;
4 | import com.ycw.im.imdistributedzk.util.SpringBeanFactory;
5 | import com.ycw.im.imdistributedzk.util.ZKit;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | /**
10 | * Function:
11 | *
12 | * @author ycw
13 | * @since JDK 1.8
14 | */
15 | public class RegistryZK implements Runnable {
16 |
17 | private static Logger logger = LoggerFactory.getLogger(RegistryZK.class);
18 |
19 | private ZKit zkUtil;
20 |
21 | private AppConfiguration appConfiguration;
22 |
23 | private String ip;
24 | private int port;
25 |
26 | public RegistryZK(String ip, int port) {
27 | this.ip = ip;
28 | this.port = port;
29 | zkUtil = SpringBeanFactory.getBean(ZKit.class);
30 | appConfiguration = SpringBeanFactory.getBean(AppConfiguration.class);
31 | }
32 |
33 | @Override
34 | public void run() {
35 |
36 | //创建父节点
37 | zkUtil.createRootNode();
38 |
39 | //是否要将自己注册到 ZK
40 | if (appConfiguration.isZkSwitch()) {
41 | String path = appConfiguration.getZkRoot() + "/ip-" + ip + ":" + port;
42 | zkUtil.createNode(path, path);
43 | logger.info("注册 zookeeper 成功,msg=[{}]", path);
44 | }
45 |
46 | //注册监听服务
47 | zkUtil.subscribeEvent(appConfiguration.getZkRoot());
48 |
49 | }
50 | }
--------------------------------------------------------------------------------
/im-distributed-zk/src/main/java/com/ycw/im/imdistributedzk/util/AppConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedzk.util;
2 |
3 | import org.springframework.beans.factory.annotation.Value;
4 | import org.springframework.stereotype.Component;
5 |
6 | /**
7 | * Function:
8 | *
9 | * @author ycw
10 | * @since JDK 1.8
11 | */
12 | @Component
13 | public class AppConfiguration {
14 |
15 | @Value("${app.zk.root}")
16 | private String zkRoot;
17 |
18 | @Value("${app.zk.addr}")
19 | private String zkAddr;
20 |
21 | @Value("${app.zk.switch}")
22 | private boolean zkSwitch;
23 |
24 | @Value("${server.port}")
25 | private int port;
26 |
27 | public int getPort() {
28 | return port;
29 | }
30 |
31 | public void setPort(int port) {
32 | this.port = port;
33 | }
34 |
35 | public String getZkRoot() {
36 | return zkRoot;
37 | }
38 |
39 | public void setZkRoot(String zkRoot) {
40 | this.zkRoot = zkRoot;
41 | }
42 |
43 | public String getZkAddr() {
44 | return zkAddr;
45 | }
46 |
47 | public void setZkAddr(String zkAddr) {
48 | this.zkAddr = zkAddr;
49 | }
50 |
51 | public boolean isZkSwitch() {
52 | return zkSwitch;
53 | }
54 |
55 | public void setZkSwitch(boolean zkSwitch) {
56 | this.zkSwitch = zkSwitch;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/im-distributed-zk/src/main/java/com/ycw/im/imdistributedzk/util/SpringBeanFactory.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedzk.util;
2 |
3 | import org.springframework.beans.BeansException;
4 | import org.springframework.context.ApplicationContext;
5 | import org.springframework.context.ApplicationContextAware;
6 | import org.springframework.stereotype.Component;
7 |
8 | @Component
9 | public final class SpringBeanFactory implements ApplicationContextAware {
10 | private static ApplicationContext context;
11 |
12 | public static T getBean(Class c) {
13 | return context.getBean(c);
14 | }
15 |
16 |
17 | public static T getBean(String name, Class clazz) {
18 | return context.getBean(name, clazz);
19 | }
20 |
21 | @Override
22 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
23 | context = applicationContext;
24 | }
25 |
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/im-distributed-zk/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/im-distributed-zk/src/test/java/com/ycw/im/imdistributedzk/ImDistributedZkApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedzk;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class ImDistributedZkApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/im-netty.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/im-singel/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 |
4 | ### STS ###
5 | .apt_generated
6 | .classpath
7 | .factorypath
8 | .project
9 | .settings
10 | .springBeans
11 | .sts4-cache
12 |
13 | ### IntelliJ IDEA ###
14 | .idea
15 | *.iws
16 | *.iml
17 | *.ipr
18 |
19 | ### NetBeans ###
20 | /nbproject/private/
21 | /nbbuild/
22 | /dist/
23 | /nbdist/
24 | /.nb-gradle/
25 | /build/
26 |
--------------------------------------------------------------------------------
/im-singel/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/im-singel/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
2 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/controller/ChatController.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.controller;
2 |
3 | import com.ycw.im.imsingel.Mobilewechat.pojo.DataResult;
4 | import com.ycw.im.imsingel.Mobilewechat.service.ChatService;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.web.bind.annotation.RequestMapping;
7 | import org.springframework.web.bind.annotation.RestController;
8 |
9 | /**
10 | * @Author yuchunwei
11 | */
12 | @RestController
13 | @RequestMapping("/c")
14 | public class ChatController {
15 | @Autowired
16 | private ChatService chatService;
17 |
18 | @RequestMapping("/getUnSignMsgs")
19 | public DataResult getUnSignMsgs(String acceptUserId) {
20 | return chatService.queryUnSignMsgs(acceptUserId);
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/controller/FriendController.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.controller;
2 |
3 | import com.ycw.im.imsingel.Mobilewechat.pojo.DataResult;
4 | import com.ycw.im.imsingel.Mobilewechat.pojo.bo.AddFriendRequst;
5 | import com.ycw.im.imsingel.Mobilewechat.pojo.bo.HandleFriendRequest;
6 | import com.ycw.im.imsingel.Mobilewechat.pojo.bo.UserBo;
7 | import com.ycw.im.imsingel.Mobilewechat.service.FriendService;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.web.bind.annotation.*;
10 |
11 | /**
12 | * @Author yuchunwei
13 | */
14 | @RestController
15 | @RequestMapping("/f")
16 | public class FriendController {
17 | @Autowired
18 | private FriendService friendService;
19 |
20 | @PostMapping("/addFriendRequest")
21 | public DataResult addFriend(@RequestBody AddFriendRequst requst) {
22 | return friendService.addFriend(requst);
23 | }
24 |
25 | @RequestMapping("/queryFriendRequests")
26 | public DataResult queryRequest(UserBo userBo) {
27 | return friendService.queryFriendRequest(userBo.getUserId());
28 | }
29 |
30 | //忽略是0 同意是1
31 | @RequestMapping("/operFriendRequest")
32 | public DataResult operFriendRequest(HandleFriendRequest request) {
33 | return friendService.operFriendRequest(request);
34 | }
35 |
36 | @RequestMapping("/myFriends")
37 | public DataResult getAllFriends(String userId) {
38 | return friendService.getAllFriend(userId);
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/controller/TestController.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.controller;
2 |
3 | import org.springframework.web.bind.annotation.RequestMapping;
4 | import org.springframework.web.bind.annotation.RestController;
5 |
6 | /**
7 | * @Author yuchunwei
8 | */
9 | @RestController
10 | public class TestController {
11 |
12 | @RequestMapping("/index")
13 | public String test() {
14 | return "hello netty";
15 | }
16 |
17 | public static void main(String[] args) {
18 |
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/controller/UserController.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.controller;
2 |
3 | import com.ycw.im.imsingel.Mobilewechat.pojo.Users;
4 | import com.ycw.im.imsingel.Mobilewechat.pojo.bo.AddFriendRequst;
5 | import com.ycw.im.imsingel.Mobilewechat.pojo.bo.UserBo;
6 | import com.ycw.im.imsingel.Mobilewechat.service.UserService;
7 | import com.ycw.im.imsingel.Mobilewechat.pojo.DataResult;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.web.bind.annotation.*;
10 |
11 | /**
12 | * @Author yuchunwei
13 | */
14 | @RestController
15 | @RequestMapping("/u")
16 | public class UserController {
17 | @Autowired
18 | private UserService userService;
19 |
20 | @PostMapping("/login")
21 | public DataResult login(@RequestBody Users users) {
22 | if (isVaild(users.getUsername(), users.getPassword())) {
23 | return DataResult.errorMsg("密码或者用户名不能为空");
24 | }
25 | return userService.login(users);
26 | }
27 |
28 | @RequestMapping("/register")
29 | public DataResult register(Users users) {
30 | if (isVaild(users.getUsername(), users.getPassword())) {
31 | return DataResult.errorMsg("密码或者用户名不能为空");
32 | }
33 | DataResult result = userService.queryUsername(users.getUsername());
34 | if (result.getStatus() != 200) {
35 | return result;
36 | }
37 | return userService.registor(users.getUsername(), users.getPassword());
38 | }
39 |
40 | @PostMapping("/uploadFace")
41 | public DataResult uploadImage(@RequestBody UserBo userBo) {
42 | return userService.upLoadImage(userBo);
43 | }
44 |
45 | @PostMapping("setNickname")
46 | public DataResult setNickname(@RequestBody UserBo userBo) {
47 | return userService.setNickName(userBo);
48 | }
49 |
50 | @PostMapping("search")
51 | public DataResult searchFriend(@RequestBody AddFriendRequst requst) {
52 | return userService.searchFriend(requst);
53 | }
54 |
55 |
56 | public static boolean isVaild(String username, String password) {
57 | if (username.equals("") || password.equals("")) {
58 | return true;
59 | }
60 | return false;
61 | }
62 |
63 |
64 | public static void main(String[] args) {
65 |
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/enums/AddFriendRequstEnum.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.enums;
2 |
3 | /**
4 | * @Author yuchunwei
5 | */
6 | //无论添加好友的请求是成功还是忽略 都是已经处理的状态
7 | public enum AddFriendRequstEnum {
8 | HANDLED(1, "已经处理"),
9 | UNHANDLED(2, "还没有被处理"),
10 | ISYOURFRIEND(3, "已经是你的好友,无法添加"),
11 | ISYOURSELF(4, "无法添加自己");
12 |
13 | private int code;
14 | private String message;
15 |
16 | AddFriendRequstEnum(int code, String message) {
17 | this.code = code;
18 | this.message = message;
19 | }
20 |
21 | public int getCode() {
22 | return code;
23 | }
24 |
25 | public String getMessage() {
26 | return message;
27 | }
28 |
29 | public void setCode(int code) {
30 | this.code = code;
31 | }
32 |
33 | public void setMessage(String message) {
34 | this.message = message;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/enums/MsgStateEnum.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.enums;
2 |
3 | public enum MsgStateEnum {
4 | CONNECT(1, " 第一次(或重连)初始化连接"),
5 | CHAT(2, "聊天消息"),
6 | SIGNED(3, "消息签收"),
7 | KEEPALIVE(4, "客户端保持心跳"),
8 | PULL_FRIEND(5, "重新拉取好友"),
9 | CLOSE(6, "close");
10 | private Integer code;
11 | private String des;
12 |
13 | MsgStateEnum(Integer code, String des) {
14 | this.code = code;
15 | this.des = des;
16 | }
17 |
18 | public void setCode(Integer code) {
19 | this.code = code;
20 | }
21 |
22 | public Integer getCode() {
23 | return code;
24 | }
25 |
26 | public void setDes(String des) {
27 | this.des = des;
28 | }
29 |
30 | public String getDes() {
31 | return des;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/mapper/ChatMsgMapper.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.mapper;
2 |
3 | import com.ycw.im.imsingel.Mobilewechat.pojo.ChatMsg;
4 | import org.apache.ibatis.annotations.Param;
5 | import org.springframework.stereotype.Repository;
6 |
7 | import java.util.List;
8 |
9 | @Repository
10 | public interface ChatMsgMapper {
11 | int insertMsg(ChatMsg chatMsg);
12 |
13 | List queryUnSignMsgs(@Param("acceptUserId") String acceptUserId);
14 |
15 | void updateMsgToSign(List ids);
16 | }
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/mapper/FriendsRequestMapper.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.mapper;
2 |
3 | import com.ycw.im.imsingel.Mobilewechat.pojo.bo.AddFriendRequst;
4 | import com.ycw.im.imsingel.Mobilewechat.pojo.bo.HandleFriendRequest;
5 | import com.ycw.im.imsingel.Mobilewechat.pojo.vo.QueryAddFriendRequestVo;
6 | import org.apache.ibatis.annotations.Param;
7 | import org.springframework.stereotype.Repository;
8 |
9 | import java.util.List;
10 |
11 | @Repository
12 | public interface FriendsRequestMapper {
13 |
14 | void insertAddFriendRequst(AddFriendRequst requst);
15 |
16 | List queryFriendRequst(@Param("userId") String userId);
17 |
18 | void updateStatus(HandleFriendRequest request);
19 | }
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/mapper/MyFriendsMapper.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.mapper;
2 |
3 | import com.ycw.im.imsingel.Mobilewechat.pojo.vo.QueryAllFriendVo;
4 | import org.apache.ibatis.annotations.Param;
5 | import org.springframework.stereotype.Repository;
6 |
7 | import java.util.List;
8 |
9 | @Repository
10 | public interface MyFriendsMapper {
11 | List selectFriendIds(@Param("userId") String userId);
12 |
13 | void insertFriend(@Param("acceptUserId") String acceptUserId, @Param("sendUserId") String sendUserId);
14 |
15 | List selectFriends(List ids);
16 | }
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/mapper/UsersMapper.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.mapper;
2 |
3 | import com.ycw.im.imsingel.Mobilewechat.pojo.bo.UserBo;
4 | import com.ycw.im.imsingel.Mobilewechat.pojo.vo.UserVoResult;
5 | import com.ycw.im.imsingel.Mobilewechat.pojo.Users;
6 | import org.springframework.stereotype.Repository;
7 |
8 | @Repository
9 | public interface UsersMapper {
10 | Users queryUsername(String username);
11 |
12 | void registor(String username, String password);
13 |
14 | UserVoResult login(Users users);
15 |
16 | void updateImage(UserBo userBo);
17 |
18 | UserVoResult getUser(UserBo userBo);
19 |
20 | void updateNickName(UserBo userBo);
21 |
22 | UserVoResult selecUserByUserName(String userName);
23 |
24 |
25 | }
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/netty/ChatHandler.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.netty;
2 |
3 | import com.ycw.im.imsingel.Mobilewechat.netty.pojo.DataContent;
4 | import com.ycw.im.imsingel.Mobilewechat.netty.strategy.Context;
5 | import com.ycw.im.imsingel.Mobilewechat.utils.JsonUtils;
6 | import io.netty.channel.ChannelHandlerContext;
7 | import io.netty.channel.SimpleChannelInboundHandler;
8 | import io.netty.channel.group.ChannelGroup;
9 | import io.netty.channel.group.DefaultChannelGroup;
10 | import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
11 | import io.netty.util.concurrent.GlobalEventExecutor;
12 |
13 | /**
14 | * @Author yuchunwei
15 | */
16 | public class ChatHandler extends SimpleChannelInboundHandler {
17 | private static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
18 |
19 | @Override
20 | protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame msg) throws Exception {
21 | String content = msg.text();
22 | System.out.println("收到的消息" + content);
23 | DataContent dataContent = JsonUtils.jsonToPojo(content, DataContent.class);
24 | Context.handle(dataContent, channelHandlerContext.channel());
25 |
26 | }
27 |
28 | @Override
29 | public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
30 | channels.add(ctx.channel());
31 | }
32 |
33 | @Override
34 | public void channelActive(ChannelHandlerContext ctx) throws Exception {
35 | System.out.println("有新的channel");
36 | super.channelActive(ctx);
37 | }
38 |
39 | @Override
40 | public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
41 | System.out.println("有用户被移除");
42 | super.handlerRemoved(ctx);
43 | }
44 |
45 | public static void main(String[] args) {
46 |
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/netty/Initial.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.netty;
2 |
3 | import io.netty.channel.ChannelInitializer;
4 | import io.netty.channel.socket.SocketChannel;
5 | import io.netty.handler.codec.http.HttpObjectAggregator;
6 | import io.netty.handler.codec.http.HttpServerCodec;
7 | import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
8 | import io.netty.handler.stream.ChunkedWriteHandler;
9 |
10 | /**
11 | * @Author yuchunwei
12 | */
13 | public class Initial extends ChannelInitializer {
14 |
15 | @Override
16 | protected void initChannel(SocketChannel channel) throws Exception {
17 | channel.pipeline().addLast(new HttpServerCodec());
18 | channel.pipeline().addLast(new ChunkedWriteHandler());
19 | channel.pipeline().addLast(new HttpObjectAggregator(1024 * 64));
20 |
21 | channel.pipeline().addLast(new WebSocketServerProtocolHandler("/ws"));
22 | channel.pipeline().addLast(new ChatHandler());
23 | }
24 |
25 | public static void main(String[] args) {
26 |
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/netty/Server.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.netty;
2 |
3 | import io.netty.bootstrap.ServerBootstrap;
4 | import io.netty.channel.ChannelFuture;
5 | import io.netty.channel.EventLoopGroup;
6 | import io.netty.channel.nio.NioEventLoopGroup;
7 | import io.netty.channel.socket.nio.NioServerSocketChannel;
8 |
9 | /**
10 | * @Author yuchunwei
11 | */
12 | public class Server {
13 | private final static Server INSTANCE = new Server();
14 |
15 | private EventLoopGroup mainGroup;
16 | private EventLoopGroup subGroup;
17 | private ServerBootstrap server;
18 | private ChannelFuture future;
19 |
20 | private Server() {
21 | mainGroup = new NioEventLoopGroup();
22 | subGroup = new NioEventLoopGroup();
23 | server = new ServerBootstrap();
24 | server.group(mainGroup, subGroup)
25 | .channel(NioServerSocketChannel.class)
26 | .childHandler(new Initial());
27 | }
28 |
29 | public static Server getInstance() {
30 | return INSTANCE;
31 | }
32 |
33 | public void start(int port) {
34 | future = server.bind(port);
35 | System.err.println("netty server 启动,端口号为" + port);
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/netty/UserChannels.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.netty;
2 |
3 | import io.netty.channel.Channel;
4 |
5 | import java.util.HashMap;
6 |
7 | /**
8 | * @Author yuchunwei
9 | */
10 |
11 |
12 | public class UserChannels {
13 |
14 | private static HashMap manager = new HashMap<>();
15 |
16 | public static void put(String senderId, Channel channel) {
17 | manager.put(senderId, channel);
18 | }
19 |
20 | public static Channel get(String senderId) {
21 | return manager.get(senderId);
22 | }
23 |
24 | public static void output() {
25 | for (HashMap.Entry entry : manager.entrySet()) {
26 | System.out.println("UserId: " + entry.getKey()
27 | + ", ChannelId: " + entry.getValue().id().asLongText());
28 | }
29 | }
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/netty/pojo/ChatMsgVo.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.netty.pojo;
2 |
3 | import lombok.Data;
4 |
5 | /**
6 | * @Author yuchunwei
7 | */
8 | @Data
9 | public class ChatMsgVo {
10 | private static final long serialVersionUID = 3611169682695799175L;
11 |
12 | private String senderId; // 发送者的用户id
13 | private String receiverId; // 接受者的用户id
14 | private String msg; // 聊天内容
15 | private String msgId; // 用于消息的签收
16 | }
17 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/netty/pojo/DataContent.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.netty.pojo;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import lombok.Data;
5 |
6 | /**
7 | * @Author yuchunwei
8 | */
9 | @Data
10 | public class DataContent {
11 | private static final long serialVersionUID = 8021381444738260454L;
12 |
13 | private Integer action; // 动作类型
14 | @JsonProperty(value = "ChatMsgVo")
15 | private ChatMsgVo chatMsgVo; // 用户的聊天内容entity
16 | private String extand; // 扩展字段
17 | }
18 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/netty/strategy/Context.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.netty.strategy;
2 |
3 | import com.ycw.im.imsingel.Mobilewechat.netty.pojo.DataContent;
4 | import io.netty.channel.Channel;
5 |
6 | /**
7 | * @Author yuchunwei
8 | */
9 | public class Context {
10 | private Strategy strategy;
11 |
12 | public static void handle(DataContent dataContent, Channel curChannel) {
13 | Strategy strategy = StrategyFactory.getInstance().create(dataContent.getAction());
14 | strategy.handle(dataContent, curChannel);
15 | }
16 |
17 | public Strategy getStrategy() {
18 | return strategy;
19 | }
20 |
21 | public void setStrategy(Strategy strategy) {
22 | this.strategy = strategy;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/netty/strategy/Strategy.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.netty.strategy;
2 |
3 | import com.ycw.im.imsingel.Mobilewechat.netty.pojo.DataContent;
4 | import io.netty.channel.Channel;
5 |
6 | public interface Strategy {
7 |
8 | public void handle(DataContent dataContent, Channel curChannel);
9 | }
10 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/netty/strategy/StrategyFactory.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.netty.strategy;
2 |
3 | import com.ycw.im.imsingel.Mobilewechat.enums.MsgStateEnum;
4 | import com.ycw.im.imsingel.Mobilewechat.netty.strategy.impl.*;
5 |
6 | import java.util.HashMap;
7 |
8 | /**
9 | * @Author yuchunwei
10 | */
11 | public class StrategyFactory {
12 | private static StrategyFactory factory = new StrategyFactory();
13 |
14 | private StrategyFactory() {
15 | }
16 |
17 | private static HashMap map = new HashMap<>();
18 |
19 | static {
20 | map.put(MsgStateEnum.CONNECT.getCode(), new ConnectStrategy());
21 | map.put(MsgStateEnum.CHAT.getCode(), new ChatStrategy());
22 | map.put(MsgStateEnum.CLOSE.getCode(), new CloseStrategy());
23 | map.put(MsgStateEnum.KEEPALIVE.getCode(), new HeartCheckStrategy());
24 | map.put(MsgStateEnum.SIGNED.getCode(), new SignStrategy());
25 | }
26 |
27 | public Strategy create(Integer type) {
28 | return map.get(type);
29 | }
30 |
31 | public static StrategyFactory getInstance() {
32 | return factory;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/netty/strategy/impl/ChatStrategy.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.netty.strategy.impl;
2 |
3 | import com.ycw.im.imsingel.Mobilewechat.netty.UserChannels;
4 | import com.ycw.im.imsingel.Mobilewechat.netty.pojo.ChatMsgVo;
5 | import com.ycw.im.imsingel.Mobilewechat.netty.pojo.DataContent;
6 | import com.ycw.im.imsingel.Mobilewechat.netty.strategy.Strategy;
7 | import com.ycw.im.imsingel.Mobilewechat.pojo.ChatMsg;
8 | import com.ycw.im.imsingel.Mobilewechat.service.ChatService;
9 | import com.ycw.im.imsingel.Mobilewechat.utils.JsonUtils;
10 | import com.ycw.im.imsingel.Mobilewechat.utils.SpringUtil;
11 | import io.netty.channel.Channel;
12 | import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
13 |
14 | import java.util.Date;
15 |
16 | /**
17 | * @Author yuchunwei
18 | */
19 | public class ChatStrategy implements Strategy {
20 | @Override
21 | public void handle(DataContent dataContent, Channel curChannel) {
22 | ChatMsgVo chatMsgVo = dataContent.getChatMsgVo();
23 | ChatMsg chatMsg = new ChatMsg();
24 | String msgText = chatMsgVo.getMsg();
25 | String receiverId = chatMsgVo.getReceiverId();
26 | String senderId = chatMsgVo.getSenderId();
27 |
28 |
29 | chatMsg.setAcceptUserId(receiverId);
30 | chatMsg.setSendUserId(senderId);
31 | chatMsg.setMsg(msgText);
32 | chatMsg.setCreateTime(new Date());
33 | //签收flag 0 -> 未签收 1 -> 已签收
34 | chatMsg.setSignFlag(0);
35 | ChatService chatService = (ChatService) SpringUtil.getBean("chatServiceImpl");
36 | int msgId = chatService.insertMsg(chatMsg);
37 | chatMsgVo.setMsgId(String.valueOf(msgId));
38 | Channel receiveChannel = UserChannels.get(senderId);
39 | if (receiveChannel != null) {
40 | receiveChannel.writeAndFlush(new TextWebSocketFrame(JsonUtils.objectToJson(chatMsgVo)));
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/netty/strategy/impl/CloseStrategy.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.netty.strategy.impl;
2 |
3 | import com.ycw.im.imsingel.Mobilewechat.netty.UserChannels;
4 | import com.ycw.im.imsingel.Mobilewechat.netty.pojo.DataContent;
5 | import com.ycw.im.imsingel.Mobilewechat.netty.strategy.Strategy;
6 | import io.netty.channel.Channel;
7 |
8 | /**
9 | * @Author yuchunwei
10 | */
11 | public class CloseStrategy implements Strategy {
12 |
13 | @Override
14 | public void handle(DataContent dataContent, Channel curChannel) {
15 | UserChannels.put(dataContent.getExtand(), null);
16 | System.out.println("用户" + dataContent.getExtand() + "被移除");
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/netty/strategy/impl/ConnectStrategy.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.netty.strategy.impl;
2 |
3 | import com.ycw.im.imsingel.Mobilewechat.netty.UserChannels;
4 | import com.ycw.im.imsingel.Mobilewechat.netty.pojo.ChatMsgVo;
5 | import com.ycw.im.imsingel.Mobilewechat.netty.pojo.DataContent;
6 | import com.ycw.im.imsingel.Mobilewechat.netty.strategy.Strategy;
7 | import io.netty.channel.Channel;
8 |
9 | /**
10 | * @Author yuchunwei
11 | */
12 | public class ConnectStrategy implements Strategy {
13 |
14 | @Override
15 | public void handle(DataContent dataContent, Channel curChannel) {
16 | ChatMsgVo chatMsgVo = dataContent.getChatMsgVo();
17 | UserChannels.put(dataContent.getChatMsgVo().getSenderId(), curChannel);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/netty/strategy/impl/HeartCheckStrategy.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.netty.strategy.impl;
2 |
3 | import com.ycw.im.imsingel.Mobilewechat.netty.pojo.DataContent;
4 | import com.ycw.im.imsingel.Mobilewechat.netty.strategy.Strategy;
5 | import io.netty.channel.Channel;
6 |
7 | /**
8 | * @Author yuchunwei
9 | */
10 | public class HeartCheckStrategy implements Strategy {
11 |
12 |
13 | @Override
14 | public void handle(DataContent dataContent, Channel curChannel) {
15 | System.out.println("收到心跳检查");
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/netty/strategy/impl/SignStrategy.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.netty.strategy.impl;
2 |
3 | import com.ycw.im.imsingel.Mobilewechat.netty.pojo.DataContent;
4 | import com.ycw.im.imsingel.Mobilewechat.netty.strategy.Strategy;
5 | import com.ycw.im.imsingel.Mobilewechat.service.ChatService;
6 | import com.ycw.im.imsingel.Mobilewechat.utils.SpringUtil;
7 | import io.netty.channel.Channel;
8 |
9 | import java.util.Arrays;
10 | import java.util.List;
11 |
12 | /**
13 | * @Author yuchunwei
14 | */
15 | public class SignStrategy implements Strategy {
16 |
17 |
18 | @Override
19 | public void handle(DataContent dataContent, Channel curChannel) {
20 | String unSignedMsgIdStr = dataContent.getExtand();
21 | List unSignedMsgIds = Arrays.asList(unSignedMsgIdStr.split(","));
22 | //应该检测一下是否是数字的
23 | if (unSignedMsgIds.size() > 0) {
24 | ChatService chatService = (ChatService) SpringUtil.getBean("chatServiceImpl");
25 | chatService.updateMsgToSign(unSignedMsgIds);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/plugin/FileConst.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.plugin;
2 |
3 | /**
4 | * @Author yuchunwei
5 | */
6 | public class FileConst {
7 | /**
8 | * 默认图片的宽度:为一数组,如果为一个元素则必须等于该值才合格,如果为两个值,则为图片宽度应符合的区间值。元素个数最多只可为两个
9 | */
10 | public static final int[] DEFAULT_IMG_WIDTH = {0, 1366};
11 |
12 | /**
13 | * 默认图片的高度
14 | */
15 | public static final int[] DEFAULT_IMG_HEIGHT = {0, 768};
16 |
17 | /**
18 | * 默认图片的大小:单位B, 52428800B = 51200KB = 50M
19 | */
20 | public static final int[] DEFAULT_IMG_SIZE = {1024, 52428800};
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/plugin/QiniuUploadType.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.plugin;
2 |
3 | public enum QiniuUploadType {
4 | FACEBIGIMAGE("faceBigImage/", FileConst.DEFAULT_IMG_WIDTH, FileConst.DEFAULT_IMG_HEIGHT, FileConst.DEFAULT_IMG_SIZE),
5 | FACEIMAGE("faceImage/", FileConst.DEFAULT_IMG_WIDTH, FileConst.DEFAULT_IMG_HEIGHT, FileConst.DEFAULT_IMG_SIZE),
6 | QRCODE("qrcode/", FileConst.DEFAULT_IMG_WIDTH, FileConst.DEFAULT_IMG_HEIGHT, FileConst.DEFAULT_IMG_SIZE);
7 |
8 | private String path;
9 | /**
10 | * 上传图片的宽度
11 | */
12 | private int[] width;
13 | /**
14 | * 上传图片的高度
15 | */
16 | private int[] height;
17 | /**
18 | * 上传图片的大小
19 | */
20 | private int[] size;
21 |
22 | QiniuUploadType(String path, int[] width, int[] height, int[] size) {
23 | this.path = path;
24 | this.width = width;
25 | this.height = height;
26 | this.size = size;
27 | }
28 |
29 | public String getPath() {
30 |
31 | return path;
32 | }
33 |
34 | public int[] getWidth() {
35 | return width;
36 | }
37 |
38 | public int[] getHeight() {
39 | return height;
40 | }
41 |
42 | public int[] getSize() {
43 | return size;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/pojo/ChatMsg.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.pojo;
2 |
3 |
4 | import javax.persistence.Column;
5 | import javax.persistence.Id;
6 | import javax.persistence.Table;
7 | import java.util.Date;
8 |
9 | @Table(name = "chat_msg")
10 | public class ChatMsg {
11 | @Id
12 | private String id;
13 |
14 | @Column(name = "send_user_id")
15 | private String sendUserId;
16 |
17 | @Column(name = "accept_user_id")
18 | private String acceptUserId;
19 |
20 | private String msg;
21 |
22 | @Column(name = "sign_flag")
23 | private Integer signFlag;
24 |
25 | @Column(name = "create_time")
26 | private Date createTime;
27 |
28 | /**
29 | * @return id
30 | */
31 | public String getId() {
32 | return id;
33 | }
34 |
35 | /**
36 | * @param id
37 | */
38 | public void setId(String id) {
39 | this.id = id;
40 | }
41 |
42 | /**
43 | * @return send_user_id
44 | */
45 | public String getSendUserId() {
46 | return sendUserId;
47 | }
48 |
49 | /**
50 | * @param sendUserId
51 | */
52 | public void setSendUserId(String sendUserId) {
53 | this.sendUserId = sendUserId;
54 | }
55 |
56 | /**
57 | * @return accept_user_id
58 | */
59 | public String getAcceptUserId() {
60 | return acceptUserId;
61 | }
62 |
63 | /**
64 | * @param acceptUserId
65 | */
66 | public void setAcceptUserId(String acceptUserId) {
67 | this.acceptUserId = acceptUserId;
68 | }
69 |
70 | /**
71 | * @return msg
72 | */
73 | public String getMsg() {
74 | return msg;
75 | }
76 |
77 | /**
78 | * @param msg
79 | */
80 | public void setMsg(String msg) {
81 | this.msg = msg;
82 | }
83 |
84 | /**
85 | * @return sign_flag
86 | */
87 | public Integer getSignFlag() {
88 | return signFlag;
89 | }
90 |
91 | /**
92 | * @param signFlag
93 | */
94 | public void setSignFlag(Integer signFlag) {
95 | this.signFlag = signFlag;
96 | }
97 |
98 | /**
99 | * @return create_time
100 | */
101 | public Date getCreateTime() {
102 | return createTime;
103 | }
104 |
105 | /**
106 | * @param createTime
107 | */
108 | public void setCreateTime(Date createTime) {
109 | this.createTime = createTime;
110 | }
111 | }
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/pojo/FriendsRequest.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.pojo;
2 |
3 | import javax.persistence.Column;
4 | import javax.persistence.Id;
5 | import javax.persistence.Table;
6 | import java.util.Date;
7 |
8 | @Table(name = "friends_request")
9 | public class FriendsRequest {
10 | @Id
11 | private String id;
12 |
13 | @Column(name = "send_user_id")
14 | private String sendUserId;
15 |
16 | @Column(name = "accept_user_id")
17 | private String acceptUserId;
18 |
19 | @Column(name = "request_time")
20 | private Date requestTime;
21 |
22 | /**
23 | * @return id
24 | */
25 | public String getId() {
26 | return id;
27 | }
28 |
29 | /**
30 | * @param id
31 | */
32 | public void setId(String id) {
33 | this.id = id;
34 | }
35 |
36 | /**
37 | * @return send_user_id
38 | */
39 | public String getSendUserId() {
40 | return sendUserId;
41 | }
42 |
43 | /**
44 | * @param sendUserId
45 | */
46 | public void setSendUserId(String sendUserId) {
47 | this.sendUserId = sendUserId;
48 | }
49 |
50 | /**
51 | * @return accept_user_id
52 | */
53 | public String getAcceptUserId() {
54 | return acceptUserId;
55 | }
56 |
57 | /**
58 | * @param acceptUserId
59 | */
60 | public void setAcceptUserId(String acceptUserId) {
61 | this.acceptUserId = acceptUserId;
62 | }
63 |
64 | /**
65 | * @return request_time
66 | */
67 | public Date getRequestTime() {
68 | return requestTime;
69 | }
70 |
71 | /**
72 | * @param requestTime
73 | */
74 | public void setRequestTime(Date requestTime) {
75 | this.requestTime = requestTime;
76 | }
77 | }
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/pojo/MyFriends.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.pojo;
2 |
3 | import javax.persistence.Column;
4 | import javax.persistence.Id;
5 | import javax.persistence.Table;
6 |
7 | @Table(name = "my_friends")
8 | public class MyFriends {
9 | @Id
10 | private String id;
11 |
12 | @Column(name = "my_user_id")
13 | private String myUserId;
14 |
15 | @Column(name = "my_friend_user_id")
16 | private String myFriendUserId;
17 |
18 | /**
19 | * @return id
20 | */
21 | public String getId() {
22 | return id;
23 | }
24 |
25 | /**
26 | * @param id
27 | */
28 | public void setId(String id) {
29 | this.id = id;
30 | }
31 |
32 | /**
33 | * @return my_user_id
34 | */
35 | public String getMyUserId() {
36 | return myUserId;
37 | }
38 |
39 | /**
40 | * @param myUserId
41 | */
42 | public void setMyUserId(String myUserId) {
43 | this.myUserId = myUserId;
44 | }
45 |
46 | /**
47 | * @return my_friend_user_id
48 | */
49 | public String getMyFriendUserId() {
50 | return myFriendUserId;
51 | }
52 |
53 | /**
54 | * @param myFriendUserId
55 | */
56 | public void setMyFriendUserId(String myFriendUserId) {
57 | this.myFriendUserId = myFriendUserId;
58 | }
59 | }
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/pojo/bo/AddFriendRequst.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.pojo.bo;
2 |
3 | import com.ycw.im.imsingel.Mobilewechat.enums.AddFriendRequstEnum;
4 | import lombok.Data;
5 |
6 | /**
7 | * @Author yuchunwei
8 | */
9 | @Data
10 | public class AddFriendRequst {
11 | private String myUserId;
12 | private String friendUsername;
13 | private String friendId;
14 | private String date;
15 | private int status = AddFriendRequstEnum.UNHANDLED.getCode();
16 | }
17 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/pojo/bo/HandleFriendRequest.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.pojo.bo;
2 |
3 | import lombok.Data;
4 |
5 | /**
6 | * @Author yuchunwei
7 | */
8 | @Data
9 | public class HandleFriendRequest {
10 | private String acceptUserId;
11 | private String sendUserId;
12 | private String operType;
13 | private int status;
14 | }
15 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/pojo/bo/UserBo.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.pojo.bo;
2 |
3 | import lombok.Data;
4 |
5 | /**
6 | * @Author yuchunwei
7 | */
8 | @Data
9 | public class UserBo {
10 | private String userId;
11 | private String faceData;
12 | private String nickname;
13 | }
14 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/pojo/vo/QueryAddFriendRequestVo.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.pojo.vo;
2 |
3 | import lombok.Data;
4 |
5 | /**
6 | * @Author yuchunwei
7 | */
8 | @Data
9 | public class QueryAddFriendRequestVo {
10 | private String sendUserId;
11 | private String sendNickname;
12 | private String sendFaceImage;
13 | }
14 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/pojo/vo/QueryAllFriendVo.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.pojo.vo;
2 |
3 | import lombok.Data;
4 |
5 | /**
6 | * @Author yuchunwei
7 | */
8 | @Data
9 | public class QueryAllFriendVo {
10 | private String friendUserId;
11 | private String friendNickname;
12 | private String friendFaceImage;
13 | }
14 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/pojo/vo/UserVoResult.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.pojo.vo;
2 |
3 | import lombok.Data;
4 |
5 | /**
6 | * @Author yuchunwei
7 | */
8 | @Data
9 | public class UserVoResult {
10 | private String username;
11 | private String faceImage;
12 | private String faceImageBig;
13 | private String nickname;
14 | private String qrcode;
15 | private String userId;
16 | }
17 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/service/ChatService.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.service;
2 |
3 | import com.ycw.im.imsingel.Mobilewechat.pojo.ChatMsg;
4 | import com.ycw.im.imsingel.Mobilewechat.pojo.DataResult;
5 |
6 | import java.util.List;
7 |
8 | public interface ChatService {
9 | int insertMsg(ChatMsg msg);
10 |
11 | DataResult queryUnSignMsgs(String accpetId);
12 |
13 | void updateMsgToSign(List ids);
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/service/FriendService.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.service;
2 |
3 | import com.ycw.im.imsingel.Mobilewechat.pojo.DataResult;
4 | import com.ycw.im.imsingel.Mobilewechat.pojo.bo.AddFriendRequst;
5 | import com.ycw.im.imsingel.Mobilewechat.pojo.bo.HandleFriendRequest;
6 |
7 | /**
8 | * @Author yuchunwei
9 | */
10 | public interface FriendService {
11 | DataResult addFriend(AddFriendRequst requst);
12 |
13 | DataResult queryFriendRequest(String userId);
14 |
15 | DataResult operFriendRequest(HandleFriendRequest request);
16 |
17 | DataResult getAllFriend(String userId);
18 | }
19 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/service/UserService.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.service;
2 |
3 | import com.ycw.im.imsingel.Mobilewechat.pojo.Users;
4 | import com.ycw.im.imsingel.Mobilewechat.pojo.DataResult;
5 | import com.ycw.im.imsingel.Mobilewechat.pojo.bo.AddFriendRequst;
6 | import com.ycw.im.imsingel.Mobilewechat.pojo.bo.UserBo;
7 |
8 | public interface UserService {
9 | DataResult queryUsername(String username);
10 |
11 | DataResult registor(String username, String password);
12 |
13 | DataResult login(Users users);
14 |
15 | DataResult upLoadImage(UserBo userBo);
16 |
17 | DataResult setNickName(UserBo userBo);
18 |
19 | DataResult searchFriend(AddFriendRequst requst);
20 |
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/service/impl/ChatServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.service.impl;
2 |
3 | import com.ycw.im.imsingel.Mobilewechat.mapper.ChatMsgMapper;
4 | import com.ycw.im.imsingel.Mobilewechat.pojo.ChatMsg;
5 | import com.ycw.im.imsingel.Mobilewechat.pojo.DataResult;
6 | import com.ycw.im.imsingel.Mobilewechat.service.ChatService;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.stereotype.Service;
9 |
10 | import java.util.List;
11 |
12 | /**
13 | * @Author yuchunwei
14 | */
15 | @Service
16 | public class ChatServiceImpl implements ChatService {
17 | @Autowired
18 | private ChatMsgMapper msgMapper;
19 |
20 | @Override
21 | public DataResult queryUnSignMsgs(String acceptUserId) {
22 | List chatMsgs = msgMapper.queryUnSignMsgs(acceptUserId);
23 | return DataResult.ok(chatMsgs);
24 | }
25 |
26 | @Override
27 | public int insertMsg(ChatMsg msg) {
28 | return msgMapper.insertMsg(msg);
29 | }
30 |
31 | @Override
32 | public void updateMsgToSign(List ids) {
33 | msgMapper.updateMsgToSign(ids);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/utils/JsonUtils.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.utils;
2 |
3 | import java.util.List;
4 |
5 | import com.fasterxml.jackson.core.JsonProcessingException;
6 | import com.fasterxml.jackson.databind.JavaType;
7 | import com.fasterxml.jackson.databind.ObjectMapper;
8 |
9 | /**
10 | * @Description: 自定义响应结构, 转换类
11 | */
12 | public class JsonUtils {
13 |
14 | // 定义jackson对象
15 | private static final ObjectMapper MAPPER = new ObjectMapper();
16 |
17 | /**
18 | * 将对象转换成json字符串。
19 | * Title: pojoToJson
20 | * Description:
21 | *
22 | * @param data
23 | * @return
24 | */
25 | public static String objectToJson(Object data) {
26 | try {
27 | String string = MAPPER.writeValueAsString(data);
28 | return string;
29 | } catch (JsonProcessingException e) {
30 | e.printStackTrace();
31 | }
32 | return null;
33 | }
34 |
35 | /**
36 | * 将json结果集转化为对象
37 | *
38 | * @param jsonData json数据
39 | * @param clazz 对象中的object类型
40 | * @return
41 | */
42 | public static T jsonToPojo(String jsonData, Class beanType) {
43 | try {
44 | T t = MAPPER.readValue(jsonData, beanType);
45 | return t;
46 | } catch (Exception e) {
47 | e.printStackTrace();
48 | }
49 | return null;
50 | }
51 |
52 | /**
53 | * 将json数据转换成pojo对象list
54 | * Title: jsonToList
55 | * Description:
56 | *
57 | * @param jsonData
58 | * @param beanType
59 | * @return
60 | */
61 | public static List jsonToList(String jsonData, Class beanType) {
62 | JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
63 | try {
64 | List list = MAPPER.readValue(jsonData, javaType);
65 | return list;
66 | } catch (Exception e) {
67 | e.printStackTrace();
68 | }
69 |
70 | return null;
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/utils/MD5Utils.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.utils;
2 |
3 | import org.apache.tomcat.util.codec.binary.Base64;
4 |
5 | import java.security.MessageDigest;
6 |
7 |
8 | public class MD5Utils {
9 |
10 | /**
11 | * @Description: 对字符串进行md5加密
12 | */
13 | public static String getMD5Str(String strValue) throws Exception {
14 | MessageDigest md5 = MessageDigest.getInstance("MD5");
15 | String newstr = Base64.encodeBase64String(md5.digest(strValue.getBytes()));
16 | return newstr;
17 | }
18 |
19 | public static void main(String[] args) {
20 | try {
21 | String md5 = getMD5Str("hello everything");
22 | System.out.println(md5);
23 | } catch (Exception e) {
24 | e.printStackTrace();
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Mobilewechat/utils/SpringUtil.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Mobilewechat.utils;
2 |
3 | import org.springframework.beans.BeansException;
4 | import org.springframework.context.ApplicationContext;
5 | import org.springframework.context.ApplicationContextAware;
6 | import org.springframework.stereotype.Component;
7 |
8 | /**
9 | * @Description: 提供手动获取被spring管理的bean对象
10 | */
11 | @Component
12 | public class SpringUtil implements ApplicationContextAware {
13 |
14 | private static ApplicationContext applicationContext;
15 |
16 | @Override
17 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
18 | if (SpringUtil.applicationContext == null) {
19 | SpringUtil.applicationContext = applicationContext;
20 | }
21 | }
22 |
23 | // 获取applicationContext
24 | public static ApplicationContext getApplicationContext() {
25 | return applicationContext;
26 | }
27 |
28 | // 通过name获取 Bean.
29 | public static Object getBean(String name) {
30 | return getApplicationContext().getBean(name);
31 | }
32 |
33 | // 通过class获取Bean.
34 | public static T getBean(Class clazz) {
35 | return getApplicationContext().getBean(clazz);
36 | }
37 |
38 | // 通过name,以及Clazz返回指定的Bean
39 | public static T getBean(String name, Class clazz) {
40 | return getApplicationContext().getBean(name, clazz);
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/NettyBoots.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel;
2 |
3 | import com.ycw.im.imsingel.Mobilewechat.netty.Server;
4 | import com.ycw.im.imsingel.Webwechat.web.websocket.WebSocketServer;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.context.ApplicationListener;
7 | import org.springframework.context.event.ContextRefreshedEvent;
8 | import org.springframework.stereotype.Component;
9 |
10 | import java.util.List;
11 |
12 | /**
13 | * @Author yuchunwei
14 | * 在springboot上下文启动期间,启动netty服务器
15 | */
16 | @Component
17 | public class NettyBoots implements ApplicationListener {
18 | @Autowired
19 | private WebSocketServer webNettyServer;
20 |
21 | @Override
22 | public void onApplicationEvent(ContextRefreshedEvent event) {
23 |
24 | if (event.getApplicationContext().getParent() == null) {
25 | try {
26 | Server.getInstance().start(8088);
27 | // webNettyServer.build(3333);
28 | } catch (Exception e) {
29 | e.printStackTrace();
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/WebApplication.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel;
2 |
3 | import org.mybatis.spring.annotation.MapperScan;
4 | import org.springframework.boot.SpringApplication;
5 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
6 | import org.springframework.boot.autoconfigure.SpringBootApplication;
7 |
8 |
9 | /**
10 | * @Author yuchunwei
11 | */
12 | @SpringBootApplication
13 | //@ComponentScan({"com.blog"})
14 | //@ServletComponentScan
15 | @MapperScan(basePackages = "com.ycw.im.imsingel.Mobilewechat.mapper")
16 | @EnableAutoConfiguration
17 | public class WebApplication {
18 | public static void main(String[] args) {
19 | SpringApplication.run(WebApplication.class, args);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Webwechat/dao/GroupInfoDao.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Webwechat.dao;
2 |
3 |
4 | import com.ycw.im.imsingel.Webwechat.model.po.GroupInfo;
5 |
6 | public interface GroupInfoDao {
7 |
8 | void loadGroupInfo();
9 |
10 | GroupInfo getByGroupId(String groupId);
11 | }
12 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Webwechat/dao/UserInfoDao.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Webwechat.dao;
2 |
3 | import com.ycw.im.imsingel.Webwechat.model.po.UserInfo;
4 |
5 | public interface UserInfoDao {
6 |
7 | void loadUserInfo();
8 |
9 | UserInfo getByUsername(String username);
10 |
11 | UserInfo getByUserId(String userId);
12 | }
13 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Webwechat/dao/impl/GroupInfoDaoImpl.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Webwechat.dao.impl;
2 |
3 | import org.springframework.stereotype.Repository;
4 | import com.ycw.im.imsingel.Webwechat.dao.GroupInfoDao;
5 | import com.ycw.im.imsingel.Webwechat.model.po.GroupInfo;
6 | import com.ycw.im.imsingel.Webwechat.model.po.UserInfo;
7 | import com.ycw.im.imsingel.Webwechat.util.Constant;
8 |
9 | import java.util.ArrayList;
10 | import java.util.List;
11 |
12 | @Repository
13 | public class GroupInfoDaoImpl implements GroupInfoDao {
14 |
15 | @Override
16 | public void loadGroupInfo() {
17 | UserInfo userInfo = new UserInfo("001", "Member001", "001", "static/img/avatar/Member001.jpg");
18 | UserInfo userInfo2 = new UserInfo("002", "Member002", "002", "static/img/avatar/Member002.jpg");
19 | UserInfo userInfo3 = new UserInfo("003", "Member003", "003", "static/img/avatar/Member003.jpg");
20 | UserInfo userInfo4 = new UserInfo("004", "Member004", "004", "static/img/avatar/Member004.jpg");
21 | UserInfo userInfo5 = new UserInfo("005", "Member005", "005", "static/img/avatar/Member005.jpg");
22 | UserInfo userInfo6 = new UserInfo("006", "Member006", "006", "static/img/avatar/Member006.jpg");
23 | UserInfo userInfo7 = new UserInfo("007", "Member007", "007", "static/img/avatar/Member007.jpg");
24 | UserInfo userInfo8 = new UserInfo("008", "Member008", "008", "static/img/avatar/Member008.jpg");
25 | UserInfo userInfo9 = new UserInfo("009", "Member009", "009", "static/img/avatar/Member009.jpg");
26 | List members = new ArrayList();
27 | members.add(userInfo);
28 | members.add(userInfo2);
29 | members.add(userInfo3);
30 | members.add(userInfo4);
31 | members.add(userInfo5);
32 | members.add(userInfo6);
33 | members.add(userInfo7);
34 | members.add(userInfo8);
35 | members.add(userInfo9);
36 | GroupInfo groupInfo = new GroupInfo("01", "Group01", "static/img/avatar/Group01.jpg", members);
37 | Constant.groupInfoMap.put(groupInfo.getGroupId(), groupInfo);
38 | }
39 |
40 | @Override
41 | public GroupInfo getByGroupId(String groupId) {
42 | return Constant.groupInfoMap.get(groupId);
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Webwechat/model/po/GroupInfo.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Webwechat.model.po;
2 |
3 | import java.util.List;
4 |
5 | public class GroupInfo {
6 |
7 | private String groupId;
8 | private String groupName;
9 | private String groupAvatarUrl;
10 | private List members;
11 |
12 | public GroupInfo(String groupId, String groupName, String groupAvatarUrl, List members) {
13 | super();
14 | this.groupId = groupId;
15 | this.groupName = groupName;
16 | this.groupAvatarUrl = groupAvatarUrl;
17 | this.members = members;
18 | }
19 |
20 | public String getGroupId() {
21 | return groupId;
22 | }
23 |
24 | public void setGroupId(String groupId) {
25 | this.groupId = groupId;
26 | }
27 |
28 | public List getMembers() {
29 | return members;
30 | }
31 |
32 | public void setMembers(List members) {
33 | this.members = members;
34 | }
35 |
36 | public String getGroupName() {
37 | return groupName;
38 | }
39 |
40 | public void setGroupName(String groupName) {
41 | this.groupName = groupName;
42 | }
43 |
44 | public String getGroupAvatarUrl() {
45 | return groupAvatarUrl;
46 | }
47 |
48 | public void setGroupAvatarUrl(String groupAvatarUrl) {
49 | this.groupAvatarUrl = groupAvatarUrl;
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Webwechat/model/po/UserInfo.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Webwechat.model.po;
2 |
3 | import java.util.List;
4 |
5 | public class UserInfo {
6 |
7 | private String userId;
8 | private String username;
9 | private String password;
10 | private String avatarUrl;
11 | private List friendList;
12 | private List groupList;
13 |
14 | public UserInfo() {
15 | super();
16 | }
17 |
18 | public UserInfo(String userId, String username, String password, String avatarUrl) {
19 | super();
20 | this.userId = userId;
21 | this.username = username;
22 | this.password = password;
23 | this.avatarUrl = avatarUrl;
24 | }
25 |
26 | public String getUserId() {
27 | return userId;
28 | }
29 |
30 | public void setUserId(String userId) {
31 | this.userId = userId;
32 | }
33 |
34 | public String getUsername() {
35 | return username;
36 | }
37 |
38 | public void setUsername(String username) {
39 | this.username = username;
40 | }
41 |
42 | public String getPassword() {
43 | return password;
44 | }
45 |
46 | public void setPassword(String password) {
47 | this.password = password;
48 | }
49 |
50 | public String getAvatarUrl() {
51 | return avatarUrl;
52 | }
53 |
54 | public void setAvatarUrl(String avatarUrl) {
55 | this.avatarUrl = avatarUrl;
56 | }
57 |
58 | public List getFriendList() {
59 | return friendList;
60 | }
61 |
62 | public void setFriendList(List friendList) {
63 | this.friendList = friendList;
64 | }
65 |
66 | public List getGroupList() {
67 | return groupList;
68 | }
69 |
70 | public void setGroupList(List groupList) {
71 | this.groupList = groupList;
72 | }
73 |
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Webwechat/model/vo/ResponseJson.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Webwechat.model.vo;
2 |
3 | import com.alibaba.fastjson.JSONObject;
4 | import org.springframework.http.HttpStatus;
5 |
6 | import java.util.HashMap;
7 |
8 | public class ResponseJson extends HashMap {
9 | private static final long serialVersionUID = 1L;
10 |
11 | private static final Integer SUCCESS_STATUS = 200;
12 | private static final Integer ERROR_STATUS = -1;
13 | private static final String SUCCESS_MSG = "一切正常";
14 |
15 | public ResponseJson() {
16 | super();
17 | }
18 |
19 | public ResponseJson(int code) {
20 | super();
21 | setStatus(code);
22 | }
23 |
24 | public ResponseJson(HttpStatus status) {
25 | super();
26 | setStatus(status.value());
27 | setMsg(status.getReasonPhrase());
28 | }
29 |
30 | public ResponseJson success() {
31 | put("msg", SUCCESS_MSG);
32 | put("status", SUCCESS_STATUS);
33 | return this;
34 | }
35 |
36 | public ResponseJson success(String msg) {
37 | put("msg", msg);
38 | put("status", SUCCESS_STATUS);
39 | return this;
40 | }
41 |
42 | public ResponseJson error(String msg) {
43 | put("msg", msg);
44 | put("status", ERROR_STATUS);
45 | return this;
46 | }
47 |
48 | public ResponseJson setData(String key, Object obj) {
49 | @SuppressWarnings("unchecked")
50 | HashMap data = (HashMap) get("data");
51 | if (data == null) {
52 | data = new HashMap();
53 | put("data", data);
54 | }
55 | data.put(key, obj);
56 | return this;
57 | }
58 |
59 | public ResponseJson setStatus(int status) {
60 | put("status", status);
61 | return this;
62 | }
63 |
64 | public ResponseJson setMsg(String msg) {
65 | put("msg", msg);
66 | return this;
67 | }
68 |
69 | public ResponseJson setValue(String key, Object val) {
70 | put(key, val);
71 | return this;
72 | }
73 |
74 | /**
75 | * 返回JSON字符串
76 | */
77 | @Override
78 | public String toString() {
79 | return JSONObject.toJSONString(this);
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Webwechat/service/ChatService.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Webwechat.service;
2 |
3 | import com.alibaba.fastjson.JSONObject;
4 | import io.netty.channel.ChannelHandlerContext;
5 |
6 | public interface ChatService {
7 |
8 | public void register(JSONObject param, ChannelHandlerContext ctx);
9 |
10 | public void singleSend(JSONObject param, ChannelHandlerContext ctx);
11 |
12 | public void groupSend(JSONObject param, ChannelHandlerContext ctx);
13 |
14 | public void FileMsgSingleSend(JSONObject param, ChannelHandlerContext ctx);
15 |
16 | public void FileMsgGroupSend(JSONObject param, ChannelHandlerContext ctx);
17 |
18 | public void remove(ChannelHandlerContext ctx);
19 |
20 | public void typeError(ChannelHandlerContext ctx);
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Webwechat/service/FileUploadService.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Webwechat.service;
2 |
3 | import org.springframework.web.multipart.MultipartFile;
4 | import com.ycw.im.imsingel.Webwechat.model.vo.ResponseJson;
5 |
6 | import javax.servlet.http.HttpServletRequest;
7 |
8 | public interface FileUploadService {
9 |
10 | ResponseJson upload(MultipartFile file, HttpServletRequest request);
11 | }
12 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Webwechat/service/SecurityService.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Webwechat.service;
2 |
3 | import com.ycw.im.imsingel.Webwechat.model.vo.ResponseJson;
4 |
5 | import javax.servlet.http.HttpSession;
6 |
7 | public interface SecurityService {
8 |
9 | ResponseJson login(String username, String password, HttpSession session);
10 |
11 | ResponseJson logout(HttpSession session);
12 | }
13 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Webwechat/service/UserInfoService.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Webwechat.service;
2 |
3 | import com.ycw.im.imsingel.Webwechat.model.vo.ResponseJson;
4 |
5 | public interface UserInfoService {
6 |
7 | ResponseJson getByUserId(String userId);
8 | }
9 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Webwechat/service/impl/FileUploadServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Webwechat.service.impl;
2 |
3 | import org.springframework.stereotype.Service;
4 | import org.springframework.web.multipart.MultipartFile;
5 | import com.ycw.im.imsingel.Webwechat.model.vo.ResponseJson;
6 | import com.ycw.im.imsingel.Webwechat.service.FileUploadService;
7 | import com.ycw.im.imsingel.Webwechat.util.FileUtils;
8 |
9 | import javax.servlet.http.HttpServletRequest;
10 | import java.io.IOException;
11 | import java.nio.file.Files;
12 | import java.nio.file.Path;
13 | import java.nio.file.Paths;
14 | import java.util.UUID;
15 |
16 | @Service
17 | public class FileUploadServiceImpl implements FileUploadService {
18 |
19 | private final static String SERVER_URL_PREFIX = "http://localhost:8080/WebSocket/";
20 | private final static String FILE_STORE_PATH = "UploadFile";
21 |
22 | @Override
23 | public ResponseJson upload(MultipartFile file, HttpServletRequest request) {
24 | // 重命名文件,防止重名
25 | String filename = getRandomUUID();
26 | String suffix = "";
27 | String originalFilename = file.getOriginalFilename();
28 | String fileSize = FileUtils.getFormatSize(file.getSize());
29 | // 截取文件的后缀名
30 | if (originalFilename.contains(".")) {
31 | suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
32 | }
33 | filename = filename + suffix;
34 | String prefix = request.getSession().getServletContext().getRealPath("/") + FILE_STORE_PATH;
35 | System.out.println("存储路径为:" + prefix + "\\" + filename);
36 | Path filePath = Paths.get(prefix, filename);
37 | try {
38 | Files.copy(file.getInputStream(), filePath);
39 | } catch (IOException e) {
40 | e.printStackTrace();
41 | return new ResponseJson().error("文件上传发生错误!");
42 | }
43 | return new ResponseJson().success()
44 | .setData("originalFilename", originalFilename)
45 | .setData("fileSize", fileSize)
46 | .setData("fileUrl", SERVER_URL_PREFIX + FILE_STORE_PATH + "\\" + filename);
47 | }
48 |
49 | private String getRandomUUID() {
50 | return UUID.randomUUID().toString().replace("-", "");
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Webwechat/service/impl/SecurityServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Webwechat.service.impl;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.stereotype.Service;
7 | import com.ycw.im.imsingel.Webwechat.dao.UserInfoDao;
8 | import com.ycw.im.imsingel.Webwechat.model.po.UserInfo;
9 | import com.ycw.im.imsingel.Webwechat.model.vo.ResponseJson;
10 | import com.ycw.im.imsingel.Webwechat.service.SecurityService;
11 | import com.ycw.im.imsingel.Webwechat.util.Constant;
12 |
13 | import javax.servlet.http.HttpSession;
14 | import java.text.MessageFormat;
15 |
16 | @Service
17 | public class SecurityServiceImpl implements SecurityService {
18 |
19 | @Autowired
20 | private UserInfoDao userInfoDao;
21 |
22 | private static final Logger LOGGER = LoggerFactory.getLogger(SecurityServiceImpl.class);
23 |
24 |
25 | @Override
26 | public ResponseJson login(String username, String password, HttpSession session) {
27 | UserInfo userInfo = userInfoDao.getByUsername(username);
28 | if (userInfo == null) {
29 | return new ResponseJson().error("不存在该用户名");
30 | }
31 | if (!userInfo.getPassword().equals(password)) {
32 | return new ResponseJson().error("密码不正确");
33 | }
34 | session.setAttribute(Constant.USER_TOKEN, userInfo.getUserId());
35 | return new ResponseJson().success();
36 | }
37 |
38 | @Override
39 | public ResponseJson logout(HttpSession session) {
40 | Object userId = session.getAttribute(Constant.USER_TOKEN);
41 | if (userId == null) {
42 | return new ResponseJson().error("请先登录!");
43 | }
44 | session.removeAttribute(Constant.USER_TOKEN);
45 | LOGGER.info(MessageFormat.format("userId为 {0} 的用户已注销登录!", userId));
46 | return new ResponseJson().success();
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Webwechat/service/impl/UserInfoServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Webwechat.service.impl;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.stereotype.Service;
5 | import com.ycw.im.imsingel.Webwechat.dao.UserInfoDao;
6 | import com.ycw.im.imsingel.Webwechat.model.po.UserInfo;
7 | import com.ycw.im.imsingel.Webwechat.model.vo.ResponseJson;
8 | import com.ycw.im.imsingel.Webwechat.service.UserInfoService;
9 |
10 | @Service
11 | public class UserInfoServiceImpl implements UserInfoService {
12 |
13 | @Autowired
14 | private UserInfoDao userInfoDao;
15 |
16 | @Override
17 | public ResponseJson getByUserId(String userId) {
18 | UserInfo userInfo = userInfoDao.getByUserId(userId);
19 | return new ResponseJson().success()
20 | .setData("userInfo", userInfo);
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Webwechat/util/ChatType.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Webwechat.util;
2 |
3 | public enum ChatType {
4 |
5 | REGISTER, SINGLE_SENDING, GROUP_SENDING, FILE_MSG_SINGLE_SENDING, FILE_MSG_GROUP_SENDING;
6 |
7 | public static void main(String[] args) {
8 | System.out.println(ChatType.REGISTER);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Webwechat/util/Constant.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Webwechat.util;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 | import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;
5 | import com.ycw.im.imsingel.Webwechat.model.po.GroupInfo;
6 | import com.ycw.im.imsingel.Webwechat.model.po.UserInfo;
7 |
8 | import java.util.HashMap;
9 | import java.util.Map;
10 | import java.util.concurrent.ConcurrentHashMap;
11 |
12 | /**
13 | * 描述: 全局常量
14 | * 1. USER_TOKEN 用户认证的键,用来匹配http session中的对应userId;
15 | * 2. webSocketServerHandshaker表,用channelId为键,存放握手实例。用来响应CloseWebSocketFrame的请求;
16 | * 3. onlineUser表,用userId为键,存放在线的客户端连接上下文;
17 | * 4. groupInfo表,用groupId为键,存放群信息;
18 | * 5. userInfo表,用username为键,存放用户信息。
19 | *
20 | * @author Kanarien
21 | * @version 1.0
22 | * @date 2018年5月18日 下午9:17:35
23 | */
24 | public class Constant {
25 |
26 | public static final String USER_TOKEN = "userId";
27 |
28 | public static Map webSocketHandshakerMap =
29 | new ConcurrentHashMap();
30 |
31 | public static Map onlineUserMap =
32 | new ConcurrentHashMap();
33 |
34 | public static Map groupInfoMap =
35 | new ConcurrentHashMap();
36 |
37 | public static Map userInfoMap =
38 | new HashMap();
39 | }
40 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Webwechat/util/JsonMsgHelper.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Webwechat.util;
2 |
3 | import com.fasterxml.jackson.core.JsonGenerationException;
4 | import com.fasterxml.jackson.databind.JsonMappingException;
5 | import com.fasterxml.jackson.databind.ObjectMapper;
6 | import org.springframework.http.HttpStatus;
7 |
8 | import javax.servlet.http.HttpServletResponse;
9 | import java.io.IOException;
10 | import java.io.Writer;
11 |
12 | public class JsonMsgHelper {
13 |
14 | private static final ObjectMapper JSONMAPPER = new ObjectMapper();
15 |
16 | public static void writeJson(HttpServletResponse response, Object pojo, HttpStatus status)
17 | throws JsonGenerationException, JsonMappingException, IOException {
18 | response.setContentType("application/json;charset=UTF-8");
19 | response.setStatus(status.value());
20 | writeJson(response.getWriter(), pojo);
21 | }
22 |
23 | public static void writeJson(Writer writer, Object pojo)
24 | throws JsonGenerationException, JsonMappingException, IOException {
25 | JSONMAPPER.writeValue(writer, pojo);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Webwechat/web/config/WebConfig.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Webwechat.web.config;
2 |
3 | import org.springframework.context.annotation.Configuration;
4 | import org.springframework.stereotype.Component;
5 | import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
6 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
7 |
8 | /**
9 | * @Author yuchunwei
10 | */
11 | @Configuration
12 | public abstract class WebConfig implements WebMvcConfigurer {
13 | public void addResourceHandlers(ResourceHandlerRegistry registry) {
14 | registry.addResourceHandler("/public/**").addResourceLocations("classpath:/public/");
15 | registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Webwechat/web/controller/ChatroomController.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Webwechat.web.controller;
2 |
3 |
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.stereotype.Controller;
6 | import org.springframework.web.bind.annotation.RequestMapping;
7 | import org.springframework.web.bind.annotation.RequestMethod;
8 | import org.springframework.web.bind.annotation.ResponseBody;
9 | import com.ycw.im.imsingel.Webwechat.model.vo.ResponseJson;
10 | import com.ycw.im.imsingel.Webwechat.service.UserInfoService;
11 | import com.ycw.im.imsingel.Webwechat.util.Constant;
12 | import org.springframework.web.servlet.ModelAndView;
13 |
14 | import javax.servlet.http.HttpSession;
15 |
16 | @Controller
17 | public class ChatroomController {
18 |
19 | @Autowired
20 | UserInfoService userInfoService;
21 |
22 | /**
23 | * 描述:登录成功后,调用此接口进行页面跳转
24 | *
25 | * @return
26 | */
27 | @RequestMapping(value = "/chatroom")
28 | public ModelAndView toChatroom(HttpSession session) {
29 | Object userId = session.getAttribute(Constant.USER_TOKEN);
30 | if (userId == null) return new ModelAndView("login.html");
31 | return new ModelAndView("chatroom.html");
32 | }
33 |
34 | /**
35 | * 描述:登录成功跳转页面后,调用此接口获取用户信息
36 | *
37 | * @return
38 | */
39 | @RequestMapping(value = "/chatroom/get_userinfo", method = RequestMethod.POST)
40 | @ResponseBody
41 | public ResponseJson getUserInfo(HttpSession session) {
42 | Object userId = session.getAttribute(Constant.USER_TOKEN);
43 | return userInfoService.getByUserId((String) userId);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Webwechat/web/controller/FileUploadController.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Webwechat.web.controller;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.stereotype.Controller;
5 | import org.springframework.web.bind.annotation.RequestMapping;
6 | import org.springframework.web.bind.annotation.RequestParam;
7 | import org.springframework.web.bind.annotation.ResponseBody;
8 | import org.springframework.web.multipart.MultipartFile;
9 | import com.ycw.im.imsingel.Webwechat.model.vo.ResponseJson;
10 | import com.ycw.im.imsingel.Webwechat.service.FileUploadService;
11 |
12 | import javax.servlet.http.HttpServletRequest;
13 |
14 | import static org.springframework.web.bind.annotation.RequestMethod.POST;
15 |
16 | @Controller
17 | @RequestMapping("/chatroom")
18 | public class FileUploadController {
19 |
20 | @Autowired
21 | private FileUploadService fileUploadService;
22 |
23 | @RequestMapping(value = "/upload", method = POST)
24 | @ResponseBody
25 | public ResponseJson upload(
26 | @RequestParam(value = "file", required = true) MultipartFile file, HttpServletRequest request) {
27 | return fileUploadService.upload(file, request);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Webwechat/web/controller/LoginController.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Webwechat.web.controller;
2 |
3 | import com.ycw.im.imsingel.Mobilewechat.controller.UserController;
4 | import com.ycw.im.imsingel.Mobilewechat.pojo.DataResult;
5 | import com.ycw.im.imsingel.Mobilewechat.pojo.Users;
6 | import com.ycw.im.imsingel.Mobilewechat.service.UserService;
7 | import com.ycw.im.imsingel.Webwechat.service.impl.SecurityServiceImpl;
8 | import com.ycw.im.imsingel.Webwechat.util.Constant;
9 | import org.slf4j.Logger;
10 | import org.slf4j.LoggerFactory;
11 | import org.springframework.beans.factory.annotation.Autowired;
12 | import org.springframework.stereotype.Controller;
13 | import org.springframework.ui.Model;
14 | import org.springframework.web.bind.annotation.*;
15 | import com.ycw.im.imsingel.Webwechat.model.vo.ResponseJson;
16 | import com.ycw.im.imsingel.Webwechat.service.SecurityService;
17 | import org.springframework.web.servlet.ModelAndView;
18 |
19 | import javax.servlet.http.HttpSession;
20 | import java.text.MessageFormat;
21 |
22 | @Controller
23 | @RestController
24 | public class LoginController {
25 |
26 | private static final Logger LOGGER = LoggerFactory.getLogger(LoginController.class);
27 |
28 | @Autowired
29 | private UserService userService;
30 |
31 | @RequestMapping(value = {"login", "/"}, method = RequestMethod.GET)
32 | public ModelAndView toLogin() {
33 | return new ModelAndView("login.html");
34 | }
35 |
36 | @PostMapping("/login")
37 | @ResponseBody
38 | public DataResult login(HttpSession session, Users users) {
39 | if (UserController.isVaild(users.getUsername(), users.getPassword())) {
40 | return DataResult.errorMsg("密码或者用户名不能为空");
41 | }
42 | DataResult result = userService.login(users);
43 | if (result.getStatus() == 200) {
44 | session.setAttribute(Constant.USER_TOKEN, users.getId());
45 | }
46 | return result;
47 | }
48 |
49 | @PostMapping("/logout")
50 | @ResponseBody
51 | public DataResult logout(HttpSession session) {
52 | Object userId = session.getAttribute(Constant.USER_TOKEN);
53 | if (userId == null) {
54 | return DataResult.errorMsg("请先登陆");
55 | }
56 | session.removeAttribute(Constant.USER_TOKEN);
57 | LOGGER.info(MessageFormat.format("userId为 {0} 的用户已注销登录!", userId));
58 | return DataResult.ok();
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Webwechat/web/interceptor/UserAuthInteceptor.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Webwechat.web.interceptor;
2 |
3 | import org.springframework.web.servlet.HandlerInterceptor;
4 | import org.springframework.web.servlet.ModelAndView;
5 | import com.ycw.im.imsingel.Webwechat.util.Constant;
6 |
7 | import javax.servlet.http.HttpServletRequest;
8 | import javax.servlet.http.HttpServletResponse;
9 | import javax.servlet.http.HttpSession;
10 |
11 | public class UserAuthInteceptor implements HandlerInterceptor {
12 |
13 | @Override
14 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
15 | throws Exception {
16 | HttpSession session = request.getSession();
17 | Object userToken = session.getAttribute(Constant.USER_TOKEN);
18 | if (userToken == null) {
19 | /*JsonMsgHelper.writeJson(response, new ResponseJson(HttpStatus.FORBIDDEN).setMsg("请登录"),
20 | HttpStatus.FORBIDDEN);*/
21 | response.sendRedirect("login");
22 | return false;
23 | }
24 | return true;
25 | }
26 |
27 | @Override
28 | public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
29 | ModelAndView modelAndView) throws Exception {
30 | response.setHeader("Access-Control-Allow-Origin", "*");
31 | response.setHeader("Access-Control-Allow-Credentials", "true");
32 | }
33 |
34 | @Override
35 | public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
36 | throws Exception {
37 |
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/Webwechat/web/websocket/WebSocketChildChannelHandler.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.Webwechat.web.websocket;
2 |
3 | import io.netty.channel.ChannelHandler;
4 | import io.netty.channel.ChannelInitializer;
5 | import io.netty.channel.socket.SocketChannel;
6 | import io.netty.handler.codec.http.HttpObjectAggregator;
7 | import io.netty.handler.codec.http.HttpServerCodec;
8 | import io.netty.handler.stream.ChunkedWriteHandler;
9 | import org.springframework.stereotype.Component;
10 |
11 | import javax.annotation.Resource;
12 |
13 | @Component
14 | public class WebSocketChildChannelHandler extends ChannelInitializer {
15 |
16 | @Resource(name = "webSocketServerHandler")
17 | private ChannelHandler webSocketServerHandler;
18 |
19 | @Resource(name = "httpRequestHandler")
20 | private ChannelHandler httpRequestHandler;
21 |
22 | @Override
23 | protected void initChannel(SocketChannel ch) throws Exception {
24 | ch.pipeline().addLast("http-codec", new HttpServerCodec()); // HTTP编码解码器
25 | ch.pipeline().addLast("aggregator", new HttpObjectAggregator(65536)); // 把HTTP头、HTTP体拼成完整的HTTP请求
26 | ch.pipeline().addLast("http-chunked", new ChunkedWriteHandler()); // 方便大文件传输,不过实质上都是短的文本数据
27 | ch.pipeline().addLast("http-handler", new HttpRequestHandler());
28 | ch.pipeline().addLast("websocket-handler", new WebSocketServerHandler());
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/learnNettyExample/BrowserAndClient/Init.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.learnNettyExample.BrowserAndClient;
2 |
3 | import io.netty.channel.ChannelInitializer;
4 | import io.netty.channel.socket.SocketChannel;
5 | import io.netty.handler.codec.http.HttpObjectAggregator;
6 | import io.netty.handler.codec.http.HttpServerCodec;
7 |
8 | /**
9 | * @Author yuchunwei
10 | */
11 | public class Init extends ChannelInitializer {
12 |
13 | @Override
14 | protected void initChannel(SocketChannel channel) throws Exception {
15 | channel.pipeline().addLast(new HttpServerCodec());
16 | channel.pipeline().addLast(new HttpObjectAggregator(512 * 1024));
17 | channel.pipeline().addLast(new ResponseHandler());
18 | }
19 |
20 | public static void main(String[] args) {
21 |
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/learnNettyExample/BrowserAndClient/NettyServer.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.learnNettyExample.BrowserAndClient;
2 |
3 | import io.netty.bootstrap.ServerBootstrap;
4 | import io.netty.channel.ChannelFuture;
5 | import io.netty.channel.nio.NioEventLoopGroup;
6 | import io.netty.channel.socket.nio.NioServerSocketChannel;
7 |
8 | /**
9 | * @Author yuchunwei
10 | */
11 | public class NettyServer {
12 |
13 | public static void init() {
14 | NioEventLoopGroup bossGroup = new NioEventLoopGroup();
15 | NioEventLoopGroup workGroup = new NioEventLoopGroup();
16 | ServerBootstrap server = new ServerBootstrap();
17 | try {
18 | server
19 | .group(bossGroup, workGroup)
20 | .channel(NioServerSocketChannel.class)
21 | .childHandler(new Init());
22 |
23 | ChannelFuture future = server.bind("127.0.0.1", 8088).sync();
24 | future.channel().closeFuture().sync();
25 | } catch (Exception e) {
26 | e.printStackTrace();
27 | } finally {
28 | bossGroup.shutdownGracefully();
29 | workGroup.shutdownGracefully();
30 | }
31 | }
32 |
33 | public static void main(String[] args) {
34 | init();
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/learnNettyExample/BrowserAndClient/ResponseHandler.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.learnNettyExample.BrowserAndClient;
2 |
3 | import io.netty.buffer.ByteBuf;
4 | import io.netty.channel.Channel;
5 | import io.netty.channel.ChannelHandlerContext;
6 | import io.netty.channel.SimpleChannelInboundHandler;
7 | import io.netty.handler.codec.http.*;
8 |
9 | import java.nio.charset.Charset;
10 |
11 | /**
12 | * @Author yuchunwei
13 | */
14 | public class ResponseHandler extends SimpleChannelInboundHandler {
15 |
16 | @Override
17 | protected void channelRead0(ChannelHandlerContext ctx, HttpObject httpObject) throws Exception {
18 | Channel channel = ctx.channel();
19 | ByteBuf byteBuf = ctx.alloc().buffer();
20 | byteBuf.writeBytes("Hello Netty ".getBytes(Charset.forName("UTF-8")));
21 | // ByteBuf content = Unpooled.copiedBuffer("Hello netty~", CharsetUtil.UTF_8);
22 | System.out.println("ip :" + channel.remoteAddress());
23 | FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
24 | HttpResponseStatus.OK, byteBuf);
25 | response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
26 | response.headers().set(HttpHeaderNames.CONTENT_LENGTH, byteBuf.readableBytes());
27 |
28 | ctx.writeAndFlush(response);
29 | }
30 |
31 | public static void main(String[] args) {
32 |
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/learnNettyExample/ClientAndServer/client/handler/LoginResponseHandler.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.learnNettyExample.ClientAndServer.client.handler;
2 |
3 |
4 | import com.ycw.im.imsingel.learnNettyExample.ClientAndServer.protocol.response.LoginResponse;
5 | import com.ycw.im.imsingel.learnNettyExample.ClientAndServer.util.LoginUtil;
6 | import io.netty.channel.ChannelHandlerContext;
7 | import io.netty.channel.SimpleChannelInboundHandler;
8 |
9 |
10 | public class LoginResponseHandler extends SimpleChannelInboundHandler {
11 | @Override
12 | public void channelRead0(ChannelHandlerContext ctx, LoginResponse response) {
13 | System.out.println(response.getMessage());
14 | if (response.isSuccess()) {
15 | LoginUtil.set(ctx.channel());
16 | LoginUtil.setUserName(ctx.channel(), response.getUserName());
17 | ;
18 | }
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/learnNettyExample/ClientAndServer/client/handler/MessageResponseHandler.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.learnNettyExample.ClientAndServer.client.handler;
2 |
3 |
4 | import com.ycw.im.imsingel.learnNettyExample.ClientAndServer.protocol.response.MessageResponse;
5 | import io.netty.channel.ChannelHandlerContext;
6 | import io.netty.channel.SimpleChannelInboundHandler;
7 |
8 | public class MessageResponseHandler extends SimpleChannelInboundHandler {
9 | @Override
10 | public void channelRead0(ChannelHandlerContext ctx, MessageResponse messageResponse) {
11 | if (messageResponse.isUp()) {
12 | System.out.println("收到[" + messageResponse.getFromUserName() + "]消息:");
13 | }
14 | System.out.println(messageResponse.getMessage());
15 |
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/learnNettyExample/ClientAndServer/codec/Codec.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.learnNettyExample.ClientAndServer.codec;
2 |
3 | import com.ycw.im.imsingel.learnNettyExample.ClientAndServer.protocol.Packet;
4 | import com.ycw.im.imsingel.learnNettyExample.ClientAndServer.protocol.request.LoginRequest;
5 | import com.ycw.im.imsingel.learnNettyExample.ClientAndServer.protocol.request.MessageRequest;
6 | import com.ycw.im.imsingel.learnNettyExample.ClientAndServer.protocol.response.LoginResponse;
7 | import com.ycw.im.imsingel.learnNettyExample.ClientAndServer.protocol.response.MessageResponse;
8 | import com.ycw.im.imsingel.learnNettyExample.ClientAndServer.protocol.serializer.JSONSerializer;
9 | import io.netty.buffer.ByteBuf;
10 |
11 | import java.util.HashMap;
12 |
13 | public class Codec {
14 | private final int MAGIC_NUMBER = 0x12345678;
15 | public static final Codec INSTANCE = new Codec();
16 | private JSONSerializer serializer = new JSONSerializer();
17 | private final HashMap> map = new HashMap<>();
18 |
19 | public Codec() {
20 | map.put(1, LoginRequest.class);
21 | map.put(2, LoginResponse.class);
22 | map.put(3, MessageRequest.class);
23 | map.put(4, MessageResponse.class);
24 | }
25 |
26 | public void encode(ByteBuf byteBuf, Packet packet) {
27 | byte[] bytes = serializer.serialize(packet);
28 |
29 | byteBuf.writeInt(MAGIC_NUMBER);
30 | byteBuf.writeInt((Integer) packet.getCommand());
31 | byteBuf.writeInt(bytes.length);
32 | byteBuf.writeBytes(bytes);
33 | }
34 |
35 | public Packet decode(ByteBuf byteBuf) {
36 | if (byteBuf.readInt() == 0x12345678) {
37 | int command = byteBuf.readInt();
38 | int length = byteBuf.readInt();
39 | byte[] bytes = new byte[length];
40 | byteBuf.readBytes(bytes);
41 | if (map.keySet().contains(command)) {
42 | return serializer.deserialize(map.get(command), bytes);
43 | }
44 | }
45 | return null;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/learnNettyExample/ClientAndServer/codec/nettyCodec/PacketDecoder.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.learnNettyExample.ClientAndServer.codec.nettyCodec;
2 |
3 | import com.ycw.im.imsingel.learnNettyExample.ClientAndServer.codec.Codec;
4 | import io.netty.buffer.ByteBuf;
5 | import io.netty.channel.ChannelHandlerContext;
6 | import io.netty.handler.codec.ByteToMessageDecoder;
7 |
8 | import java.util.List;
9 |
10 | public class PacketDecoder extends ByteToMessageDecoder {
11 | @Override
12 | protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) {
13 | out.add(Codec.INSTANCE.decode(in));
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/learnNettyExample/ClientAndServer/codec/nettyCodec/PacketEncoder.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.learnNettyExample.ClientAndServer.codec.nettyCodec;
2 |
3 | import com.ycw.im.imsingel.learnNettyExample.ClientAndServer.codec.Codec;
4 | import com.ycw.im.imsingel.learnNettyExample.ClientAndServer.protocol.Packet;
5 | import io.netty.buffer.ByteBuf;
6 | import io.netty.channel.ChannelHandlerContext;
7 | import io.netty.handler.codec.MessageToByteEncoder;
8 |
9 |
10 | public class PacketEncoder extends MessageToByteEncoder {
11 | @Override
12 | protected void encode(ChannelHandlerContext ctx, Packet packet, ByteBuf out) {
13 | Codec.INSTANCE.encode(out, packet);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/learnNettyExample/ClientAndServer/protocol/Packet.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.learnNettyExample.ClientAndServer.protocol;
2 |
3 | import com.ycw.im.imsingel.learnNettyExample.ClientAndServer.util.Command;
4 |
5 | public abstract class Packet {
6 | private Command command;
7 |
8 | public abstract Object getCommand();
9 | }
10 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/learnNettyExample/ClientAndServer/protocol/request/LoginRequest.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.learnNettyExample.ClientAndServer.protocol.request;
2 |
3 | import com.ycw.im.imsingel.learnNettyExample.ClientAndServer.protocol.Packet;
4 | import com.ycw.im.imsingel.learnNettyExample.ClientAndServer.util.Command;
5 | import lombok.Data;
6 |
7 | @Data
8 | public class LoginRequest extends Packet {
9 | private String username;
10 | private String password;
11 |
12 | public Integer getCommand() {
13 | return Command.LoginRequest.getCode();
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/learnNettyExample/ClientAndServer/protocol/request/MessageRequest.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.learnNettyExample.ClientAndServer.protocol.request;
2 |
3 | import com.ycw.im.imsingel.learnNettyExample.ClientAndServer.protocol.Packet;
4 | import com.ycw.im.imsingel.learnNettyExample.ClientAndServer.util.Command;
5 | import lombok.Data;
6 |
7 | @Data
8 | public class MessageRequest extends Packet {
9 | private String message;
10 | private String toUserName;
11 | private String fromUsername;
12 |
13 | public MessageRequest() {
14 |
15 | }
16 |
17 | public MessageRequest(String message, String toUserName, String fromUsername) {
18 | this.message = message;
19 | this.toUserName = toUserName;
20 | this.fromUsername = fromUsername;
21 | }
22 |
23 | public Integer getCommand() {
24 | return Command.MessageRequest.getCode();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/learnNettyExample/ClientAndServer/protocol/response/LoginResponse.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.learnNettyExample.ClientAndServer.protocol.response;
2 |
3 | import com.ycw.im.imsingel.learnNettyExample.ClientAndServer.protocol.Packet;
4 | import com.ycw.im.imsingel.learnNettyExample.ClientAndServer.util.Command;
5 | import lombok.Data;
6 |
7 | @Data
8 | public class LoginResponse extends Packet {
9 | private boolean isSuccess;
10 | private String message;
11 | private String userName;
12 |
13 | public Integer getCommand() {
14 | return Command.LoginRespose.getCode();
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/learnNettyExample/ClientAndServer/protocol/response/MessageResponse.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.learnNettyExample.ClientAndServer.protocol.response;
2 |
3 | import com.ycw.im.imsingel.learnNettyExample.ClientAndServer.protocol.Packet;
4 | import com.ycw.im.imsingel.learnNettyExample.ClientAndServer.util.Command;
5 | import lombok.Data;
6 |
7 | @Data
8 | public class MessageResponse extends Packet {
9 | private String message;
10 | private String toUserName;
11 | private String fromUserName;
12 | private boolean isUp;
13 |
14 | public Integer getCommand() {
15 | return Command.MessageResponse.getCode();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/learnNettyExample/ClientAndServer/protocol/serializer/JSONSerializer.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.learnNettyExample.ClientAndServer.protocol.serializer;
2 |
3 | import com.alibaba.fastjson.JSON;
4 |
5 | public class JSONSerializer implements Serializer {
6 |
7 | @Override
8 | public byte getSerializerAlogrithm() {
9 | return SerializerAlogrithm.JSON;
10 | }
11 |
12 | @Override
13 | public byte[] serialize(Object object) {
14 |
15 | return JSON.toJSONBytes(object);
16 | }
17 |
18 | @Override
19 | public T deserialize(Class clazz, byte[] bytes) {
20 |
21 | return JSON.parseObject(bytes, clazz);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/learnNettyExample/ClientAndServer/protocol/serializer/Serializer.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.learnNettyExample.ClientAndServer.protocol.serializer;
2 |
3 | public interface Serializer {
4 |
5 | Serializer DEFAULT = new JSONSerializer();
6 |
7 | /**
8 | * 序列化算法
9 | *
10 | * @return
11 | */
12 | byte getSerializerAlogrithm();
13 |
14 | /**
15 | * java 对象转换成二进制
16 | */
17 | byte[] serialize(Object object);
18 |
19 | /**
20 | * 二进制转换成 java 对象
21 | */
22 | T deserialize(Class clazz, byte[] bytes);
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/learnNettyExample/ClientAndServer/protocol/serializer/SerializerAlogrithm.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.learnNettyExample.ClientAndServer.protocol.serializer;
2 |
3 | public interface SerializerAlogrithm {
4 | /**
5 | * json 序列化
6 | */
7 | byte JSON = 1;
8 | }
9 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/learnNettyExample/ClientAndServer/server/handler/AuthHandler.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.learnNettyExample.ClientAndServer.server.handler;
2 |
3 | import com.ycw.im.imsingel.learnNettyExample.ClientAndServer.util.LoginUtil;
4 | import io.netty.channel.ChannelHandlerContext;
5 | import io.netty.channel.ChannelInboundHandlerAdapter;
6 |
7 | /**
8 | * @Author yuchunwei
9 | */
10 | public class AuthHandler extends ChannelInboundHandlerAdapter {
11 |
12 | @Override
13 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
14 | if (LoginUtil.isLogin(ctx.channel())) {
15 | ctx.pipeline().remove(this);
16 | super.channelRead(ctx, msg);
17 | } else {
18 | ctx.channel().close();
19 | }
20 |
21 | }
22 |
23 | @Override
24 | public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
25 | if (LoginUtil.isLogin(ctx.channel())) {
26 | System.out.println("当前连接登录验证完毕,无需再次验证, AuthHandler 被移除");
27 | } else {
28 | System.out.println("无登录验证,强制关闭连接!");
29 | }
30 | }
31 |
32 | public static void main(String[] args) {
33 |
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/learnNettyExample/ClientAndServer/server/handler/MessageRequestHandler.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.learnNettyExample.ClientAndServer.server.handler;
2 |
3 | import com.ycw.im.imsingel.learnNettyExample.ClientAndServer.protocol.request.MessageRequest;
4 | import com.ycw.im.imsingel.learnNettyExample.ClientAndServer.protocol.response.MessageResponse;
5 | import io.netty.channel.Channel;
6 | import io.netty.channel.ChannelHandlerContext;
7 | import io.netty.channel.SimpleChannelInboundHandler;
8 |
9 | public class MessageRequestHandler extends SimpleChannelInboundHandler {
10 | @Override
11 | public void channelRead0(ChannelHandlerContext ctx, MessageRequest request) {
12 | Channel channel;
13 | MessageResponse messageResponse = new MessageResponse();
14 | System.out.println(request.getFromUsername() + "正在发送消息");
15 | if ((channel = LoginRuqestHandler.chatList.get(request.getToUserName())) != null) {
16 | messageResponse.setMessage(request.getMessage());
17 | messageResponse.setToUserName(request.getToUserName());
18 | messageResponse.setFromUserName(request.getFromUsername());
19 | messageResponse.setUp(true);
20 | channel.writeAndFlush(messageResponse);
21 | } else {
22 | messageResponse.setUp(false);
23 | messageResponse.setMessage("对方没有上线");
24 | ctx.channel().writeAndFlush(messageResponse);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/learnNettyExample/ClientAndServer/util/Command.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.learnNettyExample.ClientAndServer.util;
2 |
3 | public enum Command {
4 | //指令代码
5 | LoginRequest(0x001),
6 | LoginRespose(0x002),
7 | MessageRequest(0x003),
8 | MessageResponse(0x004);
9 |
10 | private int code;
11 |
12 | private Command(int code) {
13 | this.code = code;
14 | }
15 |
16 | public int getCode() {
17 | return code;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/learnNettyExample/ClientAndServer/util/LoginUtil.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.learnNettyExample.ClientAndServer.util;
2 |
3 | import io.netty.channel.Channel;
4 |
5 | public class LoginUtil {
6 | public static void set(Channel channel) {
7 | channel.attr(State.LOGIN).set(true);
8 | }
9 |
10 | public static boolean isLogin(Channel channel) {
11 | return channel.hasAttr(State.LOGIN);
12 | }
13 |
14 | public static String getUserName(Channel channel) {
15 | return channel.attr(State.USERNAME).get();
16 | }
17 |
18 | public static void setUserName(Channel channel, String id) {
19 | channel.attr(State.USERNAME).set(id);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/learnNettyExample/ClientAndServer/util/State.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.learnNettyExample.ClientAndServer.util;
2 |
3 | import io.netty.util.AttributeKey;
4 |
5 | //接口中声明变量默认的是static final
6 | public interface State {
7 | AttributeKey LOGIN = AttributeKey.newInstance("login");
8 | AttributeKey USERNAME = AttributeKey.newInstance("username");
9 | }
10 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/learnNettyExample/WebSocketAndNetty/ChatHandler.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.learnNettyExample.WebSocketAndNetty;
2 |
3 | import io.netty.channel.Channel;
4 | import io.netty.channel.ChannelHandlerContext;
5 | import io.netty.channel.SimpleChannelInboundHandler;
6 | import io.netty.channel.group.ChannelGroup;
7 | import io.netty.channel.group.DefaultChannelGroup;
8 | import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
9 | import io.netty.util.concurrent.GlobalEventExecutor;
10 |
11 | /**
12 | * @Author yuchunwei
13 | */
14 | public class ChatHandler extends SimpleChannelInboundHandler {
15 | private static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
16 |
17 | @Override
18 | protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame msg) throws Exception {
19 | String content = msg.text();
20 | System.out.println("收到的消息" + msg);
21 | //对所有在线的用户广播
22 | for (Channel channel : channels) {
23 | channel.writeAndFlush(new TextWebSocketFrame("广播 :某用户发送了消息" + content));
24 | }
25 |
26 | }
27 |
28 | @Override
29 | public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
30 | channels.add(ctx.channel());
31 | }
32 |
33 | public static void main(String[] args) {
34 |
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/learnNettyExample/WebSocketAndNetty/Init.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.learnNettyExample.WebSocketAndNetty;
2 |
3 | import io.netty.channel.ChannelInitializer;
4 | import io.netty.channel.socket.SocketChannel;
5 | import io.netty.handler.codec.http.HttpObjectAggregator;
6 | import io.netty.handler.codec.http.HttpServerCodec;
7 | import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
8 | import io.netty.handler.stream.ChunkedWriteHandler;
9 |
10 | /**
11 | * @Author yuchunwei
12 | */
13 | public class Init extends ChannelInitializer {
14 |
15 | public static void main(String[] args) {
16 |
17 | }
18 |
19 | @Override
20 | protected void initChannel(SocketChannel socketChannel) throws Exception {
21 | socketChannel.pipeline().addLast(new HttpServerCodec());
22 | socketChannel.pipeline().addLast(new ChunkedWriteHandler());
23 | socketChannel.pipeline().addLast(new HttpObjectAggregator(1024 * 64));
24 |
25 | socketChannel.pipeline().addLast(new WebSocketServerProtocolHandler("/ws"));
26 | socketChannel.pipeline().addLast(null);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/im-singel/src/main/java/com/ycw/im/imsingel/learnNettyExample/WebSocketAndNetty/WsServer.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel.learnNettyExample.WebSocketAndNetty;
2 |
3 | import io.netty.bootstrap.ServerBootstrap;
4 | import io.netty.channel.ChannelFuture;
5 | import io.netty.channel.EventLoopGroup;
6 | import io.netty.channel.nio.NioEventLoopGroup;
7 | import io.netty.channel.socket.nio.NioServerSocketChannel;
8 |
9 | /**
10 | * @Author yuchunwei
11 | */
12 | public class WsServer {
13 |
14 | private static void init() {
15 | EventLoopGroup bossGroup = new NioEventLoopGroup();
16 | EventLoopGroup workGroup = new NioEventLoopGroup();
17 | try {
18 | ServerBootstrap bootstrap = new ServerBootstrap();
19 | bootstrap
20 | .group(bossGroup, workGroup)
21 | .channel(NioServerSocketChannel.class)
22 | .childHandler(new Init());
23 | ChannelFuture future = bootstrap.bind(8088).sync();
24 | future.channel().closeFuture().sync();
25 | } catch (Exception e) {
26 | e.printStackTrace();
27 | } finally {
28 | bossGroup.shutdownGracefully();
29 | workGroup.shutdownGracefully();
30 | }
31 | }
32 |
33 | public static void main(String[] args) {
34 |
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/im-singel/src/main/resources/application.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/application.properties
--------------------------------------------------------------------------------
/im-singel/src/main/resources/mapper/ChatMsgMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
15 | INSERT INTO chat_msg(send_user_id,accept_user_id,msg,sign_flag,create_time)
16 | values(#{sendUserId},#{acceptUserId},#{msg},#{signFlag},#{createTime})
17 |
18 |
19 |
22 |
23 |
24 | UPDATE chat_msg SET sign_flag = 1 WHERE id
25 | IN
26 |
27 | #{id}
28 |
29 |
30 |
--------------------------------------------------------------------------------
/im-singel/src/main/resources/mapper/FriendsRequestMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | insert into friends_request(send_user_id,accept_user_id,request_time,status)
14 | values(#{myUserId},#{friendId},#{date},#{status})
15 |
16 |
17 |
23 |
24 | UPDATE friends_request SET status = #{status} WHERE accept_user_id = #{acceptUserId} AND send_user_id =
25 | #{sendUserId}
26 |
27 |
--------------------------------------------------------------------------------
/im-singel/src/main/resources/mapper/MyFriendsMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
13 |
14 |
15 | INSERT INTO my_friends(my_user_id,my_friend_user_id) values(#{acceptUserId},#{sendUserId})
16 |
17 |
18 |
26 |
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/css/fonts/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/css/fonts/FontAwesome.otf
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/css/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/css/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/css/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/css/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/css/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/css/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/css/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/css/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/css/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/css/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/css/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/css/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/css/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/css/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/css/fonts/glyphicons-halflings-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/css/fonts/glyphicons-halflings-regular.woff2
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/css/img/loading-sm.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/css/img/loading-sm.gif
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/css/img/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/css/img/loading.gif
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/avatar/Group01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/avatar/Group01.jpg
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/avatar/Member001.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/avatar/Member001.jpg
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/avatar/Member002.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/avatar/Member002.jpg
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/avatar/Member003.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/avatar/Member003.jpg
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/avatar/Member004.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/avatar/Member004.jpg
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/avatar/Member005.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/avatar/Member005.jpg
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/avatar/Member006.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/avatar/Member006.jpg
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/avatar/Member007.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/avatar/Member007.jpg
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/avatar/Member008.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/avatar/Member008.jpg
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/avatar/Member009.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/avatar/Member009.jpg
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/box_head.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/box_head.jpg
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/chat.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/chat.ico
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/chat_bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/chat_bg.jpg
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji.jpg
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji/emoji_01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji/emoji_01.png
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji/emoji_02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji/emoji_02.png
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji/emoji_03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji/emoji_03.png
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji/emoji_04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji/emoji_04.png
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji/emoji_05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji/emoji_05.png
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji/emoji_06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji/emoji_06.png
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji/emoji_07.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji/emoji_07.png
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji/emoji_08.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji/emoji_08.png
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji/emoji_09.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji/emoji_09.png
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji/emoji_10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji/emoji_10.png
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji/emoji_11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji/emoji_11.png
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji/emoji_12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji/emoji_12.png
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji/emoji_13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji/emoji_13.png
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji/emoji_14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji/emoji_14.png
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji/emoji_15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji/emoji_15.png
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji/emoji_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji/emoji_16.png
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji/emoji_17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji/emoji_17.png
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji/emoji_18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji/emoji_18.png
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji/emoji_19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji/emoji_19.png
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji/emoji_20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji/emoji_20.png
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji/emoji_21.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji/emoji_21.png
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji/emoji_22.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji/emoji_22.png
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji/emoji_23.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji/emoji_23.png
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/emoji/emoji_24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/emoji/emoji_24.png
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/login_bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/login_bg.jpg
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/img/upload.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/im-singel/src/main/resources/static/img/upload.jpg
--------------------------------------------------------------------------------
/im-singel/src/main/resources/static/js/common/jquery.actual.min.js:
--------------------------------------------------------------------------------
1 | /*! Copyright 2012, Ben Lin (http://dreamerslab.com/)
2 | * Licensed under the MIT License (LICENSE.txt).
3 | *
4 | * Version: 1.0.19
5 | *
6 | * Requires: jQuery >= 1.2.3
7 | */
8 | (function(a){if(typeof define==="function"&&define.amd){define(["jquery"],a);
9 | }else{a(jQuery);}}(function(a){a.fn.addBack=a.fn.addBack||a.fn.andSelf;a.fn.extend({actual:function(b,l){if(!this[b]){throw'$.actual => The jQuery method "'+b+'" you called does not exist';
10 | }var f={absolute:false,clone:false,includeMargin:false,display:"block"};var i=a.extend(f,l);var e=this.eq(0);var h,j;if(i.clone===true){h=function(){var m="position: absolute !important; top: -1000 !important; ";
11 | e=e.clone().attr("style",m).appendTo("body");};j=function(){e.remove();};}else{var g=[];var d="";var c;h=function(){c=e.parents().addBack().filter(":hidden");
12 | d+="visibility: hidden !important; display: "+i.display+" !important; ";if(i.absolute===true){d+="position: absolute !important; ";}c.each(function(){var m=a(this);
13 | var n=m.attr("style");g.push(n);m.attr("style",n?n+";"+d:d);});};j=function(){c.each(function(m){var o=a(this);var n=g[m];if(n===undefined){o.removeAttr("style");
14 | }else{o.attr("style",n);}});};}h();var k=/(outer)/.test(b)?e[b](i.includeMargin):e[b]();j();return k;}});}));
15 |
--------------------------------------------------------------------------------
/im-singel/src/test/java/com/ycw/im/imsingel/ImSingelApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imsingel;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class ImSingelApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/image/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/image/1.png
--------------------------------------------------------------------------------
/image/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiujiujiujiujiuaia/IM-netty/8fc2225f44ba52d4da9e02ef050b8d45962999be/image/2.png
--------------------------------------------------------------------------------
/src/main/java/com/ycw/im/imdistributedcommon/ImDistributedCommonApplication.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedcommon;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class ImDistributedCommonApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(ImDistributedCommonApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/ycw/im/imdistributedcommons/ImDistributedCommonsApplication.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedcommons;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class ImDistributedCommonsApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(ImDistributedCommonsApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/ycw/im/imdistributedroute/ImDistributedRouteApplication.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedroute;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class ImDistributedRouteApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(ImDistributedRouteApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/test/java/com/ycw/im/imdistributedcommon/ImDistributedCommonApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedcommon;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class ImDistributedCommonApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/test/java/com/ycw/im/imdistributedcommons/ImDistributedCommonsApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedcommons;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class ImDistributedCommonsApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/test/java/com/ycw/im/imdistributedroute/ImDistributedRouteApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.ycw.im.imdistributedroute;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class ImDistributedRouteApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------