黑马点评(速通版)
个人环境 Ubuntu 24.04
项目配置
-
repo: 搜一搜就行 https://github.com/cs001020/hmdp?tab=readme-ov-file
-
idea config: 降java版本到11就能不报错
-
redis, mysql: 搜索即可 systemd 启动
-
nginx 稍微复杂一点, 给的是win下的nginx, 配完systemd之后,用他的
nginx.conf替换/etc/nginx/nginx.conf(记得备份) 然后修改
# 指定前端项目所在的位置
location / {
root /home/ayanami/www/hmdp/html/hmdp; # 修改此处, 改为${下载的nginx文件夹原来位置}/hmdp/html/hmdp
<!--truncate--> index index.html index.htm;
}
即可
可能还需要在顶部修改 user ${Your User Name}
ps: nginx似乎套一层后会让之前的连接的token之类invalid掉, 例如b站 kimi 退出登录
目前不 知道除了简单sudo systemctl stop nginx的方法
会不会nginx丢docker里面之类别放本机跑好一点
登录
threadlocal
redis 存 session, 做水平拓展负载均衡
用户校验 phone key, 验证码 value
session信息, value 用hash而不用string(json)
存储session数据 value是一个"HashMap", 支持单字段crud, 内存占用少
key ? 生成一个唯一 token, 返回给客户端
redis key加业务前缀"login:code:"
设置有效期
redisTemplate.opsForValue().set(LOGIN_CODE_KEY + phone, code, 2, TimeUnit.MINUTES);
设置30min有效期
// 保存用户信息到redis
UserDTO userDTO = new UserDTO();
BeanUtils.copyProperties(user, UserDTO.class);
String token = UUID.randomUUID().toString(true);
Map<String, Object> userMap = BeanUtil.beanToMap(userDTO);
stringRedisTemplate.opsForHash().putAll(LOGIN_USER_KEY + token, userMap);
stringRedisTemplate.expire(LOGIN_USER_KEY + token, 30, TimeUnit.MINUTES);
return Result.ok();
"用户不活跃30min": 在拦截器里面更新token有效期(再调用一次expire就行)
自定义拦截器不能做依赖注入? 老实写构造函数, 在外部@Configuration的Configurer中注入, 再调用registry时构造
快捷键缩写行尾.var
这样redis + threadlocal就绕开了登录中tomcat的session机制,减少session传递开销
前端得到token在请求头里面放
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 1.获取请求头token
// 2.由token获取redis用户
// 3.判断token是否存在
// 4.保存用户到threadlocal
// 5.刷新用户token有效期
String token = request.getHeader("authorization");
if (StrUtil.isBlank(token)){
response.setStatus(401); // unauthorized
return false;
}
Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(LOGIN_USER_KEY + token);
UserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);
// exist, save user info
UserHolder.saveUser(userDTO);
stringRedisTemplate.expire(LOGIN_USER_KEY + token, LOGIN_USER_TTL, TimeUnit.MINUTES);
return true;
}
拦截器只拦需要登录的路径->再加一个新的拦截器, 拦所有路径
拦截器顺序, 可以.order调整优先级, 从order小到order大执行, 也可以默认(相同order按照添加顺序)