1.短信登录

1.导入黑马点评项目

1.1 首先,导入课前资料提供的SQL文件:

CleanShot 2025-10-12 at 14.54.47@2x.png

CleanShot 2025-10-12 at 14.55.02@2x.png

CleanShot 2025-10-12 at 14.55.16@2x.png

1.2 导入后端项目

在资料中提供了一个项目源码:

CleanShot 2025-10-12 at 14.56.29@2x.png

将其复制到你的idea工作空间,然后利用idea打开即可:

CleanShot 2025-10-12 at 14.56.43@2x.png

启动项目后,在浏览器访问: http://localhost:8081/shop-type/list 如果可以看到数据则证明运行没有问题

不要忘了修改application.yaml文件中的mysql、redis地址信息

1.3 导入前端项目

在资料中提供了一个nginx文件夹:

CleanShot 2025-10-12 at 15.10.28@2x.png

将其复制到任意目录,要确保该目录不包含中文、特殊字符和空格,例如:

CleanShot 2025-10-12 at 15.10.42@2x.png

运行前端项目

在nginx所在目录下打开一个CMD窗口,输入命令:

start nginx. exe

打开chrome浏览器,在空白页面点击鼠标右键,选择检查,即可打开开发者工具:

CleanShot 2025-10-12 at 15.23.53@2x.png

然后打开手机模式:

CleanShot 2025-10-12 at 15.24.07@2x.png

然后访问: http://127.0.0.1:8080 即可看到页面

如果是macOS,这样启动:

macOS 启动 Nginx 完整指南

🚨 重要提示

nginx.exe 是 Windows 可执行文件,无法在 macOS 上直接运行!

您需要在 macOS 上重新安装 Nginx。


方案一:使用 Homebrew 安装(强烈推荐)⭐

Step 1: 安装 Homebrew(如果还没有)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Step 2: 安装 Nginx
brew install nginx
Step 3: 启动 Nginx
# 方法1: 直接启动
sudo nginx

# 方法2: 使用 Homebrew 服务(推荐)
brew services start nginx

# 查看状态
brew services list
Step 4: 验证安装
# 检查 Nginx 版本
nginx -v

# 测试配置文件
nginx -t

# 访问测试
open http://localhost:8080
常用命令
# 启动
brew services start nginx
# 或
sudo nginx

# 停止
brew services stop nginx
# 或
sudo nginx -s stop

# 重启
brew services restart nginx
# 或
sudo nginx -s reload

# 查看状态
brew services list

方案二:迁移您当前的配置

如果您想使用当前目录的配置文件:

Step 1: 安装 Nginx(同上)
brew install nginx
Step 2: 复制配置文件
# 找到 Homebrew 安装的 Nginx 配置目录
# 通常在:/opt/homebrew/etc/nginx/ 或 /usr/local/etc/nginx/

# 复制您的配置
cp ~/用户/oxy/文稿/program/front/nginx-1.18.0/conf/nginx.conf /opt/homebrew/etc/nginx/nginx.conf

