web应用中常会用到用户信息,一般都是从会话中获取,不过这样不优雅,相似的代码到处都是,希望可以通过spring的特性,在我需要的时候可以自动装配。
1.登录时产生token,同时把token与反序列化的用户信息放入redis中;
2.访问时携带token,网关层进行拦截,同时从redis通过token将用户信息放入header中;
3.业务层,通过拦截器拦截请求,从header中获取反序列化的用户信息,放入Request中;
4.通过参数分解器,从Request中获取参数注入
HandlerMethodArgumentResolver: https://www.jianshu.com/p/ac9...
BeanPostProcessor: https://blog.csdn.net/zhyh198...
BeanPostProcessor和BeanFactoryProcessor浅析: https://www.jianshu.com/p/fb3...
public class UserResolveFilter extends ZuulFilter { /** * 请求拦截类型 * * @return */ @Override public String filterType() { return FilterConstants.PRE_TYPE; } @Override public int filterOrder() { return 20; } /** * 哪些请求要被拦截 * * @return */ @Override public boolean shouldFilter() { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); // 端口号之后的请求地址 return request.getRequestURI().startsWith("/core-server"); } @Override public Object run() throws ZuulException { RequestContext ctx = RequestContext.getCurrentContext(); ctx.getZuulRequestHeaders().remove("user"); HttpServletRequest request = ctx.getRequest(); String token = request.getHeader("token"); if (!StringUtils.isBlank(token)) { // 这里获取token后,可以完成自己的映射操作 ctx.addZuulRequestHeader("user", "{/"id/":1,/"name/":/"jiaotd/",/"age/":18}"); } return null; } }
@Configuration @Slf4j public class Config { @Bean public UserResolveFilter userCenterResolveUserFilter() { log.info("init UserResolveFilter"); return new UserResolveFilter(); } }
@Configuration @WebFilter(filterName = "userInfoResolverFilter", urlPatterns = "/*") public class UserInfoResolverFilter implements Filter { //@WebFilter 用于将一个类声明为过滤器,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为过滤器 @Override public void init(FilterConfig filterConfig) throws ServletException { log.info("UserInfoResolverFilter init()....."); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { String json = ((HttpServletRequest) servletRequest).getHeader("user"); log.info("请求头中的User为:{}", json); User user = JSON.parseObject(URLDecoder.decode(json, "utf-8"), User.class); servletRequest.setAttribute("user", user); filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { log.info("UserInfoResolverFilter destroy()....."); } }
public class UserArgumentResolver implements HandlerMethodArgumentResolver { /** * 参数类型是User的执行 #resolveArgument 方法 * * @param methodParameter * @return */ @Override public boolean supportsParameter(MethodParameter methodParameter) { return methodParameter.getParameterType() == User.class; } /** * 赋值 * * @param methodParameter * @param modelAndViewContainer * @param nativeWebRequest * @param webDataBinderFactory * @return * @throws Exception */ @Override public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception { User user = (User) nativeWebRequest.getAttribute("user", RequestAttributes.SCOPE_REQUEST); return user; } }
@Component public class ArgumentResolverPostProcessor implements BeanPostProcessor { /** * spring 初始化 Bean 操作 * * @param bean * @param beanName * @return * @throws BeansException */ @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof RequestMappingHandlerAdapter) { //requestMappingHandlerAdapter进行修改 RequestMappingHandlerAdapter adapter = (RequestMappingHandlerAdapter) bean; List<HandlerMethodArgumentResolver> argumentResolvers = adapter.getArgumentResolvers(); //添加自定义参数处理器 argumentResolvers = addArgumentResolvers(argumentResolvers); adapter.setArgumentResolvers(argumentResolvers); } return null; } private List<HandlerMethodArgumentResolver> addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) { List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>(); //将自定的添加到最前面 resolvers.add(new UserArgumentResolver()); //将原本的添加后面 resolvers.addAll(argumentResolvers); return resolvers; }
@RestController @RequestMapping("/core") public class CoreController { @GetMapping("/user") public User getUser(User user) { return user; } }