Skip to content
This repository has been archived by the owner on Oct 10, 2024. It is now read-only.

Latest commit

 

History

History
275 lines (166 loc) · 10.1 KB

README.md

File metadata and controls

275 lines (166 loc) · 10.1 KB

组队达人 (form-team-talent)

简介

一个简洁的小程序,可以快速,方便,高效地进行课外活动,课题研究,大作业等的组队。

点击查看小程序展示

团队分工情况

  • jzh:40%,后端代码和部分前端代码
  • wfy:30%,界面设计和部分前端代码
  • wyz:30%,负责文档,PPT的编写和部分前端代码

功能设计

每个人都可以通过组队达人创建一个活动,活动可以设置为私有活动或者公共活动,可以指定截止时间和具体内容,其他人可以通过扫描二维码加入活动。

加入活动页面,可以创建自己的小组,小组可以设置人数限制,说明小组的目标,对成员的要求等等。

活动参与者可以申请加入小组,说明自己的情况,以便组长筛选组员,组长同意申请之后就成功加入了小组。

每个人可以编辑自己的具体信息,以便了解和认识其他人。

技术设计

一、后端技术概览:

主要通过 Java 实现,支持通过 Docker 快速部署。使用微信云托管部署服务,使用腾讯云COS(或阿里云OSS)存储静态文件, 通过 Redis 实现缓存,通过 Swagger3 构建 api 文档,通过 ElasticSearch 实现活动搜索功能。

  • SpringBoot 2.7.5
  • Docker & Docker-compose
  • MySQL 5.7.35
  • Redis 3.0.354
  • MybatisPlus
  • Hutool
  • JWT
  • Quartz
  • OkHttp
  • qcloud.cos / aliyun.oss
  • Swagger3
  • ElasticSearch 7.17.3

二、前端技术概览:

主要由 JavaScript 实现。

微信小程序端,通过微信官方API和 Vant Weapp 框架搭建UI。

  • WeChat API
  • Vant Weapp

浏览器端,通过 npm,axios 等进行构建。

三、关键技术点和问题:

1、docker 部署问题

如果不使用 docker-compose 部署服务,只通过 docker 进行部署的话,由于有多个容器需要部署且容器间需要通信,为了正常通信,需要建立桥接网络,通过创建一个 network(默认为 bridge 模式),将两个容器的网络均指定为该 network, 即可让两个容器互通。

对于 mysql 服务所在容器,假如容器名定为 mysqldb,那么在 java 后端配置文件里对应的 mysql 服务的 url 应该指定为 jdbc:mysql://mysqldb/xxxxxxx。这样才能顺利连通 mysql 服务。

当然,假如使用 docker-compose 则没有这个问题了。

2、前后端交互认证问题

微信小程序的认证流程大致是这样的:

P1: 在小程序端向用户申请获得用户信息的权限,用户同意后,微信服务器返回一个 code 授权码,小程序端携带该授权码访问后端认证接口。

P2: 后端通过该授权码访问微信提供的接口服务获得该用户的 openId,接着将 openId 通过 Jwt 进行加密生成 token,放入请求头中返回给小程序端。

P3: 小程序端将 token 存入本地,以后每次需要用户认证的请求都带上该请求头。后端尝试获取请求头中 token,如果 token 不存在或者 token 过期则向小程序端返回 token 失效的错误码。

P4: 如果小程序端收到 token 失效错误码后,则进行 P1 操作。

认证流程图如下所示:

f1

3、关于后端返回的 json 数据

对于一个采用驼峰命名法命名的变量,比如 userId,转换后返回前端的 json 属性名是 userId,没有问题。

但是当变量名为 uId时,转换后则变为 uid,这就产生了问题。我还测试了其它一些变量,如下:

# userId
{"code":200,"msg":"ok","obj":{"userId":"hello"}}
# uId
{"code":200,"msg":"ok","obj":{"uid":"hello"}}
# Id
{"code":200,"msg":"ok","obj":{"id":"hello"}}
# uuId
{"code":200,"msg":"ok","obj":{"uuId":"hello"}}

可见当为 uId 和 Id 时,都会出现问题。

一般可以考虑在后端变量命名时,不让第二个字符大写,或者采用 @JsonProperty("uId") 进行解决。

4. 建立适当的索引

有些索引建立了反而会降低效率,比如写多于读的场景:在本项目中,对于一个加入小组的请求,写入到 t_req 表之后, 撤销请求操作和处理请求操作都可能是较为频繁的,也就是增删行操作较多,可能导致索引频繁地进行重建。

这里对 t_uat 表索引的设计进行说明。

当用户获取自己所加入的活动或小组时,需要根据用户 id 进行查询,所以可以建立用户 id 的索引。

当一个用户申请加入某个小组时,需要查询用户是否已经加入了该小组,但由于用户不能加入同一活动下的其它小组,所以只需要根据用户 id,活动 id 进行查询即可,可以用这两者建立一个联合索引:CREATE INDEX t_uat_idx_join ON t_uat(a_id, u_id);