# 复制 html 文件
cp -r ~/用户/oxy/文稿/program/front/nginx-1.18.0/html/* /opt/homebrew/var/www/
Step 3: 测试并启动
# 测试配置
nginx -t

# 启动
sudo nginx

快速启动指南(推荐新手)

# 1. 安装 Nginx
brew install nginx

# 2. 查看安装位置
which nginx
# 输出:/opt/homebrew/bin/nginx

# 3. 查看配置文件位置
nginx -t
# 输出:nginx: configuration file /opt/homebrew/etc/nginx/nginx.conf test is successful

# 4. 启动 Nginx
brew services start nginx

# 5. 验证运行
curl http://localhost:8080
# 或在浏览器打开 http://localhost:8080

# 6. 查看日志
tail -f /opt/homebrew/var/log/nginx/access.log
tail -f /opt/homebrew/var/log/nginx/error.log

常见问题解决

1. 端口被占用
# 查看占用端口的进程
sudo lsof -i :8080

# 杀死进程
sudo kill -9 <PID>
2. 权限问题
# 确保有执行权限
sudo nginx

# 或修改配置文件中的用户
# 编辑 /opt/homebrew/etc/nginx/nginx.conf
# 将 user nobody; 改为 user 你的用户名;
3. 配置文件路径
# Homebrew 安装的 Nginx 配置文件位置
# Intel Mac: /usr/local/etc/nginx/
# Apple Silicon (M1/M2): /opt/homebrew/etc/nginx/

# 网站根目录
# Intel Mac: /usr/local/var/www/
# Apple Silicon: /opt/homebrew/var/www/

我的推荐方案 🎯

我建议:

  1. 使用 Homebrew 安装 Nginx(最简单)
  2. 将您的配置文件复制到新的 Nginx 配置目录
  3. 将 html 文件复制到新的网站根目录

具体操作:

# 1. 安装
brew install nginx

# 2. 备份原配置
cp /opt/homebrew/etc/nginx/nginx.conf /opt/homebrew/etc/nginx/nginx.conf.backup

# 3. 复制您的配置(需要调整路径)
cp ~/用户/oxy/文稿/program/front/nginx-1.18.0/conf/nginx.conf /opt/homebrew/etc/nginx/

# 4. 复制网站文件
cp -r ~/用户/oxy/文稿/program/front/nginx-1.18.0/html/* /opt/homebrew/var/www/

# 5. 测试配置
nginx -t

# 6. 启动
brew services start nginx

2.基于Session实现登录

CleanShot 2025-10-12 at 15.37.45@2x.png

2.1 发送短信验证码

CleanShot 2025-10-12 at 15.40.29@2x.png

package com.hmdp.service.impl;  
  
import cn.hutool.core.util.RandomUtil;  
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;  
import com.hmdp.dto.Result;  
import com.hmdp.entity.User;  
import com.hmdp.mapper.UserMapper;  
import com.hmdp.service.IUserService;  
import com.hmdp.utils.RegexUtils;  
import lombok.extern.slf4j.Slf4j;  
import org.springframework.stereotype.Service;  
  
import javax.servlet.http.HttpSession;  
  
/**  
 * <p>  
 * 服务实现类  
 * </p>  
 *  
 * @author 虎哥  
 * @since 2021-12-22  
 */@Slf4j  
@Service  
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {  
  
    @Override  
    public Result setCode(String phone, HttpSession session) {  
        // 1.校验手机号  
        if (!RegexUtils.isPhoneInvalid(phone)) {  
            // 2.如果不符合,返回错误信息  
            return Result.fail("手机号格式错误!");  
        }  
        // 3.如果符合,生成一个验证码  
        String code = RandomUtil.randomNumbers(6);  
  
        // 4.保存验证码到session  
        session.setAttribute("code", code);  
  
        // 5.发送验证码  
        log.debug("发送短信验证码成功,验证码:{}", code);  
  
        // 6.返回ok  
        return Result.ok();  
    }  
}

2.2 短信验证码登录

CleanShot 2025-10-12 at 15.52.24@2x.png

package com.hmdp.service.impl;  
  
import cn.hutool.core.util.RandomUtil;  
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;  
import com.hmdp.dto.LoginFormDTO;  
import com.hmdp.dto.Result;  
import com.hmdp.entity.User;  
import com.hmdp.mapper.UserMapper;  
import com.hmdp.service.IUserService;  
import com.hmdp.utils.RegexUtils;  
import lombok.extern.slf4j.Slf4j;  
import org.springframework.stereotype.Service;  
  
import javax.servlet.http.HttpSession;  
  
/**  
 * <p>  
 * 服务实现类  
 * </p>  
 *  
 * @author 虎哥  
 * @since 2021-12-22  
 */@Slf4j  
@Service  
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {  
  
    @Override  
    public Result setCode(String phone, HttpSession session) {  
        // 1.校验手机号  
        if (!RegexUtils.isPhoneInvalid(phone)) {  
            // 2.如果不符合,返回错误信息  
            return Result.fail("手机号格式错误!");  
        }  
        // 3.如果符合,生成一个验证码  
        String code = RandomUtil.randomNumbers(6);  
  
        // 4.保存验证码到session  
        session.setAttribute("code", code);  
  
        // 5.发送验证码  
        log.debug("发送短信验证码成功,验证码:{}", code);  
  
        // 6.返回ok  
        return Result.ok();  
    }  
  
    @Override  
    public Result login(LoginFormDTO loginForm, HttpSession session) {  
        // 1.校验手机号  
        String phone = loginForm.getPhone();  
        if (!RegexUtils.isPhoneInvalid(phone)) {  
            // 2.如果不符合,返回错误信息  
            return Result.fail("手机号格式错误!");  
        }  
  
        // 2.校验验证码  
        Object cacheCode = session.getAttribute("code");  
        String code = loginForm.getCode();  
        if (cacheCode == null || !cacheCode.toString().equals(code)) {  
            // 3.如果不一致,报错  
            return Result.fail("验证码错误!");  
        }  
  
        // 4.如果一致,根据手机号查询用户 select * from tb_user where phone = ?        User user = query().eq("phone", phone).one();  
  
        // 5.判断用户是否存在  
        if (user == null) {  
            // 6.如果不存在,创建新用户并保存  
            user = createUserWithPhone(phone);  
        }  
  
        // 7.如果存在,保存用户信息到session  
        session.setAttribute("user", user);  
  
        // 8.返回ok  
        return Result.ok();  
    }  
  
    private User createUserWithPhone(String phone) {  
        // 1.创建用户  
        User user = new User();  
        user.setPhone(phone);  
        user.setNickName("user_" + RandomUtil.randomString(10));  
        // 2.保存用户  
        save(user);  
        // 3.返回用户  
        return user;  
    }  
}

2.3 登录验证功能

CleanShot 2025-10-12 at 16.46.45@2x.png

CleanShot 2025-10-12 at 16.49.33@2x.png

package com.hmdp.utils;  
  
import com.hmdp.dto.UserDTO;  
import org.springframework.web.servlet.HandlerInterceptor;  
  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
import javax.servlet.http.HttpSession;  
  
/**  
 * 这个类是:  
 *  
 * @author: CHINHAE  
 * @date: 2025/10/12 16:51  
 * @version: 1.0  
 */public class LoginInterceptor implements HandlerInterceptor{  
    @Override  
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  
        // 1.获取session  
        HttpSession session = request.getSession();  
        // 2.获取session中的用户  
        Object user = session.getAttribute("user");  
        // 3.判断用户是否存在  
        if (user == null) {  
            // 4.如果用户不存在,返回false  
            response.setStatus(401);  
            return false;  
        }  
        // 5.如果用户存在,将用户信息保存到ThreadLocal  
        UserHolder.saveUser((UserDTO) user);  
        // 6.放行  
        return true;  
    }  
  
    @Override  
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {  
        // 1.移除ThreadLocal中的用户  
        UserHolder.removeUser();  
    }    
}
package com.hmdp.config;  
  
import com.hmdp.utils.LoginInterceptor;  
import org.springframework.context.annotation.Configuration;  
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;  
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;  
  
/**  
 * 这个类是:  
 *  
 * @author: CHINHAE  
 * @date: 2025/10/12 16:58  
 * @version: 1.0  
 */@Configuration  
public class MvcConfig implements WebMvcConfigurer {  
  
    @Override  
    public void addInterceptors(InterceptorRegistry registry) {  
        registry.addInterceptor(new LoginInterceptor())  
            .excludePathPatterns(  
                "/user/code",   
"/user/login",   
"/blog/hot",   
"/shop/**",   
"/shop-type/**",   
"/voucher/**",  
                "/upload/**"  
                );  
    }  
}
package com.hmdp.service.impl;  
  
import cn.hutool.core.bean.BeanUtil;  
import cn.hutool.core.util.RandomUtil;  
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;  
import com.hmdp.dto.LoginFormDTO;  
import com.hmdp.dto.Result;  
import com.hmdp.dto.UserDTO;  
import com.hmdp.entity.User;  
import com.hmdp.mapper.UserMapper;  
import com.hmdp.service.IUserService;  
import com.hmdp.utils.RegexUtils;  
import lombok.extern.slf4j.Slf4j;  
import org.springframework.stereotype.Service;  
  
import javax.servlet.http.HttpSession;  
  
/**  
 * <p>  
 * 服务实现类  
 * </p>  
 *  
 * @author 虎哥  
 * @since 2021-12-22  
 */@Slf4j  
@Service  
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {  
  
    @Override  
    public Result setCode(String phone, HttpSession session) {  
        // 1.校验手机号  
        if (!RegexUtils.isPhoneInvalid(phone)) {  
            // 2.如果不符合,返回错误信息  
            return Result.fail("手机号格式错误!");  
        }  
        // 3.如果符合,生成一个验证码  
        String code = RandomUtil.randomNumbers(6);  
  
        // 4.保存验证码到session  
        session.setAttribute("code", code);  
  
        // 5.发送验证码  
        log.debug("发送短信验证码成功,验证码:{}", code);  
  
        // 6.返回ok  
        return Result.ok();  
    }  
  
    @Override  
    public Result login(LoginFormDTO loginForm, HttpSession session) {  
        // 1.校验手机号  
        String phone = loginForm.getPhone();  
        if (!RegexUtils.isPhoneInvalid(phone)) {  
            // 2.如果不符合,返回错误信息  
            return Result.fail("手机号格式错误!");  
        }  
  
        // 2.校验验证码  
        Object cacheCode = session.getAttribute("code");  
        String code = loginForm.getCode();  
        if (cacheCode == null || !cacheCode.toString().equals(code)) {  
            // 3.如果不一致,报错  
            return Result.fail("验证码错误!");  
        }  
  
        // 4.如果一致,根据手机号查询用户 select * from tb_user where phone = ?        User user = query().eq("phone", phone).one();  
  
        // 5.判断用户是否存在  
        if (user == null) {  
            // 6.如果不存在,创建新用户并保存  
            user = createUserWithPhone(phone);  
        }  
  
        // 7.如果存在,保存用户信息到session(将User转换为UserDTO)  
        UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);  
        session.setAttribute("user", userDTO);  
  
        // 8.返回ok  
        return Result.ok();  
    }  
  
    private User createUserWithPhone(String phone) {  
        // 1.创建用户  
        User user = new User();  
        user.setPhone(phone);  
        user.setNickName("user_" + RandomUtil.randomString(10));  
        // 2.保存用户  
        save(user);  
        // 3.返回用户  
        return user;  
    }  
}

3.集群的session共享问题

session共享问题:多台Tomcat并不共享session存储空间,当请求切换到不同tomcat服务时导致数据丢失的问题。

CleanShot 2025-10-12 at 17.28.53@2x.png

4.基于Redis实现共享session登录

保存登录的用户信息,可以使用String结构,以JSON字符串来保存,比较直观:

CleanShot 2025-10-12 at 17.39.47@2x.png

Hash结构可以将对象中的每个字段独立存储,可以针对单个字段做CRUD,并且内存占用更少:

CleanShot 2025-10-12 at 17.39.58@2x.png

CleanShot 2025-10-12 at 17.43.23@2x.png

CleanShot 2025-10-12 at 17.45.10@2x.png

Redis代替session需要考虑的问题:

  • 选择合适的数据结构
  • 选择合适的key
  • 选择合适的存储粒度
package com.hmdp.service.impl;  
  
import cn.hutool.core.bean.BeanUtil;  
import cn.hutool.core.bean.copier.CopyOptions;  
import cn.hutool.core.lang.UUID;  
import cn.hutool.core.util.RandomUtil;  
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;  
import com.hmdp.dto.LoginFormDTO;  
import com.hmdp.dto.Result;  
import com.hmdp.dto.UserDTO;  
import com.hmdp.entity.User;  
import com.hmdp.mapper.UserMapper;  
import com.hmdp.service.IUserService;  
import com.hmdp.utils.RegexUtils;  
import lombok.extern.slf4j.Slf4j;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.data.redis.core.StringRedisTemplate;  
import org.springframework.stereotype.Service;  
  
