项目地址 https://github.com/JabinGP/demo-chatroom,对你有帮助的话请多多star
go+iris+jwt+mysql+gorm+viper,iris项目实战简易聊天室,登陆、注册、私聊、群聊。前端
git clone https://github.com/JabinGP/demo-chatroom.git cd demo-chatroom // 复制config.toml.example 为 config.toml 并填写数据库信息,或者可选修改端口号 go run demo-chatroom.go
默认为8888端口,启动后访问http://localhost:8888
便可,或者访问演示地址http://mike.jabingp.cn:8888
mysql
用了react,可是没用ui框架,不少的小细节上表现并很差,凑合着看吧,重点放在后端。react
聊天框设置了窗口自动滚动到底端,可是api是react提供的,发如今许多浏览器上并不兼容,使用chrome浏览器能够解决这个问题。git
注册后手动返回选择登录,消息框里面的红色名称为公共发言,灰色名称为私聊发言、能够在红色的框里面指定接收者的名称,若是不指定的话,默认是公共发言,指定后只有对应的用户能看到信息。github
蓝色框内显示本身的用户名,点击即直接退出登陆。golang
api格式基于restful设计,登陆功能使用jwt完成,许多接口须要登陆状态,请求的时候须要携带JWT,具体请看golang iris的jwt实践,另外便于测试,JWT签发有效时间只设置了20分钟,过时须要从新登陆。web
功能 | 请求方式 | 地址 |
---|---|---|
获取登陆token | POST | http://localhost:8888/v1/login |
查找用户 | GET | http://localhost:8888/v1/user |
注册 | POST | http://localhost:8888/v1/user |
用户本身修改信息 | PUT | http://localhost:8888/v1/user |
用户发送信息 | POST | http://localhost:8888/v1/message |
用户获取信息 | GET | http://localhost:8888/v1/message |
用户获取token信息 | GET | http://localhost:8888/v1/token/info |
详细请求参数能够在demo-chatroom的postman-api文档里查看。sql
或者查看源码,请求参数在model/reqo
里面查看,响应参数能够在model/reso
里查看chrome
聊天功能AJAX不是最好的选择,WebSocket比较好,可是被要求使用了AJAX因此没有选择后者。数据库
项目的前端比较简陋,由于只是做为demo使用。
英语不是很好,代码注释用英语只是由于懒得切换输入法。
第一次用go开发web项目,也是第一次用react写前端,因为前端没怎么注重项目结构(xjbx),就不放源码了,把项目编译后放在了assets文件夹下,可读性不好,可是能够和后端一块儿启动,不须要单独启动前端,比较方便查看效果。若是还有时间会考虑用原生写一个极简版的供你们参考原理。
第一次用ORM操做数据库,感受好难用,我仍是宁愿手写sql,好多想要的效果翻半天文档都找不到解决方案,后期有机会考虑用sqlx重构。
最近对Go比较有兴趣,又接到任务编写一个简易聊天室,发现目前iris的项目实践比较少,只有一些HelloWorld级别的示例,因而决定用Go来作,而后开源出来供大互相参考借鉴,固然项目结构如何设计彻底基于我有限的开发经验,对于不合理的地方,请给出你宝贵的意见。
这个项目有以下要求
登录功能此次选用JWT
来实现,JWT
和Session
各自的优劣就再也不赘述。
基于AJAX是全部先后端分离项目的必备,所以这个功能不过多讨论,这里重点在于无刷新,难点在哪?
用户的操做逻辑是,在聊天室里面发送数据,而后数据就被发出去,聊天界面要显示出本身发送的数据,以及要实时更新别人发出来的数据。
前端和后端之间是经过AJAX来交流的,前端发送数据和后端发送数据能够表现为
这里有什么问题?问就在前端永远只能主动发起请求,然后端永远只能接受请求。这意味着最新的消息永远没法实时地从后端主动发送给前端,最新的消息只能先存放在后端,而后等待前端发起请求,后端才能返回数据。
因为后端是没有能力主动推送消息给前端的,所以用户获取最新数据的解决方法是前端设置一个定时器每隔一段比较短的时间就请求一次后台接口(轮询)
,这样就能不断更新数据。
前端已经肯定使用AJAX定时轮询后台接口来获取最新数据,为了数据实时性,轮询间隔会小于1s
,这样又会带来另个问题,后端在如此频繁的请求下,必定不能每次都将全部数据都传输出去,一是数据大小致使的网路传输效率、流量成本问题,二是数据大小致使的前端判断新数据的效率问题,那么后端每次必须都返回前端尚未接收过的数据,而问题在于--后端怎么知道前端已经接收了哪些信息?
这个就要利用到消息的自增主键
,只须要前端每次请求的时候都携带上前端已经接收的最后的消息的主键
,因为主键是不重复且自增的,咱们能够很轻松的找出比该主键大的数据,也就是前端还没接收到的数据。
语言
框架
数据存储
技术
因为使用了Gorm数据库ORM框架,如下表都是自动生成的,自带了
xxxxxx_at
字段
基于如上的需求,设计了users
和messages
两个表
关键字段
数据库表结构
Field | Type | Null | Key | Default | Extra |
---|---|---|---|---|---|
id | int(10) unsigned | NO | PRI | NULL | auto_increment |
created_at | timestamp | YES | NULL | ||
updated_at | timestamp | YES | NULL | ||
deleted_at | timestamp | YES | MUL | NULL | |
username | varchar(255) | YES | NULL | ||
passwd | varchar(255) | YES | NULL | ||
gender | bigint(20) | YES | NULL | ||
age | bigint(20) | YES | NULL | ||
interest | varchar(255) | YES | NULL |
关键字段
数据库表结构
Field | Type | Null | Key | Default | Extra |
---|---|---|---|---|---|
id | int(10) unsigned | NO | PRI | NULL | auto_increment |
created_at | timestamp | YES | NULL | ||
updated_at | timestamp | YES | NULL | ||
deleted_at | timestamp | YES | MUL | NULL | |
sender_id | int(10) unsigned | YES | NULL | ||
receiver_id | int(10) unsigned | YES | NULL | ||
content | varchar(255) | YES | NULL | ||
send_time | timestamp | YES | NULL |
如下结构出于我的经验,有不当之处请给出宝贵意见
model 定义一系列结构体
很好理解,就是数据库对应的实体,但不要求与数据库字段一一对应
不一样接口请求的时候,能够携带的参数以及响应的数据也不一样,因此为每个接口设计一个对应的请求实体和响应实体
如下为我的理解
主要职责是,接受请求的请求参数,转换为reqo,进行简单的请求参数验证(我我的的定义与数据库无关的验证,如非空、非零),调用Service层的函数获取pojo结果,并将pojo结果转换封装为reso返回。
主要职责是,对Dao层的接口进一步封装,提供通用的接口给Controller调用,返回数据能够是pojo,在Service内须要进行数据的验证,如(新增用户,校验用户名是否重复)。
这里基本上一个方法直接对应一条sql语句,不作任何的验证,认为接收到的数据是可靠的(已经通过了Controller和Service两层的参数验证了),返回数据能够是pojo。
项目地址 https://github.com/JabinGP/demo-chatroom,对你有帮助的话请多多star