自己动手搭建聊天APP

分类: 约彩365app下载 时间: 2025-07-18 12:30:52 作者: admin 阅读: 8704 点赞: 817
自己动手搭建聊天APP

自己动手实现聊天APP

成果

开始

时隔两年多,想再次看看 app 的开发。还记得两年前辛苦使用 andro studio 写 xml 的日子,五味杂陈。网上走了一圈,发现 dcloud 公司推出了 uni-app 和 5 + app 的方式开发 app , 为了知道这些方式和 andro studio 开发 app 的区别。我开始了探寻。

uni-app 和 5 + app

uni-app 最大的特点便是 编写一套代码,可发布到iOS、Android、H5、以及各种小程序(微信/支付宝/百度/头条/QQ/钉钉/淘宝)、快应用 ,并且 基于vue 。听上去方便不少哦。

5 + app 是 HTML5 Plus移动App的意思。HTML5 plus(即HTML5 +)是W3C提供一套规范,属于工信部。扩展了 JavaScript 对象 plus,使得js可以调用摄像头、陀螺仪、文件系统等。HBuilder内置HTML5 + APP开发环境,可以在云端将代码打包为 apk 等文件。

经过测试发现 uni-app 编译过程稍微有点漫长,对于开发来说测试有点费时间。最终我选择 5 + app 的方式开发APP。

mui

打开 hbuilder ,新建项目可以发现有 mui 项目模板。

mui 是 dcloud 公司推出的 5 + app 开发的一款 ui 框架 ,听说性能最接近原生APP。 官网是 【mui】,官网提供了大量示例,可以参考(也可以粘贴复制哦)。但总的来说文档不是很丰富吧,有些功能我还是在百度解决。

尬聊APP

来源

在学习了两天的 mui api后我想尝试写个 app 来锻炼下自己,也为了对比 5 + app 和 android studio 开发上的深层区别和感受,再加上之前对于 即时聊天 app 的 实现感兴趣,想摸索一番,于是取了这个名字便开始了开发。

技术选型

后端大致选择 springboot + netty + mybatisplus 前端大致选择 mui + vue 数据库依旧选择 mysql(当然后边可以换其他数据库)

项目注意点

前端代码需要注意几个问题 : 1 mui 配合 vue 一起玩的时候 @click 会不起作用,只能用 mui 去绑定 tap 事件后调用 this.click() 方法,因为 mui 禁用了 click 事件 ,点击会触发 tap 事件。当然本页面暂未使用到 vue , 其他页面注意。解决代码如下:

mui(document.body).on('tap', '#btn_clcik', function(e) {

this.click()

})

2 mui 配合 vue 一起玩的时候 v-model 双向绑定不起作用。暂时我使用 document 去获取值。比如获取输入框内容时:

document.getElementById('galiao_userId').value

3 如果自定义的 js 文件用到 mui 、vue、axios 中的对象或方法时,尽量后引入。比如:

4 尽量使用 v-text 代替 {{ }} 避免插值闪烁。

后端项目

构建

新建maven工程,pom.xml:

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

4.0.0

org.springframework.boot

spring-boot-starter-parent

2.2.6.RELEASE

com.junan

galiao

1.0.0-SNAPSHOT

galiao

尬聊 v1 服务端

1.8

1.2.58

3.2.0

3.2.0

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter-security

org.mybatis.spring.boot

mybatis-spring-boot-starter

2.1.2

mysql

mysql-connector-java

runtime

org.springframework.boot

spring-boot-starter-data-redis

com.auth0

java-jwt

3.1.0

io.netty

netty-all

com.alibaba

fastjson

${fastjson.version}

org.projectlombok

lombok

true

com.baomidou

mybatis-plus-boot-starter

${mybatis-plus.version}

com.baomidou

mybatis-plus-generator

${mybatisplus-generation.version}

org.springframework.boot

spring-boot-starter-freemarker

org.springframework.boot

spring-boot-starter-test

test

org.junit.vintage

junit-vintage-engine

org.springframework.boot

spring-boot-maven-plugin

项目结构

核心

核心功能便是 netty 提供的服务了,在 netty 包下三个类:

GaLiaoServer 表示 Netty 服务的启动类。 GaLiaoServerInitializer 表示 Netty 服务的初始化类。 GaLiaoHandler 表示Netty 服务的处理器类。(这里面包含消息的接受和发送,它就是核心)

至于代码方面大家感兴趣可以去【尬聊开源后端项目】

项目启动页(index.html)

前端代码:

首页

这个页面暂时只是负责打开了登录页面,后期可以做成判断是否登录或自动登录,根据情况跳转到不同页面。

登录(login.html)

架构图

主要还是使用 mvc ,这里暂时不用 netty 。登录成功返回 token,客户端保存 token ,携带 token 访问服务端资源,包含后期使用 netty 发送消息也需要携带 token 。

前端登录页面代码:

登录

尬聊 v1.0

placeholder="密码">

登录页面效果:

后端主要代码:

@Override

public Message login(User user) {

User byId = getById(user.getUserId());

if (byId == null) {

return new Message()

.code(MessageCode.FAIL.value())

.data("用户不存在!");

}

if (!encoder.matches(user.getUserPwd(), byId.getUserPwd())) {

return new Message()

.code(MessageCode.FAIL.value())

.data("用户名或密码错误!");

}

// 密码正确,产生token并返回

user.setUserPwd(null); // 清理掉密码

byId.setUserPwd(null); // 清理掉密码

String token = JwtTokenUtil.createToken(user);

// redis 存储登录的用户的信息 (存储一天)

redisUtil.set(token, FastJsonUtil.toJSONString(byId), 24 * 60 * 60);

// 获取好友

String[] friendIds = byId.getUserFriends().split(",");

QueryWrapper wrapper = new QueryWrapper<>();

wrapper.in("user_id", friendIds);

wrapper.select("user_id", "user_avatar", "user_nickname");

List users = userMapper.selectList(wrapper);

byId.setFriends(users);

return new Message().code(MessageCode.OK.value()).data(byId).token(token);

}

