赞
踩
如题,上周的一天,朋友圈的一个旧友找到了我,说让我帮他开发一个小工具,虽然活不大,但没个几年的全栈经验还不一定能接下来,因为麻雀虽小,涉及的内容可不少:
需求分析
原型设计
架构选型
接口设计
数据库设计
后端开发
前端开发
服务器购买
服务器配置
镜像构建
服务调试
服务部署测试
优化迭代
交付收款
如果你对上述流程感兴趣,可以继续看下去,关注公&号:新质程序猿,回复:api-mark 可以获取源码包。
废话不多说,开整吧!
用户故事如下,我大概评估了一下需要 1-2 个工作日,就要个 2000 块吧。
总结一下就是:
支持批量上传(添加)一批接口数据
提供获取接口,每次获取一条数据以供他自己的使用
提供标记接口,他使用完会标记这条数据的状态(1成功,2老号,3异常)
提供删除接口(多条件)
支持查询导出(多条件)
数据格式大概是这样的:
- 61057944----http://xxx/api/getcode?token=e49debc93
- 61057945----http://xxx/api/getcode?token=e49deb333
看起来好像蛮简单哈~~,我随即画了一个 原型图 给他。
得到确认后,就开整吧。
注:原型设计采用的是 Axure RP 9 + ElementUI,如有需要也可以公&号留言。
需求分析只是大概对需求进行了梳理,在进行开发之前,还需要进行深入详细的设计才能评估出工作量。
我们来拆解一下这个项目。
首先要明确项目各关键点所采用的架构选型,如服务器怎么选,前后端框架怎么选,如何部署,安全标准,性能要求等等,这些都会影响到架构选型。
对于这个项目来说,单机足够,没啥安全要求,一句话就是够简单,无压力开整。
服务器:centos 7.9 4c8g 200g 足够
数据库:mysql 5.7+(部署使用的 mysql 8)
后端:springboot + jpa 够用
前端:vue + vue-admin-template 快速开发框架
部署:docker + docker-compose 方便快捷
本项目主要涉及数据的导入,查询,导出,删除,取接口,还有非必要的登录等。
下面的接口是最终完结版涉及的接口,只有真正去开发的时候你才能明确的知道全部的需求。
登录接口,hard code 一段用户验证接口即可,够用
用户信息接口,主要懒得改 vue-admin-template 中的代码,用到了,就随便提供一个给前端吧
登出接口,同上,可有可无,前端用到了,随便提供一下
资源添加接口,重点,用户需要上传txt,嫌麻烦,让他贴文本到 textarea 框更好实现,避免了文件上传接口(虽然也不复杂)
接口获取接口,重点,每次取一条已添加的资源
单条删除接口,每次删 1 条记录
批量删除接口,页面提供了勾选删除操作,原本是分别调上面的单条删除,觉得不够优雅,额外增开
查询接口,分页返回,支持多条件:状态,日期范围,编号
查询导出接口,根据条件直接导出 csv 文件,没有用 excel 因为觉得复杂,csv 直接字符串拼接,也能达到 excel 的效果
条件删除,根据查询条件,批量删除数据
接口标记,对单条记录进行状态标记
你看,虽然用户故事可能就一句话,但实际开发过程中涉及到的接口及逻辑可还真不少,单查询接口就需要不少工作量的。
直接采用 mysql, 一张 api 表搞定:
id, bigint,自增
sn, varchar(100), 编号
api, varchar(1024), 接口地址
-1,初始状态
0,已取号
1,成功
2,老号
3,异常
create_time, datetime 添加时间
update_time, datetime 更新时间
详细 SQL 语句可以从源码中获取(开头有获取方式)。
由于内容不复杂,性能及安全性要求都不太高,所以 springboot + jpa 整起来。
通过 idea 或者如下网站快速构建一个模版项目:
额外加了几个常用的工具库:
lombok, 偷懒神器,免写 getter, setter 方法
commos-lang3,提供 StringUtils, NumberUtils 之类的工具类
jpa-spec, 方便构建复杂的查询语句,例如 eq, between 之类的
前端直接用 PanJiaChen 大佬的快速开发脚手架(虽然很久没更新了,够用就好)
https://github.com/PanJiaChen/vue-admin-template
- # clone the project
- git clone https://github.com/PanJiaChen/vue-admin-template.git
-
- # enter the project directory
- cd vue-admin-template
-
- # install dependency
- npm install
-
- # develop
- npm run dev
注:node 版本不能太高,我测试了 node v16 没问题,太高会报错,构建失败。推荐我之前的一篇文章,可以帮助你快速切换 node 版本:
版本不兼容,构建又失败了?NodeJS开发环境搭建,看这一篇就够了,多版本管理就是丝滑_node10 构建不成功-CSDN博客
大家直接看源码吧,被我删减了不需要的东西,变得更精简了,就 3 个页面:
登录页面,其实也可有可无
添加页面,资源添加,就一个 textarea 表单提交,加了一些格式校验及表单参数构建
列表页面,条件查询,选中删除,单项删除,条件导出,分页
服务器购买,找一个国外的 vps 就可以了,避免大陆需要备案的琐事,我这里不广告了,如有需要可以通过公*号:新质程序猿,找到我,可以告诉你。
反正不是我出钱,就随便选一个 8c4g 25Mbps 180G 的吧,280/月 对老板来说不再话下,哈哈。
服务器安装的是 centos 7.9 版本,因为用的比较多的缘故,大家根据喜好来即可,都一样,因为我的目标是 容器 部署,所以操作系统其实无所谓,只要能安装 docker & docker-compose 即可。
主要对系统进行了一些必要的操作:
内核参数优化,调整ulimit, 文件句柄之类的,从别处抄的,大家注意甄别
安装docker,通过 aliyun mirror 安装比较快一点
配置时区,调成中国上海时区
磁盘格式化及挂载,系统盘比较小,180G 的磁盘需要自己格式化,自己挂载,搜一搜就好了
附上操作脚本:
- # 更新源
- yum makecache
- # 调整时区
- ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
- echo "Asia/Shanghai" > /etc/timezone
- # 更改内核参数
- cat << EOF > /etc/sysctl.d/custom.conf
- net.core.somaxconn = 32768
- net.core.netdev_max_backlog = 32768
- net.ipv4.ip_local_port_range = 10000 65535
- net.ipv4.tcp_max_syn_backlog = 16384
- net.ipv4.tcp_max_tw_buckets = 30000
- net.ipv4.tcp_tw_recycle = 0
- net.ipv4.tcp_timestamps = 0
- net.ipv4.tcp_fin_timeout = 30
- net.ipv4.tcp_syn_retries = 1
- net.ipv4.tcp_synack_retries = 1
- net.ipv4.tcp_fack = 1
- vm.swappiness = 0
- vm.overcommit_memory = 1
- fs.nr_open = 1000000
- fs.file-max = 2000000
- kernel.core_uses_pid = 1
- kernel.pid_max = 4194304
- EOF
-
- sysctl -p /etc/sysctl.d/custom.conf
-
- ulimit -n 1000000
-
- cat << EOF >> /etc/security/limits.conf
- * soft nproc 1000000
- * hard nproc 1000000
- * soft nofile 1000000
- * hard nofile 1000000
- EOF
由于系统挂载了一块独立的数据磁盘,需要自行格式化挂载,这当然不在话下
- fdisk /dev/sdb
- n,p,w
- mkfs.xfs /dev/sdb1
- mkdir -p /data
- mount /dev/sdb1 /data
-
- # 查看分区ID https://zhuanlan.zhihu.com/p/62459117
- blkid
- # 配置开机自动挂载
- vi /etc/fstab
- UUID=da60a5fc-d38d-4775-a780-c6b5e0bf2956 /data xfs defaults 0 0
- UUID= /data xfs defaults 0 0
- UUID=13d2692c-b992-4f00-b070-26d90911610e /data xfs defaults 0 0
通过阿里云镜像站进行 docker-ce 安装
- yum install -y yum-utils device-mapper-persistent-data lvm2
- yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
- sed -i 's+download.docker.com+mirrors.aliyun.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
- yum makecache fast
- yum -y install docker-ce
- #
- vi /etc/docker/daemon.json
- {
- "data-root": "/data/docker"
- }
- vim /usr/lib/systemd/system/docker.service
- vim /usr/lib/systemd/system/containerd.service
-
- # 需配置 infinity 为 65535 ,小于系统文件句柄
- LimitNOFILE=65535
-
- systemctl daemon-reload
-
- systemctl restart docker
- systemctl enable docker
-
- systemctl restart containerd
- systemctl enable containerd
-
- # 安装 docker-compose
- curl -SL https://github.com/docker/compose/releases/download/v2.20.3/docker-compose-linux-x86_64 -o /usr/bin/docker-compose
- chmod a+x /usr/bin/docker-compose
为了便于调试和部署,选择使用当前流行的容器进行部署,构建镜像相当比较简单,项目路径下均有对应的 Dockerfile 文件,因为我 mac 上安装的 有 docker-desktop 所以直接本地安装和 build 即可,构建完成,推到了我自己的 hub 账号下,大家也可以直接体验。
https://hub.docker.com/r/chinaxiang/laiju-web
https://hub.docker.com/r/chinaxiang/laiju-api
- # 构建前端项目 prod 环境
- npm run build:prod
- # 构建 docker image
- docker build -t chinaxiang/laiju-web:v1.0 .
- # 推送至个人账号(需要提前登录,这一步大家可以忽略)
- docker push chinaxiang/laiju-web:v1.0
- # 编译构建
- mvn clean package
- # 构建 image
- docker build -t chinaxiang/laiju-api:v1.0 .
- # 推送
- docker push chinaxiang/laiju-api:v1.0仓库地址:
本地调试应该对大家来说比较熟悉了,后端直接在 idea 里启动,或者使用 java -jar 将打好的包启动起来就可以,后端接口调试的话,直接使用浏览器或者 postman, postwoman(hoppscotch) ,或者 curl 都可以。
唯一一点是,默认的 vue-admin-template 采用的 mockserver ,所以为了直接使用本地的 server api 调整了一下 devServer 配置项。
vue.conf.js 配置 proxy
- ....
- devServer: {
- port: port,
- open: true,
- overlay: {
- warnings: false,
- errors: true
- },
- proxy: {
- '/api': {
- target: 'http://localhost:8082',
- changeOrigin: true
- }
- },
- //before: require('./mock/mock-server.js')
- },
- ....
main.js 注释掉 mock 部分代码
- ....
- /**
- * If you don't want to use mock-server
- * you want to use MockJs for mock api
- * you can execute: mockXHR()
- *
- * Currently MockJs will be used in the production environment,
- * please remove it before going online ! ! !
- */
- // if (process.env.NODE_ENV === 'production') {
- // const { mockXHR } = require('../mock')
- // mockXHR()
- // }
- ....
因为安装有 docker, docker-compose 所以部署起来相对比较简单,直接一个 docker-compose.yml 文件拉起来就可以了。
- services:
- laijuweb:
- image: chinaxiang/laiju-web:v1.2
- restart: always
- ports:
- - 3000:80
-
- laijuserver:
- image: chinaxiang/laiju-api:v1.2
- restart: always
- environment:
- PROFILE: prod
- depends_on:
- - laijudb
-
- laijudb:
- image: mysql:8.4
- command:
- - --character-set-server=utf8mb4,
- - --collation-server=utf8mb4_unicode_ci
- restart: always
- environment:
- MYSQL_ROOT_PASSWORD: root
- MYSQL_USER: panda
- MYSQL_PASSWORD: Admin250@
- volumes:
- - ./mysql:/var/lib/mysql
- - ./init.sql:/docker-entrypoint-initdb.d/init.sql
init.sql
- create database if not exists laiju;
- use laiju;
-
- create table if not exists api
- (
- id bigint auto_increment primary key,
- sn varchar(100) null,
- api varchar(1024) null,
- status int null,
- create_time datetime null,
- update_time datetime null
- );
-
- grant all on *.* to panda@'%';
- flush privileges;
- # 启动各服务
- docker-compose up -d
不过在真正部署的时候还是遇到了一些小问题,这里稍微提一下。
本地使用的 mysql 5.7 部署选择的 mysql 8, 配置上存在差异,调整了好一阵才 ok,详情见项目配置
采用 compose 部署最开始没有配置依赖关系,导致 api 启动时数据库还没启动,添加了依赖配置
部署ok后,就上线使用吧。
任何系统都免不了优化迭代,主要优化调整了如下几项,不过不算大改动。
分页优化,查询条件改变,要把页码重置
删除最开始直接删除了,有点暴力,加上 confirm 确认框
删除非第一页最后一个选项时,页码减一,提升交互体验
选中删除最开始是按多个单条删除处理的,体验不好,整合到一个接口
status 状态显示调整为 filter 形式
新增了 已标记 状态过滤,包含复合条件(1新号,2老号,3异常)
时间范围查询条件直接转换为时间戳进行传参
配合前端的复杂查询做必要的调整
加了必要的参数校验,避免脏数据
取号接口直接采用同步关键字加锁,确保并发情况下不会取到相同的号
经测试没问题之后,找老板要钱吧,因为是熟人,所以提前报了价,没有先付钱,如果大家在接项目的时候,最好能有个定金意识,避免干活拿不到钱的情况,一般采用付一半或者4-4-2的比例。
OK,至此 2000 块到手。
你觉得这个项目收 2000 块贵吗?欢迎留言讨论交流!
如需要源码,可以关注公&号:新质程序猿,回复:api-mark 获取项目源码哟,无套路,纯粹为了增加个人气,况且,说不定哪天分享的内容会帮助到你呢!
欢迎大家批评指正,一起加油。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。