利用Redis实现分布式Session
标签:项目总结, Redis

利用Redis实现分布式Session

1. 创建生成UUID的类

UUIDUtil

import java.util.UUID;

public class UUIDUtil {
    public static String uuid() {
        return UUID.randomUUID().toString().replace("-", "");
    }
}

2. 使用

在service的login方法中生成token,并添加到cookie中

//        利用uuid生成token
        String token = UUIDUtil.uuid();
        addCookie(response, token, user);

添加到cookie中

    private void addCookie(HttpServletResponse response, String token, MiaoshaUser user) {
//        生成cookie
//        以token为key,用户信息为value,存到redis中
        redisService.set(MiaoshaUserKey.token, token, user);
//        并把token放到cookie中
        Cookie cookie = new Cookie(COOKIE_NAME_TOKEN, token);
//        给cookie这是过期时间,这里设置和在redis中的key一样长的时间
        cookie.setMaxAge(MiaoshaUserKey.token.expireSeconds());
        cookie.setPath("/");
        response.addCookie(cookie);
    }

上面给token添加了一个前缀:

MiaoshaUserKey

public class MiaoshaUserKey extends BasePrefix {
    public static final int TOKEN_EXPIRE = 3600 * 24 * 2;

    public MiaoshaUserKey(int expireSeconds, String prefix) {
        super(expireSeconds, prefix);
    }

    public static MiaoshaUserKey token = new MiaoshaUserKey(TOKEN_EXPIRE, "tk");
}

这样下次请求的时候,就会将token传上来,我们根据取得到的token从redis中恢复出user信息。

5. Controller接受

获取token信息并从redis恢复user

    @RequestMapping("/to_list")
    public String toList(HttpServletResponse response, Model model,
                         @CookieValue(value = MiaoshaUserService.COOKIE_NAME_TOKEN, required = false) String cookieToken,
                         @RequestParam(value = MiaoshaUserService.COOKIE_NAME_TOKEN, required = false) String paramToken) { //获取token信息
        if (StringUtils.isEmpty(cookieToken) && StringUtils.isEmpty(paramToken)) { // 不存在token信息则未登陆,返回去登陆
            return "login";
        }
        String token = StringUtils.isEmpty(paramToken) ? cookieToken : paramToken;  //有些手机端是把cookie当做参数传过来的
        MiaoshaUser user = miaoshaUserService.getByToken(response, token);
        model.addAttribute("user", user);
        return "goods_list";
    }

6. 重新设置有效期

当从redis恢复user信息的时候,应当重设token过期时间

    public MiaoshaUser getByToken(HttpServletResponse response, String token) {
        if (StringUtils.isEmpty(token)) {
            return null;
        }
        MiaoshaUser miaoshaUser = redisService.get(MiaoshaUserKey.token, token, MiaoshaUser.class);
//        延长有效期,相当于再设置一遍
        if (miaoshaUser != null) {
            addCookie(response, token, miaoshaUser);
        }
        return miaoshaUser;
    }

最后的 MiaoshaUserService 变成了

import com.liuyao.miaosha.dao.MiaoshaUserDao;
import com.liuyao.miaosha.domain.MiaoshaUser;
import com.liuyao.miaosha.exception.GlobalException;
import com.liuyao.miaosha.redis.MiaoshaUserKey;
import com.liuyao.miaosha.redis.RedisService;
import com.liuyao.miaosha.result.CodeMsg;
import com.liuyao.miaosha.util.MD5Util;
import com.liuyao.miaosha.util.UUIDUtil;
import com.liuyao.miaosha.vo.LoginVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

@Service
public class MiaoshaUserService {
    public static final String COOKIE_NAME_TOKEN = "token";
    @Autowired
    MiaoshaUserDao miaoshaUserDao;
    @Autowired
    RedisService redisService;

    public MiaoshaUser getById(long id) {
        return miaoshaUserDao.getById(id);
    }

    public boolean login(HttpServletResponse response, LoginVo loginVo) {
        if (loginVo == null) {
            throw new GlobalException(CodeMsg.SERVER_ERROR);
        }
        String mobile = loginVo.getMobile();
        String fromPass = loginVo.getPassword();
//        判断手机号是否存在
        MiaoshaUser user = getById(Long.parseLong(mobile));
        if (user == null) {
            throw new GlobalException(CodeMsg.MOBILE_NO_EXIST);
        }
        //验证密码
        String dbPasss = user.getPassword();
        String saltDB = user.getSalt();
        String calcPass = MD5Util.fromPassToDBPass(fromPass, saltDB);
        if (!calcPass.equals(dbPasss)) {
            throw new GlobalException(CodeMsg.PASSWORD_ERROR);
        }
//        利用uuid生成token
        String token = UUIDUtil.uuid();
        addCookie(response, token, user);
        return true;
    }

    private void addCookie(HttpServletResponse response, String token, MiaoshaUser user) {
//        生成cookie
//        以token为key,用户信息为value,存到redis中
        redisService.set(MiaoshaUserKey.token, token, user);
//        并把token放到cookie中
        Cookie cookie = new Cookie(COOKIE_NAME_TOKEN, token);
//        给cookie这是过期时间,这里设置和在redis中的key一样长的时间
        cookie.setMaxAge(MiaoshaUserKey.token.expireSeconds());
        cookie.setPath("/");
        response.addCookie(cookie);
    }

    public MiaoshaUser getByToken(HttpServletResponse response, String token) {
        if (StringUtils.isEmpty(token)) {
            return null;
        }
        MiaoshaUser miaoshaUser = redisService.get(MiaoshaUserKey.token, token, MiaoshaUser.class);
//        延长有效期,相当于再设置一遍
        if (miaoshaUser != null) {
            addCookie(response, token, miaoshaUser);
        }
        return miaoshaUser;
    }
}

  • 3 min read

CONTRIBUTORS


  • 3 min read