用户中心-开发笔记
目标:能够轻松做出管理系统。
第二次直播内容:
1、上次直播问题总结
2、数据库表设计
3、完成登录注册的前后端开发
4、完成用户管理后台的前后端开发
5、其他
企业做项目流程
需求分析 => 设计(概要设计 、 详细设计) => 技术选型 =>初始化项目 / 引入需要的技术 => 写个小demo
=> 写代码 (实现业务逻辑) => 测试(单元测试)=> 代码提交 / 代码评审 => 部署 => 发布
需求分析
1、登录 / 注册
2、用户管理 (管理员权限)
3、用户校验机制 (仅星球用户)
技术选型
前端:三件套 + React + Ant design(组件库)+umi + ant design pro
后端:java +
springmvc(接口,restful接口开发)
mybatis (提供数据访, 数据持久层支持)
mybatis plus (mybatis的封装)
springboot (快速启动spring项目)
mysql
部署:服务器 / 容器
数据库设计:
user表
id (主键) bigint
user_account(用户账号) varchar
avatar_url (头像图片性别) varchar
gendar (性别)tinyint
username (用户名)varchar
password (密码) varchar
email (邮箱)varchar
status (账号状态) int
非业务相关字段:
createTime (创建时间)datetime
updateTime (更新时间)datetime
is_delete (逻辑删除字段 ) tinyint
建表语句:
drop table if exists user;
create table user
(
id bigint auto_increment comment '用户id',
user_account varchar(256) null comment '用户账户',
username varchar(256) null comment '用户名',
avatar_url varchar(1024) null comment '用户头像地址',
gender tinyint default 0 not null comment '性别',
password varchar(256) null comment '密码',
email varchar(512) null comment '邮箱',
user_status int default 0 not null comment '用户状态可拓展 0-有效 1表示无效',
create_time timestamp default current_timestamp not null,
update_time timestamp default current_timestamp not null comment '更新时间',
is_delete tinyint default 0 not null comment '是否删除 0-没有删除 1-表示删除',
primary key (id)
) comment '用户信息表';
计划:
- 初始化项目
- 前端初始化
- 初始化项目 √
- 引入一些组件 √
- 框架介绍 / 项目瘦身 √
- 后端初始化
- 准备环境(mysql) √
- 整合框架
- 准备mysql,mysql数据源 √
- 修改properties文件,修改配置 √
- 仿照mybatis plus官网,写一个mybatis + 的demo √
- 使用junit进行单元测试,使用runwith √
- 探究一下springbootTest注解
- 前端初始化
- 登录 / 注册
- 前端
- 删除冗余代码
- 后端
- 前端
- 用户管理(仅管理员可见)
- 前端
- 后端
今日计划(第二次直播)
- 开发完成后端登录功能 20 min(单机登录 => 后续改造为分布式 / 第三方登录)√
- 开发后端用户的管理接口 5 min(用户的查询 / 状态更改)√
- 后端接口测试 √
- 开发前端用户登录注册功能 40 min - 1h
- 前端代码提交到github库中 √
- 前端冗余代码删除。√
- 重新设置的登录的请求参数 √
- 设置代理,使得前端请求能转发到后端。√
- 后端代码上传到github中 √
- 讨论如何校验用户(星球的小伙伴可以使用)
今日计划(3月25号直播)
- 完成注册功能的前端开发
- 解决拦截url并重定向到登录界面问题(关注app || index.js文件中给登录做的拦截操作) ✔
- 注册界面表单编写 ✔
- 直接复用已有组件
- ts需要重新定义参数类型
- 定义前端发送请求的接口
- 增加一个入口访问注册界面 使用Link标签 ✔
- 前后端联调 ✔
- 获取用户的登录态 获取当前登录用户的信息接口 ✔
- 完成用户管理后台的前端开发
- 指定子路由 ✔
- 修改canAdmin方法保证能正常访问网页 ✔
- 学习了access的用法
- 学会了Access的组件的使用
- 开发用户的后台管理界面(前后端不需要联调可以这么玩)
- 定义表格列,确认列能正常展示 ✔
- 定义接口,修改请求参数,请求数据后,检查数据是否正确 ✔
- 在有数据的情况调整表格样式 ✔
- 调整一些枚举值的展示 ✔
- 联调前后端(后端开发已经完成)✔
- 前端代码瘦身 & 优化
- 后端代码优化20min
- 讨论及开发星球用户校验
- 项目拓展思路
今日计划(04-04)
- 开发用户注销前端 7 分钟 / 后端 3 分钟 ✔
- 补充用户注册校验逻辑前端 10 分钟 / 后端 10 分钟
- 我这边不需要做额外的账户校验,所以暂时不用这个,
- 可以后续做一个手机号的验证码登录以及微信扫码登录的升级
- 后端代码优化 20 - 30 min
- 封装通用的返回对象
- 封装错误码的枚举类 ✔
- 封装通用的返回对象 ✔
- 封装生成通用返回对象的工具类 ✔
- 封装通用的异常类,以及全局的异常处理
- 分装通用异常类 ✔
- 封装通用的返回对象
- 前端代码优化 5 - 10 min
- 定义全局的拦截器,如果返回正常则获取数据返回
- 如果返回异常码在,则提示用户
今日计划(04-17)
部署 - 直播内容
- 多环境 5 - 10min
- 项目部署上线 1h √
- 原始前端 / 后端项目
- 宝塔 Linux
- 容器
- 容器平台
- 前后端的联调 —— 跨域 15 min
- 用户中心项目扩展和规划(优化点)5 - 10 min
业务实现:
注册逻辑
- 用户在前端输入账户和密码、以及校验码(todo)
- 校验用户的账户、密码、校验密码,是否符合要求
- 非空
- 账户长度 不小于 4 位
- 密码就 不小于 8 位吧
- 账户不能重复
- 账户不包含特殊字符
- 密码和校验密码相同
- 对密码进行加密(密码千万不要直接以明文存储到数据库中)
- 向数据库插入用户数据
登录接口逻辑
-
校验用户账户和密码是否合法
- 非空
- 账户长度 不小于 4 位
- 密码就 不小于 8 位吧
- 账户不包含特殊字符
-
校验密码是否输入正确,要和数据库中的密文密码去对比
-
用户信息脱敏,隐藏敏感信息,防止数据库中的字段泄露
-
我们要记录用户的登录态(session),将其存到服务器上(用后端 SpringBoot 框架封装的服务器 tomcat 去记录)
cookie
-
返回脱敏后的用户信息
-
用户登录必须使用鉴权
查询接口
- 检查用户是否为管理员
- 根据username输入查询用户
- 允许输入为空,输入为空时默认查询所有
- 根据用户输入进行模糊查询
注销用户
直接在session中删除用户即可。
项目部署
原生命令部署
1、后端部署
-
新建一个application-prod.yml的文件,并配置生产对应的配置文件属性
-
执行maven的打包命令 (图形界面操作点击package即可)
-
使用java命令启动jar包**(注意profiles 后面带s)**
java -jar .\user-center-backend-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod
使用指定的yml启动jar包会提示(如果提示是没有指定yml使用默认启动,spring.profiles.active=prod没有生效):
2023-09-21 04:55:25.271 INFO 36896 --- [ main] c.c.u.UsercenterBackendApplication : The following 1 profile is active: "prod"
2、前端部署
请求地址:
-
开发环境: localhost:8080
-
线上环境: xxx.com
用了umi框架,build时会自动传入一个NODE_ENV == production的参数,npm run start的NODE_ENV === development
-
启动环境:
- 本地启动:npm run start(本地启动,监听端口,自动更新)
- 线上启动: npm run build(项目构建打包),可以使用serve工具启动 (npm install -g serve )
- 这里需要修改拦截器以修改拦截器的发送请求的前缀(只是一种方法)
修改配置:
拦截器文件: src/request/gobalRequest.ts
const request = extend({
credentials: 'include', // 默认请求是否带上cookie
prefix: process.env.NODE_ENV === 'production' ? 'https://123.com' : undefined
});
前端访问请求:
-
项目的配置
不同的项目(框架)都有不同的配置文件,umi 的配置文件是 config,可以在配置文件后添加对应的环境名称后缀来区分开发环境和生产环境。参考文档:https://umijs.org/zh-CN/docs/deployment
- 开发环境:config.dev.ts
- 生产环境:config.prod.ts
- 公共配置:config.ts 不带后缀
宝塔部署
Linux 运维面板
官方安装教程:https://www.bt.cn/new/download.html
方便管理服务器、方便安装软件
容器部署
docker 是容器,可以将项目的环境(比如 java、nginx)和项目的代码一起打包成镜像,所有同学都能下载镜像,更容易分发和移植。
再启动项目时,不需要敲一大堆命令,而是直接下载镜像、启动镜像就可以了。
docker 可以理解为软件安装包。
Docker 安装:https://www.docker.com/get-started/ 或者宝塔安装
Dockerfile 用于指定构建 Docker 镜像的方法
Dockerfile 一般情况下不需要完全从 0 自己写,建议去 github、gitee 等托管平台参考同类项目(比如 springboot)
Dockerfile 编写:
- FROM 依赖的基础镜像
- WORKDIR 工作目录
- COPY 从本机复制文件
- RUN 执行命令
- CMD / ENTRYPOINT(附加额外参数)指定运行容器时默认执行的命令
根据 Dockerfile 构建镜像:
# 后端
docker build -t user-center-backend:v0.0.1 .
# 前端
docker build -t user-center-front:v0.0.1 .
Docker 构建优化:减少尺寸、减少构建时间(比如多阶段构建,可以丢弃之前阶段不需要的内容)
docker run 启动
# 前端
docker run -p 80:80 -d user-center-frontend:v0.0.1
# 后端
docker run -p 8080:8080 user-center-backend:v0.0.1
虚拟化
- 端口映射:把本机的资源(实际访问地址)和容器内部的资源(应用启动端口)进行关联
- 目录映射:把本机的端口和容器应用的端口进行关联
进入容器
docker exec -i -t fee2bbb7c9ee /bin/bash
查看进程
docker ps
查看日志
docker logs -f [container-id]
杀死容器
docker kill
强制删除镜像
docker rmi -f
绑定域名
前端项目访问:用户输入网址 => 域名解析服务器(把网址解析为 ip 地址 / 交给其他的域名解析服务) =>
服务器 =>(防火墙)=> nginx 接收请求,找到对应的文件,返回文件给前端 => 前端加载文件到浏览器中(js、css) => 渲染页面
后端项目访问:用户输入网址 => 域名解析服务器 => 服务器 => nginx 接收请求 => 后端项目(比如 8080端口)
nginx 反向代理:替服务器接收请求,转发请求
笔记
三种初始化java项目的方式
1、github 下载现成的代码
2、springboot官方的模板生成器
自动生成器的使用
MyBatisX 插件,自动根据数据库生成 domain 实体对象、mapper(操作数据库的对象)、mapper.xml(定义了 mapper对象和数据库的关联,可以在里面自己写 SQL)、service(包含常用的增删改查)、serviceImpl(具体实现 service)
如何知道是某个用户登录了?
javaWeb知识
1、连接服务器后,得到一个匿名session
2、登录成功后,得到登录成功的session,并给该session设置一些值(比如用户信息),返回给前端一个设置cookies的命令。 session => cookies
3、前端收到后端的命令后,设置cookie,保存到浏览器内。
4、前端再次请求后端的时候,在请求头中带上cookies去做请求
5、后端拿到前端传来的cookie,找到对应的session
6、后端从session中可以取出session中存储变量
使用mybatis plus的逻辑删除
步骤 1: 配置com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig
- 例: application.yml
mybatis-plus:
global-config:
db-config:
logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
步骤 2: 实体类字段上加上@TableLogic
注解
@TableLogic
private Integer deleted;
我得版本超过了3.3.0因此我不配置然后做一下测试。确实可用,但是也遇到了一个小的问题,则就是
代理
正向代理:替客户端向服务器发送请求。
反向代理:替服务器统一接受请求。
控制层 Controller 封装请求
application.yml 指定接口全局 api
servlet:
context-path: /api
@RestController 适用于编写 restful 风格的 api,返回值默认为 json 类型
controller 层倾向于对请求参数本身的校验,不涉及业务逻辑本身(越少越好)
service 层是对业务逻辑的校验(有可能被 controller 之外的类调用)
Ant Design Pro(Umi 框架)
app.tsx 项目全局入口文件,定义了整个项目中使用的公共数据(比如用户信息)
access.ts 控制用户的访问权限
首次访问页面(刷新页面),进入 app.tsx,执行 getInitialState 方法,该方法的返回值就是全局可用的状态值。
ProComponents 高级表单
- 通过 columns 定义表格有哪些列
- columns 属性
- dataIndex 对应返回数据对象的属性
- title 表格列名
- copyable 是否允许复制
- ellipsis 是否允许缩略
- valueType:用于声明这一列的类型(dateTime、select)
待优化点 todo
- 前端密码重复提示(可能有别的优化方式)
- 注册没有友好的提示
- 用户注销
- 优化查询接口(支持更多查询)
MFSU:前端编译优化
Ant Design 组件库 => React
Ant Design Procomponents => Ant Design
Ant Design Pro 后台管理系统 => Ant Design、React、Ant Design Procomponents、其他的库
UMI定义全局拦截器:
自定义的 request文件
/**
* request 网络请求工具
* 更详细的 api 文档: https://github.com/umijs/umi-request
*/
import {extend} from 'umi-request';
import {message} from "antd";
const request = extend({
credentials: 'include', // 默认请求是否带上cookie
});
/**
* 所有响应拦截器
*/
/**
* 所有响应拦截器
*/
request.interceptors.response.use(async (response: any, options: any): Promise<any> => {
const res = await response.clone().json();
if (res.code === '0') {
return res.data;
}
// 如果报错则需要提示用户错误信息
message.error(res.description)
return res.data;
});
export default request;
在发送请求出引入自定义的request文件,使用这个代替UMI自带的request
// @ts-ignore
/* eslint-disable */
import request from "@/request/gobalRequest";
多环境
本地开发:localhost(127.0.0.1)
多环境:指同一套项目代码在不同的阶段需要根据实际情况来调整配置并且部署到不同的机器上。
为什么需要?
- 每个环境互不影响
- 区分不同的阶段:开发 / 测试 / 生产
- 对项目进行优化:
- 本地日志级别
- 精简依赖,节省项目体积
- 项目的环境 / 参数可以调整,比如 JVM 参数
针对不同环境做不同的事情。
在后端中文件写入一个文件,记录sql
create table user
(
id bigint auto_increment comment '用户id'
primary key,
user_account varchar(256) null comment '用户账户',
username varchar(256) null comment '用户名',
avatar_url varchar(1024) null comment '用户头像地址',
gender tinyint default 0 not null comment '性别',
password varchar(256) null comment '密码',
email varchar(512) null comment '邮箱',
user_role int default 0 not null comment '用户角色 0-用户 1-管理员',
user_status int default 0 not null comment '用户状态可拓展 0-有效 1表示无效',
create_time timestamp default CURRENT_TIMESTAMP not null,
update_time timestamp default CURRENT_TIMESTAMP not null comment '更新时间',
is_delete tinyint default 0 not null comment '是否删除 0-没有删除 1-表示删除'
)
comment '用户信息表';
问题记录
1、node17+版本以上 ,安装umi3后,启动项目报错。
原因:因为 node.js V17版本中最近发布的OpenSSL3.0, 而OpenSSL3.0对允许算法和密钥大小增加了严格的限制,反正咱是没看懂,大概就是因为加了某些限制
解决方案:
window系统在idea终端上设置
set NODE_OPTIONS=--openssl-legacy-provider
还有一种配置环境变量的方法:
将这个–openssl-legacy-provider值配置到环境变量中即可一劳永逸的解决。
或者将其配置到命令中(记得写&&):这个实际解决了问题的√
"dev": "set NODE_OPTIONS=--openssl-legacy-provider && npm run start:dev ",
2、yarn安装报错
实际是因为没有初始化git导致 husky无法安装
解决方案: 初始化git
git init
3、疑问: 官网在日期为9/2版本中,
没有在提供umi-ui的依赖的开启命令,可能是有什么缺陷?但是命令安装又可以。
4、@Resource 和 @Autowire的区别
使用@Autowired 注解,会按类型装配,如果有多个同类型的 bean,会抛出异常。
使用@Resource 注解,会按名称装配,如果名称不存在,会使用类型装配。
如果你的项目中没有多个同类型的bean,那么@Autowired和@Resource是可以互换使用的,如果有多个同类型的bean,那么就要使用@Resource进行指定名称注入。
如果有多个同类型的bean,但是你没有使用@Resource进行名称指定,就会抛出异常,所以在使用@Autowired注解时,要确保只有一个同类型的bean。
同类型bean:如果一个基类被多个继承继承(或者一接口被多个类实现),同时他们被这些类统称为基类的同类bean。
还有一种就是一个类有多个bean在spring容器中,这种bean也叫同类bean。
回到上面的问题: 如果是application容器中有多个同类bean,且你指定基类的实例由byType注入时,这个时候则会发生报错。
5、使用mybatis x生成没有mapper文件时,
注意是是不是第二步中没有勾选使用的mybatis plus版本
6、使用rest api接口调用服务时,
首先报错415,加上编码格式后,提示数据格式
暂时尚未定位原因,但是加上@ResponeBody注解问题解决。
7.遭遇问题 前端能正常启动但是访问不了前端界面,
解决问题: 换浏览器启动即可,目前是谷歌浏览器无法启动。
8、因为所有文件爆红,所以需要设置git的忽略文件夹
umi项目的git忽略文件设置(远程直接创建):
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
**/node_modules
# roadhog-api-doc ignore
/src/utils/request-temp.js
_roadhog-api-doc
# production
/dist
# misc
.DS_Store
npm-debug.log*
yarn-error.log
/coverage
.idea
yarn.lock
package-lock.json
pnpm-lock.yaml
*bak
# visual studio code
.history
*.log
functions/*
.temp/**
# umi
.umi
.umi-production
# screenshot
screenshot
.firebase
.eslintcache
build
9.提交代码时报错:
husky - commit-msg hook exited with code 1 (error)
原因是开启了husky的校验
解决方案:
1、提交commit的message格式为:
git commit -m "fix: 初始化项目"
10、页面重定向:
代码中做了判断,需要设置逻辑改写代码中的判断逻辑
11、在nginx目录中 执行./config文件报错:
./configure: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using --without-http_rewrite_module
option, or install the PCRE library into the system, or build the PCRE library
statically from the source with nginx by using --with-pcre=<path> option.
解决办法:
1、首先检查是否已经安装pcre包,
rpm -qa pcre
这里我虽然检查了发现已经安装包了,跑./configuer脚本还是报错,所以最后还是重新执行了一下安装
2、重新安装pcre包
yum install pcre pcre-devel
3、再次跑./configuer脚本检查,这次应该是安装成功了。