71

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

 5 years ago
source link: https://www.tuicool.com/articles/nYBN32f
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

本博客猫叔的博客,转载请申明出处

阅读本文约 “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版本也将移除。

UBNn6rE.png!web

如果大家在使用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);
    }
}

我这里就简单意识一下

功能测试

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

nYBvAbe.png!web

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

meQZZrJ.png!web

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

meymEzE.png!web

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

大家可以参考 InChatV1.1.3版本使用说明

生成自己的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将继续发展。

公众号:Java猫说

学习交流群:728698035

现架构设计(码农)兼创业技术顾问,不羁平庸,热爱开源,杂谈程序人生与不定期干货。

EJFriqR.jpg!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK