2018-12-12 分部式session

2018-12-12  本文已影响0人  培根好吃

1.分布式session上

1.1 service层用户登录之后生成一个sessionId token

package com.ryan.miaosha.util;

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

1.2 redis中写入MiaoshaUserKey

package com.ryan.miaosha.redis;

public class MiaoshaUserKey extends BasePrefix{
    
    
    private static final int TOKEN_EXPIRE=3600*24*2;
    private MiaoshaUserKey(int expiredSeconds,String prefix) {
        super(expiredSeconds,prefix);
    }
    public static MiaoshaUserKey getByToken=new MiaoshaUserKey(TOKEN_EXPIRE,"token");
}

1.3 service层 将它存储在cookie上,传给客户端

        客户端每次写数据都是在cookie中写入
package com.ryan.miaosha.service;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ryan.miaosha.dao.MiaoshaUser;
import com.ryan.miaosha.dao.MiaoshaUserDao;
import com.ryan.miaosha.domain.CodeMsg;
import com.ryan.miaosha.exception.GlobalException;
import com.ryan.miaosha.redis.MiaoshaUserKey;
import com.ryan.miaosha.redis.RedisService;
import com.ryan.miaosha.util.MD5Util;
import com.ryan.miaosha.util.UUIDUtil;
import com.ryan.miaosha.vo.LoginVo;

@Service
public class MiaoshaService {

    public static final String COOKIE_NAME_TOKEN="token";
    @Autowired
    MiaoshaUserDao miaoshaUserDao;
    @Autowired
    RedisService redisService;
    
    public MiaoshaUser getById(long id) {
        return miaoshaUserDao.selectById(id);
    }
    public boolean login(HttpServletResponse response, LoginVo vo) {
        MiaoshaUser user = getById(Long.parseLong(vo.getMobile()));
        if(user==null) {
            throw new GlobalException(CodeMsg.USER_NOT_EXIST);          
        }
        String saltDB = user.getSalt();
        String passwordDB = user.getPassword();
        String webPass = vo.getPassword();
        String passValidated=MD5Util.WebPassToDB(webPass, saltDB);
        if(!passValidated.equals(passwordDB)) {
            throw new GlobalException(CodeMsg.PASSWORD_ERROR);          
        }
   //利用工具UUIDUtil生成uuid
        String token=UUIDUtil.uuid();
//将token以及对应的用户存入session  redis
        redisService.set(MiaoshaUserKey.getByToken, token, user);
//将token存入cookie,传回客户端
        Cookie cookie=new Cookie(COOKIE_NAME_TOKEN, token);
//设置过期时间 ,与session相同  设置路径 根目录   添加http响应 添加cookie
        cookie.setMaxAge(MiaoshaUserKey.getByToken.expiredSeconds());
        cookie.setPath("/");
        response.addCookie(cookie);
        return true;        
    }
}

1.4 从controller层中把从客户端传来的cookie数据读出

@RequestMapping("/to_list")
    String toLogin(Model model,
            @CookieValue(value=MiaoshaService.COOKIE_NAME_TOKEN,required=false) String cookieToken,
            @RequestParam(value=MiaoshaService.COOKIE_NAME_TOKEN,required=false) String paramToken) {
        if(StringUtils.isEmpty(paramToken)&&StringUtils.isEmpty(cookieToken))
            return "login";
        String token=StringUtils.isEmpty(paramToken)?cookieToken:paramToken;
        MiaoshaUser user=miaoshaUserService.getByToken(token);
        model.addAttribute("user", user);
        return "goods_list";
    }

1.5 service层中再增加一个方法:根据token获取到user ,在goods_list html中展示出来

public  MiaoshaUser getByToken(String token) {
        if(StringUtils.isEmpty(token)) {
            return null;
        }       
        return redisService.get(MiaoshaUserKey.getByToken, token, MiaoshaUser.class);
    }

1.6 goods_list html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>登录</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'hello:'+${user.nickname}">
</body>
</html>

1.7 为了满足每次访问页面时,以最后一次登录时的cookie过期时间为准,我们需要在获取redis中的用户user之后再写入一次cookie


1.    MiaoshaUser user=miaoshaUserService.getByToken(response,token);
2.   
    private void addCookie(HttpServletResponse response, String token, MiaoshaUser user) {
        redisService.set(MiaoshaUserKey.token, token, user);
        Cookie cookie = new Cookie(COOKI_NAME_TOKEN, token);
        cookie.setMaxAge(MiaoshaUserKey.token.expireSeconds());
        cookie.setPath("/");
        response.addCookie(cookie);
    }


public  MiaoshaUser getByToken(HttpServletResponse response,String token) {
        if(StringUtils.isEmpty(token)) {
            return null;
        }   
//  判断user是否为空,如果不为空,则再将token  及用户存入一次cookie;达到以最后一次登录为基准
        MiaoshaUser user=redisService.get(MiaoshaUserKey.getByToken, token, MiaoshaUser.class);
        if(user!=null) {
            addCookie(response,token,user);
        }
        return user;
    }

1.8 创建一个WebConfig 类配置handler里面的参数

package com.ryan.miaosha.config;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer{
    /*这个参数解析器 可以根据handler方法上的参数类型 设置参数,
     * @RequestMapping("/to_list") 
       String toLogin(HttpServletResponse response,Model model) 
                             里面的response  model 都是由它这个方法来赋值的
*/  
    @Autowired
    UserArgumentResolver userArgumentResolver;
    public  void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
      resolvers.add(userArgumentResolver);
    }
}




1.3 创建一个HandlerMethodArgumentResolver接口的实现类UserArgumentResolver,用来给WebConfig传参数

package com.ryan.miaosha.config;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import com.alibaba.druid.util.StringUtils;
import com.ryan.miaosha.dao.MiaoshaUser;
import com.ryan.miaosha.redis.RedisService;
import com.ryan.miaosha.service.MiaoshaService;

@Service
public class UserArgumentResolver implements HandlerMethodArgumentResolver{

    @Autowired
    MiaoshaService miaoshaUserService;
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        Class<?> clazz = parameter.getParameterType();      
        return clazz==MiaoshaUser.class;
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        HttpServletRequest nativeRequest = webRequest.getNativeRequest(HttpServletRequest.class);
        HttpServletResponse nativeResponse = webRequest.getNativeResponse(HttpServletResponse.class);
        
        String paramToken = nativeRequest.getParameter(MiaoshaService.COOKIE_NAME_TOKEN);
        String cookieToken=getCookieTk(nativeRequest,MiaoshaService.COOKIE_NAME_TOKEN);
        if(StringUtils.isEmpty(paramToken)&&StringUtils.isEmpty(cookieToken))
            return null;
        String token=StringUtils.isEmpty(paramToken)?cookieToken:paramToken;
        return   miaoshaUserService.getByToken(nativeResponse, token);
    }

    private String getCookieTk(HttpServletRequest nativeRequest,String cookieNameToken) {
        Cookie[] cookies = nativeRequest.getCookies();
        for(Cookie cookie:cookies) {
            if(cookie.getName().equals(cookieNameToken))
            return cookie.getValue();
        }
        return null;
    }

}

1.3

上一篇下一篇

猜你喜欢

热点阅读