美文网首页
2018-12-12 分部式session

2018-12-12 分部式session

作者: 培根好吃 | 来源:发表于2018-12-12 11:57 被阅读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

    相关文章

      网友评论

          本文标题:2018-12-12 分部式session

          本文链接:https://www.haomeiwen.com/subject/lipuhqtx.html