用户模块逻辑
PS:前期准备:
(1)使用逆向工程(MBG模块)中的generatorConfig.xml将数据库中的表信息生成对应的Mapper、Mapper.xml以及domain
(2)使用谷歌浏览器自带的Talend API作为测试工具
(一)用户注册_获取动态检验码
(1)获取otp(一次性密码)校验码的方法,传递电话号码为参数
(2)对otp的思考:
1、先查询当前用户有没有注册?注册了是不可以发验证码的
通过Mapper查询当前参数(电话号码)是否存在,若存在,抛出一个自定义的业务逻辑异常
2、校验60s后有无再次发送,校验码存在redis中
因为业务中将校验码存入到了redis中,因此只需要判断是否hasKey即可,如果存在则抛出业务逻辑异常
3、再生产随机校验码
生成6位随机数(0~10)的数字,存入redis中 key为固定信息+telPhone value是6位校验码,并设置一个超时时间。
(3)学习的知识:
@ConfigurationProperties(prefix = “redis.key”):该注解是获取application.yml的值。这块是设置一个校验码的统一前缀
(4)遇到的问题:
当code全写好,配置文件配好后,通过Talend API测试工具测试的时候,发现总是报400的错误,官方的解释是: 400:客户端请求的语法错误,服务器无法理解。
自己在排错的时候**刚开始以为是@RequestParam这个注解的问题(传递参数的数据类型有问题会报该状态码)**后来发现不是这个原因,哪里都不抛异常,我也没法下手。
结果找了一下午,在每阶段的code上加上sout的标记,最终发现是redis的问题,重启6379这个端口后,一切就恢复正常了。
分析原因:因为redis的6379这个进程在服务器上运行了一周了,可能当时是改变了redis的配置信息而没重启,就导致一个新的springboot项目无法使用该redis,但是可以连接的上,可能是这个原因吧,待考究。
(二)用户注册_用户简单逻辑注册
注册code的过程
1.传递的参数是一个JSON类型,包含注册时必须的信息,并且需要对信息加以格式验证。
2、例:JSON对象中phone类似的格式约束:
@NotBlank(message = "电话号码不允许为空")
@Length(max = 11,min = 11,message = "电话必须是11字符")
@Pattern(regexp = "^1[3|4|5|8][0-9]\\d{8}$",message = "电话号码格式不正确")
private String phone;
3、注册的时候需要填动态校验码,从redis中取即可
4、通过BeanUtils.copyProperties(register,umsMember);将注册信息传入用户实体中去
5、通过umsMember.setPassword(passwordEncoder.encode(register.getPassword()));将密码进行哈希言加密
6、通过Mapper将信息insert到数据库中
(三)用户登录
用户登录逻辑很简单,传递参数有username和password,通过Mapper对信息进行校验即可。
不过需要注意以下几点:
(1)//登录成功后需要用户信息存到session里面去
1、写一个模板BaseController,让MemberController继承该Controller即可,
该Controller可以用于取session、request、response
2、登录成功后将用户member放入Session中
3、目的是什么?
(2)登录需要有相应的拦截,拦截其他页面未有权限的登录
设置一个前置拦截器,防止一些未有权限的请求能进入到某些模块中
Code如下:
if(!ObjectUtils.isEmpty(request.getSession().getAttribute(“member”))){
//不是空的,则进入下一个拦截器进行操作
return true;
}
print(response,“您没有权限访问!请先登录.”);
return false;
(四)分布式Session问题(重点)
问题描述:
单体架构下的session存在web容器里,在运行的JVM里面(成百上千集群),意味着如果说当前有两台机器组成的
JVM集群,第一次登录通过nginx路由到1号节点,意味着session只在1号里存在。下次登录通过反向代理路由
到2号节点,此时session不存在。肯定有问题!
测试验证:
针对用一个模块,分别用8001端口和8002端口打开,当用户登录后,因为通过Nginx的反向代理,会出现上述的情景,
就是明明用户登录了,再点击下订单时提示用户需要登录的问题。
综上演化出了:
分布式session(Spring Session)
原理:
原来存储在JVM的concurrentHashMap,只有你这个jvm进程能访问到,如果换到其他的JVM就访问不到了。
springSession会把session存放在中间件里面去,支持的中间件有:redis、mysql、mangoDB
本次使用redis做存储session的中间件
redis中的key信息
- “spring:session:sessions:expires:3b82d562-a1b8-4b41-b6bf-b81e9b3528ff”
- “spring:session:sessions:3b82d562-a1b8-4b41-b6bf-b81e9b3528ff”
- “spring:session:expirations:1621681380000”
分布式Session应用:
1、引入依赖:
<!--Spring Session-->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
2、写一个配置类
//构造分布式session
//maxInactiveIntervalInSeconds 表示sesison的最大存活时间 1H
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 3600)
public class RedisHttpSessionConfiguration {
/**
* 引入分布式会话体系,会话内容存储在Redis当中,原理请阅读源码
*/
}