后端主要用到 spring security 的 BCryptPasswordEncoder 对密码加密和解密,用的 sha256 算法,因此不可逆的,保证密码的安全性。登录成功后会将用户的基本信息(除了密码)放入redis ,key 为用户的token, 暂时默认存一天也是 token 的过期时间。然后把用户信息返回客户端,客户端保存在 localstorage 供页面之间共享。

主页面(main.html)

主页面主要是 main.html 页面,这个页面有一个底部导航栏来控制显示其他几个页面。 前端代码如下:

主页面

该页面效果如下:

该页面难点在于底部导航栏每个 a 标签控制每个页面显示与隐藏,而官网只提供了基于a 标签 href 的代码块的显示与隐藏,这种方式需要将其他页面以 div 的方式写在 main 页面,会导致 main 页面代码过于冗杂。本次使用的切换 html 的方式核心代码在于 init 方法,通过 a 标签上的 tabindex 的值来显示不同页面。

消息页面(message.html)

前端代码:

消息页面

消息

消息页面效果:

该页面构建了一个websocket对象供聊天信息的发送和接受,但该对象只能在本页面使用,其他页面(chat.html)需要调用本页面方法来发送消息。该页面收到消息直接传给chat页面,chat页面进行判断后选择显示或忽略。该页面涉及到消息数据的保存功能请参见代码。

联系人页面(friends.html)

前端代码:

联系人页面

联系人

  • id="open_friend_info">

页面效果:

联系人页面和消息页面比较相似,可以 copy 一部分。

发现页面 (found.html)

前端代码:

发现页面

发现

  • 毒鸡汤(每日一毒)

  • 代做决定

这个页面主要负责打开其他页面,目前主要打开 du.html 和 decision.html,这两个页面目前主要还是 js 在玩,没有 ajax 操作。可在【尬聊开源地址】查看。

我的页面(mine.html)

前端代码:

我的页面

我的

页面效果: 这个页面目前主要实现了我的二维码展示、关于、退出三个功能,后续可以做其他功能。

好友信息页面(friend_info.html)

好友信息页面

页面效果:

这个页面会根据情况判断,如果不是自己的好友,会显示 添加好友 按钮,如果是自己的好友就显示 发消息 按钮。这一块的判断在服务端,主要逻辑如下:

@Override

public Message userById(Long userId, String token) {

// 验证token

if(checkToken(token)) {

QueryWrapper wrapper = new QueryWrapper<>();

wrapper.eq("user_id", userId);

wrapper.select("user_id", "user_avatar", "user_nickname");

User user = userMapper.selectOne(wrapper);

if(user == null)

return new Message().code(MessageCode.USER_NOT_FOUND.value()).data("该用户不存在!");

// 用户存在,检查是否是自己的好友

boolean isFriend = false;

// 获取自己的好友列表

String[] split = FastJsonUtil.parseObject(

(String) redisUtil.get(token), User.class)

.getUserFriends()

.split(",");

for (String s : split) {

// 判断是否是自己好友

if(user.getUserId().equals(Long.valueOf(s))) {

isFriend = true;

break;

}

}

user.setIsFriend(isFriend);

return new Message().code(MessageCode.OK.value()).data(user);

}

// token不合法

return new Message().code(MessageCode.FAIL.value()).data("token不合法");

}

聊天页面(chat.html)

前端代码:

尬聊聊天页面

页面效果如下:

这个页面的聊天气泡功能稍微有点复杂,可以参考项目中 chat_bubble.html 的页面的简化代码实现。另外,这个页面在发消息时需要调用 message 页面来发,因为只有 message 建立了 websocket 对象。调用其他页面的方法有两种方式,一种是 mui.fire() 方法,另一种是 evalJS() 方法。注意 evalJS() 方式只能传字符串参数,无法直接传对象,可以使用 JSON.stringify() 转为 json 串传参,被调用页面使用JSON.parse() 方法将 json 串转对象。

二维码页面(mine_qrcode.html)

前端代码:

二维码页面

我的二维码

页面效果:

这个页面主要使用【qrcode.js】对尬聊号生成二维码。

扫一扫页面(sao.html)

前端代码:

扫一扫页面

扫一扫识别

页面效果:

该页面主要使用 plus.barcode.Barcode 开启一个扫一扫的效果,设置回调函数。扫描成功就弹到好友信息页面,这个页面会发 ajax 去查好友信息。

搜索页面(sou.html)

前端代码:

搜索页面

搜索

  • 用户不存在

页面效果:

这个页面难点在于输入框的回车事件的监听,如果是 vue 的 @keyup.enter.native 就监听不到,需要使用 mui 监听 keypress 事件。输入框 添加 mui-input-speech 的 class ,mui 实现了语音输入。

其他

至于其他页面功能稍微简单一些,可以去项目里面克隆源代码交流。【尬聊前端源码】、【尬聊后端源码】

展望

虽然开发了一些功能,但是还有很多问题需要去发现和解决。比如消息无法保存等 问题。

后边我希望增加有趣的功能,比如过滤 不良消息词汇,用美好的词代替,净化网络暴力。比如 : 你是傻逼 代替为 你是靓仔。让我们的交流更加美好。

当然了,如果你想到了有趣的功能欢迎留言(说不定哪天就去实现了)。要是愿意参与到开源项目的开发当然更好了。走过路过,留个 star 呗。

博客地址:https://www.anlazy.top/index.php/archives/308/ 本人公众号:一只小安仔

相关推荐