zoukankan      html  css  js  c++  java
  • 10月12 HandlerMethodArgumentResolver的使用 | 简单生成token

    一、基本实现

    1.1 实现接口

    import org.apache.commons.lang3.StringUtils;
    import org.springframework.core.MethodParameter;
    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.longge.utils.Constant;
    import com.longge.utils.RedisCacheUtils;
    
    /**
     * 获取用户的session dto
     */
    public class LoginUserInfoMethodArgumentResolver implements HandlerMethodArgumentResolver {
    
        @Override
        public Object resolveArgument(MethodParameter arg0, ModelAndViewContainer arg1, NativeWebRequest arg2,
                WebDataBinderFactory arg3) throws Exception {
            String token = arg2.getHeader(Constant.TOKEN_KEY);
            if(StringUtils.isNotBlank(token)) {
                return RedisCacheUtils.getUserInfo(token);
            }
            return null;
        }
    
        @Override
        public boolean supportsParameter(MethodParameter arg0) {
            return arg0.getParameterType().equals(UserInfo.class);
        }
    
    }

    1.2 注册

    @SpringBootApplication
    public class MyBootApplication extends WebMvcConfigurerAdapter{
        public static void main(String[] args) {
            SpringApplication.run(MyBootApplication.class, args);
        }
        
        @Override
        public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
            super.addArgumentResolvers(argumentResolvers);
            argumentResolvers.add(new LoginUserInfoMethodArgumentResolver());
        }
    }

    这里是启动类继承WebMvcConfigurerAdapter

    另外写一个@Configuration注解的来继承WebMvcConfigurerAdapter(推荐)

    1.3 使用

    @ApiOperation("新增")
    @PutMapping("add")
    public ResponseResult<SupplierDto> add(UserInfo userInfo, @Valid @RequestBody SupplierDto supplierDto) {
        // 这里的UserInfo不需要加任何注解,因为LoginUserInfoMethodArgumentResolver是对class的类型来解析的
    }

    二、和拦截器使用获取用户信息

    2.1 

    /**
     * 登录用户信息
    
     */
    @Target(ElementType.PARAMETER)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface LoginUser {
    
    }

    2.2 拦截器

    @Component
    public class AuthorizationInterceptor extends HandlerInterceptorAdapter {
        @Autowired
        private TokenService tokenService;
    
        public static final String LOGIN_USER_KEY = "LOGIN_USER_KEY";
    
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
            //从header中获取token
            String token = request.getHeader(LOGIN_TOKEN_KEY);
            //如果header中不存在token,则从参数中获取token
            if (StringUtils.isBlank(token)) {
                token = request.getParameter(LOGIN_TOKEN_KEY);
            }//设置userId到request里,后续根据userId,获取用户信息
            request.setAttribute(LOGIN_USER_KEY, tokenEntity.getUserId());
    
            return true;
        }
    }

    把用户id 设置到attribute里面

    LoginUserHandlerMethodArgumentResolver

    import com.platform.annotation.LoginUser;
    import com.platform.entity.UserVo;
    import com.platform.interceptor.AuthorizationInterceptor;
    import com.platform.service.ApiUserService;
    import org.springframework.core.MethodParameter;
    import org.springframework.web.bind.support.WebDataBinderFactory;
    import org.springframework.web.context.request.NativeWebRequest;
    import org.springframework.web.context.request.RequestAttributes;
    import org.springframework.web.method.support.HandlerMethodArgumentResolver;
    import org.springframework.web.method.support.ModelAndViewContainer;
    
    /**
     * 有@LoginUser注解的方法参数,注入当前登录用户
     */
    public class LoginUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
        private ApiUserService userService;
    
        public void setUserService(ApiUserService userService) {
            this.userService = userService;
        }
    
        @Override
        public boolean supportsParameter(MethodParameter parameter) {
            return parameter.getParameterType().isAssignableFrom(UserVo.class) && parameter.hasParameterAnnotation(LoginUser.class);
        }
    
        @Override
        public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer container,
                                      NativeWebRequest request, WebDataBinderFactory factory) throws Exception {
            //获取用户ID
            Object object = request.getAttribute(AuthorizationInterceptor.LOGIN_USER_KEY, RequestAttributes.SCOPE_REQUEST);
            if (object == null) {
                return null;
            }
    
            //获取用户信息
            UserVo user = userService.queryObject((Long) object);
    
            return user;
        }
    }

    在supportsParameter方法中判断请求参数是否被HandlerMethodArgumentResolver所支持

    这里有两个条件1个是 LoginUser 注解一个是 UserVo

    然后才会执行 resolveArgument 方法

    从attribute里得到userid 然后得到用户信息

    2.3 使用

    @ApiOperation(value = "添加商品到购物车")
        @PostMapping("add")
        public Object add(@LoginUser UserVo loginUser) {
    }

    参考

    https://blog.csdn.net/a18716374124/article/details/79208990

    https://www.cnblogs.com/yangzhilong/p/7605889.html

    二、生成token

    token三要素

    userid 、过期时间 、token字符串

     //12小时后过期
        private final static int EXPIRE = 3600 * 12;
    
    
        public Map<String, Object> createToken(long userId) {
            //生成一个token
            String token = CharUtil.getRandomString(32);
            //当前时间
            Date now = new Date();
    
            //过期时间
            Date expireTime = new Date(now.getTime() + EXPIRE * 1000);
    
            //判断是否生成过token
            TokenEntity tokenEntity = queryByUserId(userId);
            if (tokenEntity == null) {
                tokenEntity = new TokenEntity();
                tokenEntity.setUserId(userId);
                tokenEntity.setToken(token);
                tokenEntity.setUpdateTime(now);
                tokenEntity.setExpireTime(expireTime);
    
                //保存token
                save(tokenEntity);
            } else {
                tokenEntity.setToken(token);
                tokenEntity.setUpdateTime(now);
                tokenEntity.setExpireTime(expireTime);
    
                //更新token
                update(tokenEntity);
            }
    
            Map<String, Object> map = new HashMap<>();
            map.put("token", token);
            map.put("expire", EXPIRE);
    
            return map;
        }
  • 相关阅读:
    如何增加按钮的点击间隔时间
    如何增加button的点击范围
    定时器Timer的使用
    NSCache
    GCD和NSOperation的区别
    NSOperation实现线程间通信
    NSOperation添加操作依赖和监听
    自定义NSOperation
    NSOperation的多线程
    单例的实现(完整版代码)
  • 原文地址:https://www.cnblogs.com/lyon91/p/9778486.html
Copyright © 2011-2022 走看看