基于InChat的SpringBoot版本通讯聊天数据存储Demo,附带详细流程说明[InChat1.1.4]
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.
本博客猫叔的博客,转载请申明出处
阅读本文约 “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
大家可以参考 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
现架构设计(码农)兼创业技术顾问,不羁平庸,热爱开源,杂谈程序人生与不定期干货。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK