java——redis随笔——实战——短信登录

前言:

 

此章节用到的知识点:mybatisPlus  ;参考网址:https://www.bilibili.com/video/BV1Xu411A7tL?p=7&vd_source=79bbd5b76bfd74c2ef1501653cee29d6

 

 正常新建一个接口:

 再新建这个接口的实现类:

 

 

修改接口:

 修改实现类:

 

 

然后就可以注入并使用了:

 

 

 

 

=============================================================

 

 

 

 

此章节还需要参考:创建一个类来统一结果返回:https://blog.csdn.net/qq_42331202/article/details/115823134

 

 

 

统一的返回结果是 json 格式, 类似下面的数据结构

{
    "success": 布尔,//代表响应是否成功
    "code": 数字,//响应码
    "message": 字符串,//返回消息
    "data":HashMap //返回数据
}

 

 

首先写一个接口, 定义数据返回响应码

package com.example.learn.common;

/**

  • @author : wangbo
  • @version : 1.0
  • @date :Create in 2021/4/18
  • @description :
    */
    public interface ResultCode {
    // 成工时返回的状态码
    public static Integer SUCCESS=20000;
    // 失败是返回的状态码
    public static Integer ERROR=20001;

}

 

 

 

写统一返回结果的类

package com.example.learn.common;

import lombok.Data;

import java.util.HashMap;
import java.util.Map;

/**

  • @author : wangbo

  • @version : 1.0

  • @date :Create in 2021/4/18

  • @description :
    */
    @Data
    public class Result {
    private boolean success;
    private Integer code;
    private String message;
    private Map<String,Object> data=new HashMap<>();
    private Result(){

    }
    public static Result ok(){
    Result result
    =new Result();
    result.setSuccess(
    true);
    result.setCode(ResultCode.SUCCESS);
    result.setMessage(
    "成功");
    return result;
    }
    public static Result error(){
    Result result
    =new Result();
    result.setSuccess(
    false);
    result.setCode(ResultCode.ERROR);
    result.setMessage(
    "失败");
    return result;
    }
    public Result success(boolean success){
    this.setSuccess(success);
    return this;
    }
    public Result code(Integer code){
    this.setCode(code);
    return this;
    }

    public Result message(String message) {
    this.setMessage(message);
    return this;
    }

    public Result data(Map<String, Object> data) {
    this.setData(data);
    return this;
    }

}

 

 

 

 

 

 

 

其他参考:https://blog.csdn.net/qq_51447496/article/details/131414235?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-5-131414235-blog-104906051.235^v38^pc_relevant_anti_vip&spm=1001.2101.3001.4242.4&utm_relevant_index=8

 

 

 

 

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> {
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> code;
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String message;
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> T data;

</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Result(T data) {
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.code = 200<span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.message = "success"<span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.data =<span style="color: rgba(0, 0, 0, 1)"> data;
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> Result(T data, <span style="color: rgba(0, 0, 255, 1)">boolean</span><span style="color: rgba(0, 0, 0, 1)"> success, String message) {
    </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (success) {
        </span><span style="color: rgba(0, 0, 255, 1)">this</span>.code = 200<span style="color: rgba(0, 0, 0, 1)">;
        </span><span style="color: rgba(0, 0, 255, 1)">this</span>.message = "success"<span style="color: rgba(0, 0, 0, 1)">;
    } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
        </span><span style="color: rgba(0, 0, 255, 1)">this</span>.code = 500<span style="color: rgba(0, 0, 0, 1)">;
        </span><span style="color: rgba(0, 0, 255, 1)">this</span>.message =<span style="color: rgba(0, 0, 0, 1)"> message;
    }
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.data =<span style="color: rgba(0, 0, 0, 1)"> data;
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> Result(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> code, String message) {
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.code =<span style="color: rgba(0, 0, 0, 1)"> code;
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.message =<span style="color: rgba(0, 0, 0, 1)"> message;
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.data = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> &lt;T&gt; Result&lt;T&gt;<span style="color: rgba(0, 0, 0, 1)"> success(T data) {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> Result&lt;&gt;<span style="color: rgba(0, 0, 0, 1)">(data);
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> &lt;T&gt; Result&lt;T&gt;<span style="color: rgba(0, 0, 0, 1)"> fail(String message) {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> Result&lt;&gt;(500<span style="color: rgba(0, 0, 0, 1)">, message);
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> &lt;T&gt; Result&lt;T&gt; fail(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> code, String message) {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> Result&lt;&gt;<span style="color: rgba(0, 0, 0, 1)">(code, message);
}

}

 

 

 

 

 

 

======================================================================

 

 

 

 

 

拦截器:https://www.cnblogs.com/xiaobaibailongma/p/17060812.html

 

 

 

 

 

======================================================================

 

 

 

hutool 工具包快速入门:https://blog.csdn.net/Peaceuai/article/details/127953211

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;

import static com.hmdp.utils.RedisConstants.LOGIN_USER_KEY;
import static com.hmdp.utils.RedisConstants.LOGIN_USER_TTL;

public class RefreshTokenInterceptor implements HandlerInterceptor {

</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> StringRedisTemplate stringRedisTemplate;

</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> RefreshTokenInterceptor(StringRedisTemplate stringRedisTemplate) {
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.stringRedisTemplate =<span style="color: rgba(0, 0, 0, 1)"> stringRedisTemplate;
}

@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">boolean</span> preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> Exception {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 1.获取请求头中的token</span>
    String token = request.getHeader("authorization"<span style="color: rgba(0, 0, 0, 1)">);
    </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (StrUtil.isBlank(token)) {
        </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
    }
    
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 2.基于TOKEN获取redis中的用户</span>
    String key  = LOGIN_USER_KEY +<span style="color: rgba(0, 0, 0, 1)"> token;
    Map</span>&lt;Object, Object&gt; userMap =<span style="color: rgba(0, 0, 0, 1)"> stringRedisTemplate.opsForHash().entries(key);
    
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 3.判断用户是否存在</span>
    <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (userMap.isEmpty()) {
        </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
    }
    
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 5.将查询到的hash数据转为UserDTO</span>
    UserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, <span style="color: rgba(0, 0, 255, 1)">new</span> UserDTO(), <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">);
    
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 6.存在,保存用户信息到 ThreadLocal</span>

UserHolder.saveUser(userDTO);

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 7.刷新token有效期</span>

stringRedisTemplate.expire(key, LOGIN_USER_TTL, TimeUnit.MINUTES);

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 8.放行</span>
    <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
}

@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> Exception {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 移除用户</span>

UserHolder.removeUser();
}
}

 

 

 

 

 

======================================================================

 

 

 

 

 黑马视频地址:https://www.bilibili.com/video/BV1cr4y1671t?p=25&vd_source=79bbd5b76bfd74c2ef1501653cee29d6

 

 参考笔记博客:https://blog.csdn.net/weixin_50523986/article/details/131815165

 

 参考笔记博客:https://cyborg2077.github.io/2022/10/22/RedisPractice/#%E5%86%85%E5%AE%B9%E6%A6%82%E8%BF%B0

 

 

 

 

 ======================================================================

 

 

 

 

 

 

 

 

 

整体访问流程

 

 

 

 

 

 

 

 

 

IUserService
package com.hmdp.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.hmdp.dto.LoginFormDTO;
import com.hmdp.dto.Result;
import com.hmdp.entity.User;

import javax.servlet.http.HttpSession;

/**

  • <p>

  • 服务类

  • </p>

  • @author 虎哥

  • @since 2021-12-22
    */
    public interface IUserService extends IService<User> {

    Result sendCode(String phone, HttpSession session);

    Result login(LoginFormDTO loginForm, HttpSession session);

    Result sign();

    Result signCount();

}

 

 

 

 

UserServiceImpl
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 com.hmdp.utils.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.BitFieldSubCommands;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.hmdp.utils.RedisConstants.*;
import static com.hmdp.utils.SystemConstants.USER_NICK_NAME_PREFIX;

/**

  • <p>

  • 服务实现类

  • </p>

  • @author 虎哥

  • @since 2021-12-22
    */
    @Slf4j
    @Service
    public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public Result sendCode(String phone, HttpSession session) {
    // 1. 校验手机号
    if (RegexUtils.isPhoneInvalid(phone)) {
    // 2. 如果不符合,返回错误信息
    return Result.fail("手机号格式错误!");
    }
    // 3. 符合,生成验证码
    String code = RandomUtil.randomNumbers(6);

     </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 4.保存验证码到 session</span>
     stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY +<span style="color: rgba(0, 0, 0, 1)"> phone, code, LOGIN_CODE_TTL, TimeUnit.MINUTES);
    
     </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 5.发送验证码</span>
     log.debug("发送短信验证码成功,验证码:{}"<span style="color: rgba(0, 0, 0, 1)">, code);
     </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 返回ok</span>
     <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Result.ok();
    

    }

    @Override
    public Result login(LoginFormDTO loginForm, HttpSession session) {

     </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 1.校验手机号</span>
     String phone =<span style="color: rgba(0, 0, 0, 1)"> loginForm.getPhone();
     </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (RegexUtils.isPhoneInvalid(phone)) {
         </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 2.如果不符合,返回错误信息</span>
         <span style="color: rgba(0, 0, 255, 1)">return</span> Result.fail("手机号格式错误!"<span style="color: rgba(0, 0, 0, 1)">);
     }
    
     </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 3.从redis获取验证码并校验</span>
     String cacheCode = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY +<span style="color: rgba(0, 0, 0, 1)"> phone);
     String code </span>=<span style="color: rgba(0, 0, 0, 1)"> loginForm.getCode();
    
     </span><span style="color: rgba(0, 0, 255, 1)">if</span> (cacheCode == <span style="color: rgba(0, 0, 255, 1)">null</span> || !<span style="color: rgba(0, 0, 0, 1)">cacheCode.equals(code)) {
         </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 不一致,报错</span>
         <span style="color: rgba(0, 0, 255, 1)">return</span> Result.fail("验证码错误"<span style="color: rgba(0, 0, 0, 1)">);
     }
    
     </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 4.一致,根据手机号查询用户 select * from tb_user where phone = ?</span>
     User user = query().eq("phone"<span style="color: rgba(0, 0, 0, 1)">, phone).one();
    
     </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 5.判断用户是否存在</span>
     <span style="color: rgba(0, 0, 255, 1)">if</span> (user == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
         </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 6.不存在,创建新用户并保存</span>
         user =<span style="color: rgba(0, 0, 0, 1)"> createUserWithPhone(phone);
     }
    
     </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 7.保存用户信息到 redis中
     </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 7.1.随机生成token,作为登录令牌</span>
     String token = UUID.randomUUID().toString(<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
     </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 7.2.将User对象转为HashMap存储</span>
     UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
     Map</span>&lt;String, Object&gt; userMap = BeanUtil.beanToMap(userDTO, <span style="color: rgba(0, 0, 255, 1)">new</span> HashMap&lt;&gt;<span style="color: rgba(0, 0, 0, 1)">(),
             CopyOptions.create()
                     .setIgnoreNullValue(</span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">)
                     .setFieldValueEditor((fieldName, fieldValue) </span>-&gt;<span style="color: rgba(0, 0, 0, 1)"> fieldValue.toString()));
    
     </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 7.3.存储</span>
     String tokenKey = LOGIN_USER_KEY +<span style="color: rgba(0, 0, 0, 1)"> token;
     stringRedisTemplate.opsForHash().putAll(tokenKey, userMap);
    
     </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 7.4.设置token有效期</span>
    

stringRedisTemplate.expire(tokenKey, LOGIN_USER_TTL, TimeUnit.MINUTES);

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 8.返回token</span>
    <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Result.ok(token);
}

@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Result sign() {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 1.获取当前登录用户</span>
    Long userId =<span style="color: rgba(0, 0, 0, 1)"> UserHolder.getUser().getId();
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 2.获取日期</span>
    LocalDateTime now =<span style="color: rgba(0, 0, 0, 1)"> LocalDateTime.now();
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 3.拼接key</span>
    String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"<span style="color: rgba(0, 0, 0, 1)">));
    String key </span>= USER_SIGN_KEY + userId +<span style="color: rgba(0, 0, 0, 1)"> keySuffix;
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 4.获取今天是本月的第几天</span>
    <span style="color: rgba(0, 0, 255, 1)">int</span> dayOfMonth =<span style="color: rgba(0, 0, 0, 1)"> now.getDayOfMonth();
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 5.写入Redis SETBIT key offset 1</span>
    stringRedisTemplate.opsForValue().setBit(key, dayOfMonth - 1, <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Result.ok();
}

@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Result signCount() {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 1.获取当前登录用户</span>
    Long userId =<span style="color: rgba(0, 0, 0, 1)"> UserHolder.getUser().getId();
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 2.获取日期</span>
    LocalDateTime now =<span style="color: rgba(0, 0, 0, 1)"> LocalDateTime.now();
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 3.拼接key</span>
    String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"<span style="color: rgba(0, 0, 0, 1)">));
    String key </span>= USER_SIGN_KEY + userId +<span style="color: rgba(0, 0, 0, 1)"> keySuffix;
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 4.获取今天是本月的第几天</span>
    <span style="color: rgba(0, 0, 255, 1)">int</span> dayOfMonth =<span style="color: rgba(0, 0, 0, 1)"> now.getDayOfMonth();
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 5.获取本月截止今天为止的所有的签到记录,返回的是一个十进制的数字 BITFIELD sign:5:202203 GET u14 0</span>
    List&lt;Long&gt; result =<span style="color: rgba(0, 0, 0, 1)"> stringRedisTemplate.opsForValue().bitField(
            key,
            BitFieldSubCommands.create()
                    .get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(</span>0<span style="color: rgba(0, 0, 0, 1)">)
    );
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (result == <span style="color: rgba(0, 0, 255, 1)">null</span> ||<span style="color: rgba(0, 0, 0, 1)"> result.isEmpty()) {
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 没有任何签到结果</span>
        <span style="color: rgba(0, 0, 255, 1)">return</span> Result.ok(0<span style="color: rgba(0, 0, 0, 1)">);
    }
    Long num </span>= result.get(0<span style="color: rgba(0, 0, 0, 1)">);
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (num == <span style="color: rgba(0, 0, 255, 1)">null</span> || num == 0<span style="color: rgba(0, 0, 0, 1)">) {
        </span><span style="color: rgba(0, 0, 255, 1)">return</span> Result.ok(0<span style="color: rgba(0, 0, 0, 1)">);
    }
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 6.循环遍历</span>
    <span style="color: rgba(0, 0, 255, 1)">int</span> count = 0<span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">while</span> (<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">) {
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 6.1.让这个数字与1做与运算,得到数字的最后一个bit位  </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 判断这个bit位是否为0</span>
        <span style="color: rgba(0, 0, 255, 1)">if</span> ((num &amp; 1) == 0<span style="color: rgba(0, 0, 0, 1)">) {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果为0,说明未签到,结束</span>
            <span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
        }</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果不为0,说明已签到,计数器+1</span>
            count++<span style="color: rgba(0, 0, 0, 1)">;
        }
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 把数字右移一位,抛弃最后一个bit位,继续下一个bit位</span>
        num &gt;&gt;&gt;= 1<span style="color: rgba(0, 0, 0, 1)">;
    }
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Result.ok(count);
}

</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> User createUserWithPhone(String phone) {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 1.创建用户</span>
    User user = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> User();
    user.setPhone(phone);
    user.setNickName(USER_NICK_NAME_PREFIX </span>+ RandomUtil.randomString(10<span style="color: rgba(0, 0, 0, 1)">));
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 2.保存用户</span>

save(user);
return user;
}
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

UserController

package com.hmdp.controller;

import cn.hutool.core.bean.BeanUtil;
import com.hmdp.dto.LoginFormDTO;
import com.hmdp.dto.Result;
import com.hmdp.dto.UserDTO;
import com.hmdp.entity.User;
import com.hmdp.entity.UserInfo;
import com.hmdp.service.IUserInfoService;
import com.hmdp.service.IUserService;
import com.hmdp.utils.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;

/**

  • <p>

  • 前端控制器

  • </p>

  • @author 虎哥
    */
    @Slf4j
    @RestController
    @RequestMapping(
    "/user")
    public class UserController {

    @Resource
    private IUserService userService;

    @Resource
    private IUserInfoService userInfoService;

    /**

    • 发送手机验证码
      */
      @PostMapping(
      "code")
      public Result sendCode(@RequestParam("phone")String phone, HttpSession session) {
      // 发送短信验证码并保存验证码
      return userService.sendCode(phone, session);
      }

    /**

    • 登录功能
    • @param loginForm 登录参数,包含手机号、验证码;或者手机号、密码
      */
      @PostMapping(
      "/login")
      public Result login(@RequestBody LoginFormDTO loginForm, HttpSession session){
      // 实现登录功能
      return userService.login(loginForm, session);
      }

    /**

    • 登出功能
    • @return
      */
      @PostMapping(
      "/logout")
      public Result logout(){
      // TODO 实现登出功能
      return Result.fail("功能未完成");
      }

    @GetMapping("/me")
    public Result me(){
    // 获取当前登录的用户并返回
    UserDTO user = UserHolder.getUser();
    return Result.ok(user);
    }

    @GetMapping("/info/{id}")
    public Result info(@PathVariable("id")Long userId){
    // 查询详情
    UserInfo info = userInfoService.getById(userId);
    if (info == null) {
    // 没有详情,应该是第一次查看详情
    return Result.ok();
    }
    info.setCreateTime(
    null);
    info.setUpdateTime(
    null);
    // 返回
    return Result.ok(info);
    }

    @GetMapping("/{id}")
    public Result queryUserById(@PathVariable("id")Long userId){
    // 查询详情
    User user = userService.getById(userId);
    if (user == null) {
    return Result.ok();
    }
    UserDTO userDTO
    = BeanUtil.copyProperties(user, UserDTO.class);
    // 返回
    return Result.ok(userDTO);
    }

    @PostMapping("/sign")
    public Result sign(){
    return userService.sign();
    }

    @GetMapping("/sign/count")
    public Result signCount(){
    return userService.signCount();
    }
    }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Result 

package com.hmdp.dto;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;

/***

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
private Boolean success;
private String errorMsg;
private Object data;
private Long total;

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> Result ok()
{
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> Result(<span style="color: rgba(0, 0, 255, 1)">true</span>, <span style="color: rgba(0, 0, 255, 1)">null</span>, <span style="color: rgba(0, 0, 255, 1)">null</span>, <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">);
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> Result ok(Object data)
{
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> Result(<span style="color: rgba(0, 0, 255, 1)">true</span>, <span style="color: rgba(0, 0, 255, 1)">null</span>, data, <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">);
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> Result ok(List&lt;?&gt;<span style="color: rgba(0, 0, 0, 1)"> data, Long total)
{
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> Result(<span style="color: rgba(0, 0, 255, 1)">true</span>, <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">, data, total);
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> Result fail(String errorMsg)
{
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> Result(<span style="color: rgba(0, 0, 255, 1)">false</span>, errorMsg, <span style="color: rgba(0, 0, 255, 1)">null</span>, <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">);
}

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

userDTO

package com.hmdp.dto;

import lombok.Data;

@Data
public class UserDTO {
private Long id;
private String nickName;
private String icon;
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

LoginFormDTO

package com.hmdp.dto;

import lombok.Data;

@Data
public class LoginFormDTO {
private String phone;
private String code;
private String password;
}

 

 

 

 

 

 

 

 

User

package com.hmdp.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.time.LocalDateTime;

/**

  • <p>

  • </p>

  • @author 虎哥

  • @since 2021-12-22
    */
    @Data
    @EqualsAndHashCode(callSuper
    = false)
    @Accessors(chain
    = true)
    @TableName(
    "tb_user")
    public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    /**

    • 主键
      */
      @TableId(value
      = "id", type = IdType.AUTO)
      private Long id;

    /**

    • 手机号码
      */
      private String phone;

    /**

    • 密码,加密存储
      */
      private String password;

    /**

    • 昵称,默认是随机字符
      */
      private String nickName;

    /**

    • 用户头像
      */
      private String icon = "";

    /**

    • 创建时间
      */
      private LocalDateTime createTime;

    /**

    • 更新时间
      */
      private LocalDateTime updateTime;

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

RedisConstants

package com.hmdp.utils;

public class RedisConstants {
public static final String LOGIN_CODE_KEY = "login:code:";
public static final Long LOGIN_CODE_TTL = 2L;
public static final String LOGIN_USER_KEY = "login:token:";
public static final Long LOGIN_USER_TTL = 36000L;

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> Long CACHE_NULL_TTL = 2L<span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> Long CACHE_SHOP_TTL = 30L<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String CACHE_SHOP_KEY = "cache:shop:"<span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String LOCK_SHOP_KEY = "lock:shop:"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> Long LOCK_SHOP_TTL = 10L<span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String SECKILL_STOCK_KEY = "seckill:stock:"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String BLOG_LIKED_KEY = "blog:liked:"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String FEED_KEY = "feed:"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String SHOP_GEO_KEY = "shop:geo:"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String USER_SIGN_KEY = "sign:"<span style="color: rgba(0, 0, 0, 1)">;

}

 

 

 

 

 

 

 

 

 

 

RegexUtils 

 

package com.hmdp.utils;

import cn.hutool.core.util.StrUtil;

/**

  • @author 虎哥
    */
    public class RegexUtils {
    /**

    • 是否是无效手机格式
    • @param phone 要校验的手机号
    • @return true: 符合,false:不符合
      */
      public static boolean isPhoneInvalid(String phone){
      return mismatch(phone, RegexPatterns.PHONE_REGEX);
      }
      /**
    • 是否是无效邮箱格式
    • @param email 要校验的邮箱
    • @return true: 符合,false:不符合
      */
      public static boolean isEmailInvalid(String email){
      return mismatch(email, RegexPatterns.EMAIL_REGEX);
      }

    /**

    • 是否是无效验证码格式
    • @param code 要校验的验证码
    • @return true: 符合,false:不符合
      */
      public static boolean isCodeInvalid(String code){
      return mismatch(code, RegexPatterns.VERIFY_CODE_REGEX);
      }

    // 校验是否不符合正则格式
    private static boolean mismatch(String str, String regex){
    if (StrUtil.isBlank(str)) {
    return true;
    }
    return !str.matches(regex);
    }
    }

 

 

 

 

 

 

 

 

 

UserHolder

 

package com.hmdp.utils;

import com.hmdp.dto.UserDTO;

public class UserHolder {
private static final ThreadLocal<UserDTO> tl = new ThreadLocal<>();

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> saveUser(UserDTO user){
    tl.set(user);
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> UserDTO getUser(){
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> tl.get();
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> removeUser(){
    tl.remove();
}

}

 

 

 

 

 

 

 

 

 

 

  • 对于 token 有效期的设置:每当有一个请求进来,有效期就应该刷新,需要改变拦截器的代码
  • com/hmdp/interceptor/LoginInterceptor.java
    // 这里是拦截器 不在 spring 容器中 不能同 @Autowired 注入 stringRedisTemplate
    // 换个方法 在配置类中注入
    // 或者加个注解:@Configuration 就可以自动注入啦
    private StringRedisTemplate stringRedisTemplate;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 构造函数</span>
<span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> LoginInterceptor(StringRedisTemplate stringRedisTemplate) {
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.stringRedisTemplate =<span style="color: rgba(0, 0, 0, 1)"> stringRedisTemplate;
}

@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">boolean</span> preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> Exception {

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 1 获取请求头中的token
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 这一步需要前端把token保存到请求头中</span>
    String token = request.getHeader("authorization"<span style="color: rgba(0, 0, 0, 1)">);
    </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(StrUtil.isBlank(token)){
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 不存在 拦截 返回401状态码</span>
        response.setStatus(401<span style="color: rgba(0, 0, 0, 1)">);
        </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;
    }
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 2 基于token获取redis中的用户
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 只用 get 只能取出一个
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 用entrise  取出的是一个map</span>
    Map&lt;Object, Object&gt; userMap = stringRedisTemplate.opsForHash().entries(LOGIN_USER_KEY+<span style="color: rgba(0, 0, 0, 1)">token);

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 3 判断用户是否存在
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果userMap是null的话 自动返回一个空值</span>
    <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (userMap.isEmpty()){
        </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
    }

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 5 将查询到的Map对象转为UserDto
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 忽略转换过程的错误:肯定不忽略</span>
    UserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, <span style="color: rgba(0, 0, 255, 1)">new</span> UserDTO(),<span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">);

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 6 存在 保存用户信息到Threadlocal中</span>

UserHolder.saveUser(userDTO);

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 7 刷新token有效期</span>
    stringRedisTemplate.expire(LOGIN_USER_KEY+<span style="color: rgba(0, 0, 0, 1)">token,LOGIN_USER_TTL, TimeUnit.MINUTES);

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 8 放行</span>
    <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
}</span></pre>

 

 

 

 

 

 

  • com/hmdp/config/MvcConfig.java
package com.hmdp.config;
import com.hmdp.interceptor.LoginInterceptor;
import com.hmdp.interceptor.RefreshTokenInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
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;

@Configuration
public class MvcConfig implements WebMvcConfigurer {

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> @Configuration:这里可以注入</span>

@Autowired
private StringRedisTemplate stringRedisTemplate;

@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> addInterceptors(InterceptorRegistry registry) {

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 后执行 默认情况下按照添加顺序执行 拦截需要登录的请求</span>
    registry.addInterceptor(<span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> LoginInterceptor())
            .excludePathPatterns(
                    </span>"/user/code"<span style="color: rgba(0, 0, 0, 1)">,
                    </span>"/user/login"<span style="color: rgba(0, 0, 0, 1)">,
                    </span>"/blog/hot"<span style="color: rgba(0, 0, 0, 1)">,
                    </span>"/shop/**"<span style="color: rgba(0, 0, 0, 1)">,
                    </span>"/upload/**"<span style="color: rgba(0, 0, 0, 1)">,
                    </span>"/shop-type/**"<span style="color: rgba(0, 0, 0, 1)">,
                    </span>"/voucher/**"<span style="color: rgba(0, 0, 0, 1)">
            )
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 确定执行顺序 越小越先执行</span>
            .order(1<span style="color: rgba(0, 0, 0, 1)">);

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 先执行 拦截所有请求</span>
    registry.addInterceptor(<span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> RefreshTokenInterceptor(stringRedisTemplate))
            .addPathPatterns(</span>"/**"<span style="color: rgba(0, 0, 0, 1)">)
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 确定执行顺序 越小越先执行</span>
            .order(0<span style="color: rgba(0, 0, 0, 1)">);
}

}