目录
项目搭建
项目库表
基本信息模块
tb_user
tb_user-info
tb_shop
tb_shop_type
方便对店铺进行分类
探店模块
tb_blog
记录探店日记
tb_follow
发自己的探店日记,吸引粉丝关注
消费模块
tb_voucher
优惠卷自身详细信息
tb_seckill_voucher
管理各个优惠卷
tb_voucher_order
项目架构
导入后端项目模板
pom依赖
使用到的技术 redis、mybatis-plus、lombok、hutool 以及一个打包插件
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
<version>8.0.28</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<!--hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.17</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
目录结构
配置文件
server:
port: 8081
spring:
application:
name: hmdp
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/hmdp?useSSL=false&serverTimezone=UTC
username: root
password: 1234
redis:
host: 192.168.83.100
port: 6379
password: 1234
lettuce:
pool:
max-active: 10
max-idle: 10
min-idle: 1
time-between-eviction-runs: 10s
jackson:
default-property-inclusion: non_null # JSON处理时忽略非空字段
mybatis-plus:
type-aliases-package: com.hmdp.entity # 别名扫描包
logging:
level:
com.hmdp: debug
运行前端项目
前端已经将项目打包放在nginx中 ,只需启动nginx即可
短信登录
基于session
整体流程
整体流程
发送验证码
发送验证码 并使用session校验
登录或注册
用户存在即登录,不存在即注册
完成根据验证码登录或注册
校验登录成功
以上功能完成后,用户填写手机号,验证码当登录成功后,又回到非登录状态 所以在访问请求时 需要找到session,为请求附上用户数据
由于每次请求都可能需要获取用户数据,因此要将其放入拦截器
中,
每一个请求都是一个独立的线程,将数据保存在线程域localThread
中 ,既能向下传递数据,又能防止多个线程干扰
修改 登录时放入session 的用户信息,将完成的user->userDto
创建一个拦截器 ,在访问controller之前 拦截所有请求
将拦截器添加进配置
再一次设置controller
数据放入session问题
session 共享问题 :tomcat可能以集群分布,不同的tomcat有都有自己的session ,但tomcat之前无法共享
解决思路:
- tomcat服务器 之间session 拷贝
问题:- 相同数据多处存储 造成内存浪费
- 不同服务器之间拷贝存在延时,可能出现请求到来之前没完成拷贝
- 替代session 将其单独拿出来,放在大家都能看得到的地方 使tomcat服务器之间共同使用
替代要求:- 数据能够被多台连接使用,达到数据共享
- 基于内存 ,性能上要与sesion相近
- K_V 键值对存储 ,方式与session相同
所以使用redis
替代session,将由jvm内存中储存的数据改为放在redis中,有cookie携带的sessionId改为从localStore取出携带的redis的key。session会自动更新有效期替代为 在拦截器中进行手动更新redis有效期。
这样还可以具有强制下线的功能
- 要使得redis中也不存放数据,可以将数据写入JWT。 JWT的特性导致他可以被查看,但无法被修改。可以将非敏感信息放入JWT,自己不做任何保留(包括JVM与外置缓存),实现无状态登录。但JWT签名一旦发布,后期对用户进行单独处理较为麻烦。
基于redis
放入redis的任何数据前 都要考虑它的过期时间
基于redis整体流程
变化:
- 当使用session时,请求凭证放入cookie 自动发放,携带,存储 。使用redis 要手动发放凭证(后端),存储凭证(前端)、携带凭证(前端)
- 使用sesion,浏览器会自动为其请求创建一个session,session是唯一的,存储数据只要当前线程不重复就可以(相当于每人都有个小箱子,每个箱子有唯一的钥匙key,自己独占一个箱子)。使用redis,redis是公共的 (相当于所有人共用一个大仓库,为防止他人使用,每个数据都要具有唯一的钥匙即key),因此存储数据要动设定唯一的key
- 服务器变成无状态 ,不保存任何信息
- 手动刷新凭证有效期
使用redis考虑的问题:
- 合适的数据存储结构
- 合适的key
- 合适的存储粒度
- 合适过期时间
发送验证码
改动:将验证码保存在redis中,key由code->手机号
效果
登录或注册
改动
- 将验证码改为根据手机号从redis中获取
- 将查询到的用户数据(登录)或新创建的用户数据(注册)保存在redis中
- 生成唯一字符作为key
- 将对象进行序列化(hash或String)
- 返回凭证信息(含有key的token)
解决redis中用户有效期刷新问题
在拦截器中 ,根据请求头中的token 判断是否登录的同时,也要刷新它的有效期,使得活跃用户不过期
-
创建只负责刷新token的拦截器
存在问题:
解决方式:
1 、手动将其map中k转为String类型
2、 -
重新编写登录检查拦截器
-
将两个拦截器进行配置,
注意先后顺序
检验是否登录成功
在拦截器基础上 ,不需要改动