为了账号安全,请及时绑定邮箱和手机立即绑定

基于InChat的SpringBoot版本通讯聊天数据存储Demo,附带详细流程说明[InChat1.1.4]

标签:
Java

本博客 猫叔的博客,转载请申明出处
阅读本文约 “8分钟”
适读人群:Java初级

前言

InChat = Iot Netty Chat

首先,感谢那些一直以来支持InChat的朋友们,你们可能是因为工作原因,或者自己的想法,或者自己的项目等等。

InChat还不是一个合格的框架,它还存在很多弊端与问题,但是感谢你们的关注,也是你们让它学会成长。

重新声明一次,InChat:一个轻量级、高效率的支持多端(应用与硬件Iot)的可分布式、异步网络应用通讯框架。

InChat从1月1.1.3版本后,就停止了更新,期间由于个人原因(我后续也不敢保证它的连贯性),当时在8月22号,InChat发布1.1.4版本,且在9月份预计也会继续发布1.1.5版本(由于1.1.4发现了一些核心问题)

接下来,我将详细介绍1.1.4版本下的一些基本功能,欢迎大家测试,并在这里提出你们的看法或者问题。

InChat版本


<dependency>

<groupId>com.github.UncleCatMySelf</groupId>

<artifactId>InChat</artifactId>

<version>1.1.4</version>

</dependency>

构建SpringBoot的web项目

由于在停更期间,很多朋友都问到InChat在SpringBoot等web框架下的使用问题及想法,所以这个Demo是完全在SpringBoot环境下搭建的。

下载地址:InChat-SpringBoot-Demo,项目中demo-inchat-4.zip文件

这里建议大家可以直接敲一次,看看有什么问题。

首先,我的项目是SpringBoot-Web,数据库是MySQL,没有使用Redis

pom文件


<?xml version="1.0" encoding="UTF-8"?>

<project  xmlns="http://maven.apache.org/POM/4.0.0"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>2.1.7.RELEASE</version>

<relativePath/>  <!-- lookup parent from repository -->

</parent>

<groupId>com.example</groupId>

<artifactId>demo-inchat-4</artifactId>

<version>0.0.1-SNAPSHOT</version>

<name>demo-inchat-4</name>

<description>Demo project for Spring Boot</description>

  

<properties>

<java.version>1.8</java.version>

</properties>

  

<dependencies>

  

<dependency>

<groupId>com.github.UncleCatMySelf</groupId>

<artifactId>InChat</artifactId>

<version>1.1.4</version>

<exclusions>

<exclusion>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-log4j12</artifactId>

</exclusion>

<exclusion>

<groupId>log4j</groupId>

<artifactId>log4j</artifactId>

</exclusion>

</exclusions>

</dependency>

  

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-jpa</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-jdbc</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

  

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<scope>runtime</scope>

</dependency>

<dependency>

<groupId>org.projectlombok</groupId>

<artifactId>lombok</artifactId>

<optional>true</optional>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-test</artifactId>

<scope>test</scope>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-test</artifactId>

<scope>test</scope>

</dependency>

</dependencies>

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

</plugin>

</plugins>

</build>

  

</project>

关于pom文件,大家需要注意的是InChat版本其实是自带log4j,因此可能会和其他的日志组件有冲突,需要移除,这个在1.1.5版本也将移除。

图片描述

如果大家在使用InChat期间报:


Exception  in  thread  "main"  java.lang.IllegalArgumentException: LoggerFactory  is  not  a  Logback  LoggerContext  but  Logback  is  on  the  classpath.

可以按照以上移除对应的日志组件。

账户登录

基本的数据关系

  • Message 聊天消息类

@Entity

@Data

@DynamicUpdate

public  class Message {

  

/**id,自增*/

@Id

@GeneratedValue(strategy  = GenerationType.IDENTITY)

private Integer id;

  

/** 消息时间 */

private Date time;

  

/** 消息类型(发送给自己、发送给朋友、发送给群组) */

private String type;

  

/** 消息值(聊天内容) */

private String value;

  

/** 用户标识(登录token) */

private String token;

  

/** 群聊Id */

private String groudId;

  

/** 是否在线-个人(朋友是否在线) */

private String online;

  

/** 是否在线-群聊(离线朋友) */

private String onlineGroup;

  

/** 消息接收人标识(接收朋友Token) */

private String one;

  

}

  • User 用户登录(简单模拟)

public  class User {

  

/**id*/

@Id

@GeneratedValue(strategy  = GenerationType.IDENTITY)

private Integer id;

  

private String username;

  

private String password;

  

}

JPA

这里就简单用JPA处理,喜欢用MyBatis的朋友也可以试试,欢迎贡献Demo

启动类

为什么突然说到启动类呢?

因为,InChat(1.1.3之前都是在启动类,启动的),这可能是一个误解,在本次Demo中咱们的启动类是这样的。


@SpringBootApplication

@EnableScheduling

public  class DemoInchat4Application {

  

public  static  void main(String[] args) {

SpringApplication.run(DemoInchat4Application.class, args);

}

  

}

是的,就这样,在我的这个业务里,并没有打算一开始就启动InChat,当然这还是要看业务而定

Controller层

这里的Controller就是一个常规启动http接口,启动默认InChat服务。


@RestController

public  class UserController {

  

@Autowired

private UserRepository repository;

  

@GetMapping("/init")

public String init(){

ConfigFactory.initNetty = new MyInit();

ConfigFactory.fromServerService = FromServerServiceImpl.TYPE2;

ConfigFactory.listenAsynData = new UserListenAsynData();

ConfigFactory.inChatVerifyService = new VerifyServiceImpl(repository);

InitServer.open();

return  "success";

}

  

}

