版权声明:本文为博主原创文章,转载请注明原文链接 https://blog.csdn.net/qq_36922927/article/details/82057372
使用redis实现分布式session
将默认的session存放在tomcat的功能
通过redis保存token-user(key-val)的方式实现分布式session
cookie中保存token,请求前都需要带上cookie(token)去请求接口,后端通过cookie中的token去查询redis来判断当前用户是否已经登录
如果在每一个controller方法中做如下图代码的逻辑判断,无疑是浪费时间,低级的代码复制粘贴
简化之前:由于很多地方需要判断cokkie中的token,来判断用户是否在线,是否已经登录
改进前的controller方法:
@RequestMapping("/to_list")
public String toList(Model model,
@CookieValue(value = ConstUtil.COOKIE_NAME_TOKEN,required = false)String cookieToken,
@RequestParam(value = ConstUtil.COOKIE_NAME_TOKEN,required = false)String paramToken,
HttpServletResponse response){
//假定优先级:cookie》param
if(StringUtils.isEmpty(cookieToken)&&StringUtils.isEmpty(paramToken)){
return "to_login";
}
String token=StringUtils.isEmpty(paramToken)?cookieToken:paramToken;
MiaoshaUser user=userService.getUserByToken(token,response);
model.addAttribute("user",new MiaoshaUser());
return "goods_list";
}
改进:WebMvcConfigurerAdapter
使用spring的参数解析器,controller方法添加一个参数,MiaoshUser user;
参数解析器中处理查询redis的逻辑,决定是否给user对象填充数据,如果没有查询到,则设置user=null;否则填充其数据
代码:
WebConfig.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import java.util.List;
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter{
@Autowired
UserArgumentResolver userArgumentResolver;
@Override
// 参数解析器,被框架回调
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(userArgumentResolver);
}
}
UserArgumentResolver.java
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 javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Service
public class UserArgumentResolver implements HandlerMethodArgumentResolver {
@Autowired
MiaoShaUserService userService;
//判断参数类型是否是支持的,支持则范返回true
@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 {
//参数处理逻辑
//1,获得response
//2,获取token
//3,查询user信息,将user信息注入到MiaoshaUser类型参数中
HttpServletResponse response=nativeWebRequest.getNativeResponse(HttpServletResponse.class);
HttpServletRequest request=nativeWebRequest.getNativeRequest(HttpServletRequest.class);
//分别获取请求参数,cookie中的token
String paramToken=request.getParameter(ConstUtil.COOKIE_NAME_TOKEN);
String cookieToken=getCookieValue(request,ConstUtil.COOKIE_NAME_TOKEN);
if(StringUtils.isEmpty(paramToken)&&StringUtils.isEmpty(cookieToken)){
return null;
}
String token=StringUtils.isEmpty(paramToken)?cookieToken:paramToken;
MiaoshaUser user=userService.getUserByToken(token,response);
return user;
}
//遍历cookie获得需要的cookie(保存用户token的cookie的value,也就是token)
private String getCookieValue(HttpServletRequest request, String cookieName) {
Cookie[] cookies=request.getCookies();
for(Cookie cookie:cookies){
if(cookie.getName().equals(cookieName)){
return cookie.getValue();
}
}
return null;
}
}
改进后的ontroller方法:
@RequestMapping("/to_list")
public String toList(Model model,MiaoshaUser user){
// //假定优先级:cookie》param
// if(StringUtils.isEmpty(cookieToken)&&StringUtils.isEmpty(paramToken)){
// return "login";
// }
// String token=StringUtils.isEmpty(paramToken)?cookieToken:paramToken;
// MiaoshaUser user=userService.getUserByToken(token,response);
if(null==user){
return "to_login";
}
model.addAttribute("user",user);
return "goods_list";
}
实现效果:
debug:UserArgumentResolver.java
controller:效果完美!
总结:
上诉代码读者不必一一原版实现,只需要知道实现方式,就能写出适合自己业务需求的参数解析器,来解决实际问题
第一步:
前端ajax传递参数到后controller,需要先经过HandlerMethodArgumentResolver ,在这个参数解析器中决定如何将参数的值注入到参数列表中
第二步:
之后才进入到controller中,
此案例流程说明:
所以这里虽然需要注入user对象,但是前端只是传来cookie中的token,
添加参数解析器之后,就只需要在参数解析器中拿到token,
再用token去拿到user的值,通过controller方法参数的类型,找到应该注入user相关数据的参数类型,注入,那么进入到controller方法之后,就能有user的数据了