import javax.servlet.http.HttpSession;  
import java.util.HashMap;  
import java.util.Map;  
import java.util.concurrent.TimeUnit;  
  
import static com.hmdp.utils.RedisConstants.LOGIN_CODE_KEY;  
import static com.hmdp.utils.RedisConstants.LOGIN_CODE_TTL;  
import static com.hmdp.utils.RedisConstants.LOGIN_USER_KEY;  
import static com.hmdp.utils.RedisConstants.LOGIN_USER_TTL;  
  
/**  
 * <p>  
 * 服务实现类  
 * </p>  
 *  
 * @author 虎哥  
 * @since 2021-12-22  
 */@Slf4j  
@Service  
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {  
  
    @Autowired  
    private StringRedisTemplate stringRedisTemplate;  
  
    @Override  
    public Result setCode(String phone, HttpSession session) {  
        // 1.校验手机号  
        if (!RegexUtils.isPhoneInvalid(phone)) {  
            // 2.如果不符合,返回错误信息  
            return Result.fail("手机号格式错误!");  
        }  
        // 3.如果符合,生成一个验证码  
        String code = RandomUtil.randomNumbers(6);  
  
        // 4.保存验证码到redis // set key value ex 120 单位秒  
        stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY + phone, code, LOGIN_CODE_TTL, TimeUnit.MINUTES);  
  
        // 5.发送验证码  
        log.debug("发送短信验证码成功,验证码:{}", code);  
  
        // 6.返回ok  
        return Result.ok();  
    }  
  
    @Override  
    public Result login(LoginFormDTO loginForm, HttpSession session) {  
        // 1.校验手机号  
        String phone = loginForm.getPhone();  
        if (!RegexUtils.isPhoneInvalid(phone)) {  
            // 2.如果不符合,返回错误信息  
            return Result.fail("手机号格式错误!");  
        }  
  
        // 2.从redis中获取验证码  
        String cacheCode = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + phone);  
        String code = loginForm.getCode();  
        // 3.比较验证码  
        if (cacheCode == null || !cacheCode.equals(code)) {  
            // 3.如果不一致,报错  
            return Result.fail("验证码错误!");  
        }  
  
        // 4.如果一致,根据手机号查询用户 select * from tb_user where phone = ?        User user = query().eq("phone", phone).one();  
  
        // 5.判断用户是否存在  
        if (user == null) {  
            // 6.如果不存在,创建新用户并保存  
            user = createUserWithPhone(phone);  
        }  
  
        // 6.随机生成token,作为登录令牌  
        String token = UUID.randomUUID().toString(true);  
  
        // 7.将User对象换为Hash存储  
        UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);  
        Map<String, Object> userMap = BeanUtil.beanToMap(userDTO,new HashMap<>(),  
            CopyOptions.create()  
            .setIgnoreNullValue(true)  
            .setFieldValueEditor((fieldName, fieldValue) -> fieldValue.toString()));  
  
        // 8.存储token到redis  
        String tokenKey = LOGIN_USER_KEY + token;  
        stringRedisTemplate.opsForHash().putAll(tokenKey, userMap);  
        // 9.设置token的过期时间  
        stringRedisTemplate.expire(tokenKey, LOGIN_USER_TTL, TimeUnit.MINUTES);  
  
        // 9.返回ok  
        return Result.ok(token);  
    }  
  
    private User createUserWithPhone(String phone) {  
        // 1.创建用户  
        User user = new User();  
        user.setPhone(phone);  
        user.setNickName("user_" + RandomUtil.randomString(10));  
        // 2.保存用户  
        save(user);  
        // 3.返回用户  
        return user;  
    }  
}

5.登录拦截器的优化

