Java秒杀实战(七)分布式session

1.首先通过uuid生成唯一标识的token信息

String token = UUIDUtil.uuid();

2.然后把token信息连带着user用户信息放到缓存服务器中

redisService.set(MiaoshaUserKey.token, token, user);

3.再new出来一个cookie对象,往里面填充值,设置信息。

Cookie cookie = new Cookie(COOKI_NAME_TOKEN, token);
        cookie.setMaxAge(MiaoshaUserKey.token.expireSeconds());
        cookie.setPath("/");
       

 

4.这时候算是存进去了token信息,我们需要登录的时候获取token信息。

	public SeckillUser getByToke(String token) {
		if(StringUtils.isEmpty(token)){
			return null;
		}
		
		return redisService.get(SeckillUserKey.token, token, SeckillUser.class);
	}

5.当我们登录成功后,跳转其它页面时,token信息已经塞到了http请求,拿到token信息后,通过token信息取出自己的user信息后,显示到界面。


 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
 
import com.wings.seckill.domain.SeckillUser;
import com.wings.seckill.service.SeckillUserService;
 
@Controller
@RequestMapping("/goods")
public class GoodsController {
	
	private static Logger log = LoggerFactory.getLogger(GoodsController.class);
 
	@Autowired
	private SeckillUserService seckillUserService;
 
	@RequestMapping("/to_list")
	public String toList(Model model, 
			@CookieValue(name = SeckillUserService.COOKIE_TOKEN_NAME, required = false) String cookieToken,
			// @RequestParam 是为了兼容默写手机端会把cookie信息放入请求参数中
			@RequestParam(name = SeckillUserService.COOKIE_TOKEN_NAME, required = false) String paramToken) {
			
		if(StringUtils.isEmpty(cookieToken) && StringUtils.isEmpty(paramToken)){
			return "/login/to_login";
		}
		
		String token = StringUtils.isEmpty(paramToken) ? cookieToken : paramToken;
		SeckillUser seckillUser = seckillUserService.getByToke(token);
		model.addAttribute("user", seckillUser);
		return "goods_list";
	}
	
}

像User这种,几乎每个Controller方法都要使用的对象,如果每个Controller的方法都通过以上方式获取,代码将相当臃肿。这时,可以使用SpringMVC中WebMvcConfigurerAdapter的addArgumentResolvers,向需要user对象的方法进行入参注入。
 

package com.imooc.miaosha.config;


import com.imooc.miaosha.access.AccessInterceptor;
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.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import java.util.List;

/**
 * Created by 张伟光 on 2019/5/18.
 */
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

    @Autowired
    UserArgumentResolever userArgumentResolever;
    @Autowired
    AccessInterceptor accessInterceptor;
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(userArgumentResolever);
    }
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(accessInterceptor);
    }
}

下面是用spring自定参数解析器,

接口说明:
supportsParameter:用于判定是否需要处理该参数分解,返回true为需要,并会去调用下面的方法resolveArgument。
resolveArgument:真正用于处理参数分解的方法,返回的Object就是controller方法上的形参对象。

package com.wings.seckill.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.util.StringUtils;
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.wings.seckill.domain.SeckillUser;
import com.wings.seckill.service.SeckillUserService;
 
@Service
public class UserArgumentResolver implements HandlerMethodArgumentResolver{
	
	@Autowired
	private SeckillUserService seckillUserService;
 
	@Override
	public boolean supportsParameter(MethodParameter parameter) {
		Class<?> clazz = parameter.getParameterType();
		return clazz == SeckillUser.class;
	}
 
	@Override
	public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
		
		HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
		HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
		
		String paramToken = request.getParameter(SeckillUserService.COOKIE_TOKEN_NAME);
		String cookieToken = getCookieValue(request, SeckillUserService.COOKIE_TOKEN_NAME);
		
		if(StringUtils.isEmpty(cookieToken) && StringUtils.isEmpty(paramToken)){
			return null;
		}
		
		String token = StringUtils.isEmpty(paramToken) ? cookieToken : paramToken;
		return seckillUserService.getByToke(token, response);
	}
 
	private String getCookieValue(HttpServletRequest request, String cookieName) {
		Cookie[] cookies = request.getCookies();
		if(cookies != null){
			for(Cookie cookie : cookies){
				if(cookie.getName().equals(cookieName)){
					return cookie.getValue();
				}
			}
		}
		return null;
	}
 
}

这样控制器就变得干净了,可以直接获取了user信息。

【总结】

          框架封装做好了,就会给开发人员留有更多的时间来做业务。

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值