同时,有了这个索引,当要查询某个活动所含小组时,无需再建立 活动 id 的索引,因为 mysql 当前使用默认引擎为 innodb,索引底层数据结构为 B+ 树,根据 B+ 树的最左匹配原则,使用该索引可以命中活动 id 对应的条目。

数据库设计

Mysql

ER

  • t_user:用户表,记录用户基本信息,其中,用户 id 为主键。
  • t_activity:活动表,记录活动基本信息,其中,活动 id 为主键,活动创始人 id 外键约束于 t_user。
  • t_team:小组表,记录小组基本信息,其中,小组 id 为主键,隶属活动 id 外键约束于 t_activity,小组创始人 id 外键约束于 t_user。
  • t_uat:参与情况表,记录用户加入小组(活动)情况,其中,id 为主键,用户 id 外键约束于 t_user,活动 id 外键约束于 t_activity,小组 id 外键约束于 t_team。
  • t_req:请求表,记录用户所发送请求,其中,请求 id 为主键,发送者 id 和 目标者 id 外键约束于 t_user,请求对应活动 id 和小组 id 外键约束于 t_activity 和 t_team。

Redis

本项目对用户,活动,小组,请求,参与情况等条目均做了缓存优化。

以用户为例,将用户信息进行缓存,键为 “user:{uId}”,值为经过 Json 序列化的对象字串。

用户每次获取个人信息,都会首先访问 Redis 缓存,如果命中缓存,则将值反序列化后得到对象信息,直接返回。如果用户更新个人信息,则直接删除缓存。

ElasticSearch

本项目针对活动实现了搜索功能,用户可以根据活动名进行模糊搜索活动。

索引名设置为 activity,文档 _id 设置为活动 id。

在进行新增活动时,同时将结果插入到 ElasticSearch 中,删除活动时则同时删除 ElasticSearch。而在更新活动时,仅当活动名发生更改时,对 ElasticSearch 中的对应活动进行更改。查询活动时,将查询所有活动名中含有对应查询字段的活动。

后端开发步骤

application.pub.yaml 重命名为 application.yaml,然后开始编辑。(“xxxxxx...”为需编辑内容)

需要配置的内容:

  • 微信小程序的 appId 和 appSecret
  • 数据库用户和密码
  • 对象存储相关字段
  • 本地静态资源存储位置
  • token 密钥和过期时间(单位:s)
  • redis 基本配置
  • elasticsearch 基本配置
  • 是否开启 swagger (生产环境下建议关闭)

执行 init.sql 初始化数据库,之后即可开始开发。

前端开发步骤

mini-program 为小程序开发目录,后端未使用微信云托管,需通过该文件夹开发。

mini-program-cloud 也为小程序开发目录,若后端使用了微信云托管,需通过该文件夹开发。

cd mini-program # or cd mini-program-cloud
npm install

接着,如果在 mini-program 开发,编辑 app.js,将“xxxxxx”替换为后端服务地址即可。

App({
  globalData: {
    baseUrl: "xxxxxx",
  },
})

如果在 mini-program-cloud 开发,编辑 app.js 如下(先将 app.pub.js 重命名为 app.js):

that.cloud = new wx.cloud.Cloud({
  resourceAppid: 'xxxxxxxxxxxxxxxxxx', // 微信云托管环境所属账号,服务商appid、公众号或小程序appid
  resourceEnv: 'xxxxxxxxxxxxxxxxxx', // 微信云托管的环境ID
})

注:后端 api 地址为 localhost:端口号/swagger-ui/index.html

部署步骤

方法1、通过 docker 部署

docker-compose-pub.yaml 重命名为 docker-compose.yaml,然后编辑数据库密码。

创建 docker-compose.yaml 所涉及到的挂载卷目录,并将 init.sql 放到 /docker/mysql/init 目录下。

接着,编辑配置文件中 mysql 地址如下:

url: jdbc:mysql://mysqldb/form_team_talent?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8

最后,执行 ./publish.sh -u (-u 字段是为了重新生成 jar包)。

方法2、通过微信云托管部署

在数据库界面创建账号(对应数据库用户和密码),进入数据库管理界面,运行数据库初始化脚本 init.sql 即可。

在数据库界面获取数据库内网地址,然后编辑配置文件中 mysql 地址如下:

url: jdbc:mysql://数据库内网地址/form_team_talent?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8

接着进行 ElasticSearch 和 Redis 服务的部署。

最后,重新生成 jar 包,进入服务界面,创建服务,将jar包上传并部署。

测试步骤

  • 可通过 thunder client 进行测试,将 test/api_test_ftt_thunderclient.json 导入即可
  • 可通过 postman 进行测试,将 test/api_test_ftt_postman.json 导入即可

小程序界面展示

主页

个人页

管理页

活动页

小组页

请求

发送加入小组的请求:

处理请求:

联系与交流

Github: akynazh

Mail: [email protected]

致谢

JetBrains Logo (Main) logo.

感谢 JetBrains 对该项目的大力支持!