之前的拦截器流程:

CleanShot 2025-10-12 at 18.45.30@2x.png

优化的流程:

CleanShot 2025-10-12 at 18.47.12@2x.png

package com.hmdp.config;  
  
import com.hmdp.utils.LoginInterceptor;  
import com.hmdp.utils.RefreshTokenInterceptor;  
import org.springframework.context.annotation.Configuration;  
import org.springframework.data.redis.core.StringRedisTemplate;  
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;  
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;  
  
import javax.annotation.Resource;  
  
/**  
 * 这个类是:  
 *  
 * @author: CHINHAE  
 * @date: 2025/10/12 16:58  
 * @version: 1.0  
 */@Configuration  
public class MvcConfig implements WebMvcConfigurer {  
  
    @Resource  
    private StringRedisTemplate stringRedisTemplate;  
  
    @Override  
    public void addInterceptors(InterceptorRegistry registry) {  
        // 登录拦截器  
        registry.addInterceptor(new LoginInterceptor())  
            .excludePathPatterns(  
                "/user/code",   
"/user/login",   
"/blog/hot",   
"/shop/**",   
"/shop-type/**",   
"/voucher/**",  
                "/upload/**"  
                ).order(1);  
  
        // 刷新token拦截器  
        registry.addInterceptor(new RefreshTokenInterceptor(stringRedisTemplate))  
            .addPathPatterns("/**").order(0);  
    }  
}
package com.hmdp.utils;  
  
import org.springframework.web.servlet.HandlerInterceptor;  
  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
  
/**  
 * 这个类是:  
 *  
 * @author: CHINHAE  
 * @date: 2025/10/12 16:51  
 * @version: 1.0  
 */public class LoginInterceptor implements HandlerInterceptor{  
  
    @Override  
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  
        // 1.判断是否需要拦截(ThreadLocal中是否有用户)  
        if (UserHolder.getUser() == null) {  
            // 2.没有,需要拦截,设置状态码  
            response.setStatus(401);  
            return false;  
        }  
        // 3.有,则放行  
        return true;  
    }  
}
package com.hmdp.utils;  
  
import cn.hutool.core.bean.BeanUtil;  
import cn.hutool.core.util.StrUtil;  
import com.hmdp.dto.UserDTO;  
import org.springframework.data.redis.core.StringRedisTemplate;  
import org.springframework.web.servlet.HandlerInterceptor;  
  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
import java.util.Map;  
import java.util.concurrent.TimeUnit;  
  
/**  
 * 这个类是:  
 *  
 * @author: CHINHAE  
 * @date: 2025/10/12 16:51  
 * @version: 1.0  
 */public class RefreshTokenInterceptor implements HandlerInterceptor{  
  
    private StringRedisTemplate stringRedisTemplate;  
  
    public RefreshTokenInterceptor(StringRedisTemplate stringRedisTemplate) {  
        this.stringRedisTemplate = stringRedisTemplate;  
    }  
  
    @Override  
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  
        // 1.获取请求头中的token  
        String token = request.getHeader("authorization");  
        if (StrUtil.isBlank(token)) {  
            return true;  
        }  
        // 2.基于token获取redis中的用户  
        String key = RedisConstants.LOGIN_USER_KEY + token;  
        Map<Object, Object> userMap = stringRedisTemplate.opsForHash()  
            .entries(key);  
        // 3.判断用户是否存在  
        if (userMap.isEmpty()) {  
            return true;  
        }  
        // 5.将查询到的Hash数据转换为UserDTO对象  
        UserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);  
  
        // 6.存在,则将用户信息保存到ThreadLocal  
        UserHolder.saveUser(userDTO);  
  
        // 7.刷新token的有效期  
        stringRedisTemplate.expire(key, RedisConstants.LOGIN_USER_TTL, TimeUnit.MINUTES);  
  
        // 8.放行  
        return true;  
    }  
  
    @Override  
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {  
        // 1.移除ThreadLocal中的用户  
        UserHolder.removeUser();  
    }  
  
  
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