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; }