springboot之参数解析器(WebMvcConfigurerAdapter)

版权声明:本文为博主原创文章,转载请注明原文链接 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的数据了

猜你喜欢

转载自blog.csdn.net/qq_36922927/article/details/82057372