大家会发现,我通过一个http启动InChat,同时将一个UserRepository注入到InChat的校验类里面。

启动。


2019-08-23  17:10:52.399  INFO  20136 --- [ BOSS_1] c.g.u.bootstrap.NettyBootstrapServer : 服务端启动成功【192.168.1.121:8070

接下来介绍下InChat的几个配置类

InChat配置类——InitNetty

继承 InitNetty

它是初始化Netty的基本配置,你可以根据你的需要的修改配置


public  class MyInit extends InitNetty {

  

@Override

public  int getWebport() {

return  8070;

}

//分布式

@Override

public Boolean getDistributed() {

return  false;

}

//加密

@Override

public  boolean isSsl() {

return  false;

}

InChat配置类——FromServerService

实现 FromServerService

这个与InChat1.1.3版本没有差别,是一个服务器发送的系统通知,可以通过Http发送任务


public  enum FromServerServiceImpl implements FromServerService {

  

TYPE1(1,"【系统通知】您的账号存在异常,请注意安全保密信息。"),

TYPE2(2,"【系统通知】恭喜您连续登录超过5天,奖励5积分。");

  

private Integer code;

  

private String message;

  

FromServerServiceImpl(Integer code, String message){

this.code = code;

this.message = message;

}

  

public Integer getCode() {

return code;

}

  

public String findByCode(Object code) {

Integer codes = (Integer)code;

for (FromServerServiceImpl item: FromServerServiceImpl.values()) {

if (item.code == codes){

return item.message;

}

}

return  null;

}

  

public  void setCode(Integer code) {

this.code = code;

}

  

public String getMessage() {

return message;

}

  

public  void setMessage(String message) {

this.message = message;

}

  
  

}

InChat配置类——ListenAsynData

继承 ListenAsynData

异步数据获取,就是聊天数据获取的类,在1.1.4中,你需要自己写一个载体(Map或者list)来存储聊天数据,我在这个Demo中使用Map,其实可以用list,需要注意,InChat中提供了一个将Map转为InChatMessage的工具类MessageChangeUtil,

我希望我的业务不是时刻存储数据,所以我将聊天数据存储到Map中,使用定时器,定时存储到数据库中。


public  class UserListenAsynData extends ListenAsynData {

  

@Override

public  void asynData(Map<String, Object> maps) {

  

InChatMessage inChatMessage = MessageChangeUtil.Change(maps);

CacheMap.add(inChatMessage);

  

}

}

InChat配置类——InChatVerifyService

继承 InChatVerifyService

你需要给这个类加一个静态变量,方便后续初始化后,做数据操作

这个类中的两个方法,一个是用户登录校验,一个是根据群聊ID获取群聊成员数组

这两个数据我都默认通过数据库处理,群聊ID我是直接模拟,大家可以在数据库中存储一个对应的表试试


public  class VerifyServiceImpl implements InChatVerifyService {

  

private UserRepository repository;

  

public VerifyServiceImpl(UserRepository repository){

this.repository = repository;

}

  

public  boolean verifyToken(String token) {

User user = repository.findByUsername(token);

if (user.getId() != null){

return  true;

}

return  false;

}

  

public JSONArray getArrayByGroupId(String groupId) {

JSONArray jsonArray = JSONArray.parseArray("[\"1111\",\"2222\",\"3333\"]");

return jsonArray;

}

}

定时任务

我使用定时任务,定时存储聊天数据,这里需要注意,一定要清空存储过的内容


@Component

public  class SchedulerTask {

  

@Autowired

private MessageRepository repository;

  

private  static  final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

  

@Scheduled(fixedRate  = 30000)

public  void reportCurrentTime() {

System.out.println("现在时间:" + dateFormat.format(new Date()));

Map<Integer,InChatMessage> Chatcache = CacheMap.copy();

InChatMessage inChatMessage = Chatcache.get(1);

Message message = new Message();

message.setOne(inChatMessage.getOne());

message.setGroudId(inChatMessage.getGroudId());

message.setOnline(inChatMessage.getOnline());

message.setOnlineGroup(inChatMessage.getOnlineGroup());

message.setToken(inChatMessage.getToken());

message.setType(inChatMessage.getType());

message.setValue(inChatMessage.getValue());

message.setTime(inChatMessage.getTime());

repository.save(message);

}

}

我这里就简单意识一下

单机模式下,发送给自己、发送给别人、发送给群组(单机,不加密)

图片描述

正常运行,由于数据存储,我定时器只存储一条,大家记得修改下

图片描述

单机,ssl加密,发送给自己、发送给别人、发送给群组(单机、加密)

图片描述

关于加密,大家可以构建自己的加密文件,或者使用inchat.jks

生成自己的jks加密文件,请在 InitNetty类 的继承类中做对应的修改。


public  abstract  class InitNetty {

  

//...

  

/** 是否启动分布式 */

private Boolean isDistributed = false;

  

/** 是否启动加密 */

private  boolean ssl = false;

  

private String jksFile = "inchat.jks";

  

private String jksStorePassword = "123456";

  

private String jksCertificatePassword = "123456";

  

//....

}

分布式,发送数据

本Demo暂不测试,大家有兴趣可是在InChatV1.1.3版本使用说明中学习了解。

因为分布式使用后,两个Demo项目都会存在数据存储,这个不在InChat的设计范围,所以目前推荐大家先使用单机版本

后续的分布式,会有一个数据存储的中间云组件,集中处理聊天的数据存储问题等

InChat将继续发展。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
6131
获赞与收藏
1988

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消