Fork me on GitHub

java初探(1)之登录补充

在登录之后,可能服务器是分布式的,因此不能通过一个本地的session来管理登录信息,导致登录的信息不能传递,即在这台服务器上可以得到用户登录信息,但在那台就得不到。因此,需要设置分布式的session,方法是,使用一个token,存在客户端的本地cookie,当接收请求时,从客户端将cookie值传过去,或者将token值存到缓存中,从缓存中取值。

 

  • 起步

  在登录的时候,当登录成功后,便随机生成一个token值,将该值存到redis缓存中,并将该值存到cookie中,返回到客户端。

private void addCookie(HttpServletResponse response,String token, MiaoshaUser user){
        //将token存入缓存中
        redisService.set(MiaoshaUserKey.token,token,user);
        //将token存入COOKIE中
        Cookie cookie=new Cookie(COOKI_NAME_TOKEN,token);
        cookie.setMaxAge(MiaoshaUserKey.token.expireSeconds());
        cookie.setPath("/");
        response.addCookie(cookie);
    }

该方法在MiaoshaUserService中的login方法中调用。

 

  • 跳转

  登录以后,要跳转到商品页面,但需要把商品页面传过来,一种是一个机器的,可以直接传过去,但如果是分布式的,只能通过token来获取。

@Controller
@RequestMapping("/goods")
public class GoodsController {

    @RequestMapping("/to_list")
    public String list(Model model, MiaoshaUser user){
        model.addAttribute("user",user);
        return "goods_list";
    }
}

这种方法是无法获取user的值的。

 

  • 取值    

@Controller
@RequestMapping("/goods")
public class GoodsController {

    @Autowired
    private MiaoshaUserService miaoshaUserService;

    @RequestMapping("/to_list")
    public String list(HttpServletResponse response,Model model,
                       @CookieValue(value = MiaoshaUserService.COOKI_NAME_TOKEN) String token){

        MiaoshaUser user = miaoshaUserService.getByToken(response, token);

        model.addAttribute("user",user);
        return "goods_list";
    }
}

获取到cookie的值就可以获取user对象了。

 

但上述方法不够降低耦合,因此,采用配置参数的方法。

  • 定义一个web的配置类

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter{

    @Autowired
    UserArgumentResolver userArgumentResolver;

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(userArgumentResolver);
    }
}

 

  • 配置类的handle方法

public class UserArgumentResolver implements HandlerMethodArgumentResolver {

    @Autowired
    MiaoshaUserService userService;

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

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
        HttpServletResponse response = nativeWebRequest.getNativeResponse(HttpServletResponse.class);

        String paramToken = request.getParameter(MiaoshaUserService.COOKI_NAME_TOKEN);
        String cookieToken = getCookieValue(request, MiaoshaUserService.COOKI_NAME_TOKEN);
        if(StringUtils.isEmpty(cookieToken) && StringUtils.isEmpty(paramToken)) {
            return null;
        }
        String token = StringUtils.isEmpty(paramToken)?cookieToken:paramToken;
        return userService.getByToken(response, token);
    }

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

}

 

对该类进行说明。

WebConfig类是个web的配置类。我们之所以能实现在controller拿到参数的转换值,就是一堆类在内部发挥看不见的作用,而通过WebConfig可以实现,自己配置那些参数的转化,它继承了一个WebMvcConfigurerAdapter类,该类是个抽象类,定义了很多可以配置的方法,而我们对参数进行配置,则只需要添加一个HandlerMethodArgumentResolver接口的实现类。

 

而第二个类就是该接口的实现类,可以实现具体拿到参数后进行的逻辑操作,比如,在该类中,我们拿到了request、reponse对象,然后得到token在reques的值和cookie中的值。然后,将token对应的user对象取出来。因此,我们在controller类中,只需要配置user的参数就可以取到user的值。

 

posted @ 2020-02-20 21:17  lovejune  阅读(239)  评论(0编辑  收藏  举报