微服务获取用户信息和OpenFeign传递用户

server/2024/10/11 0:48:23/

问题一:

网关已经完成登录校验并获取登录用户身份信息。但是当网关将请求转发到微服务时,微服务又该如何获取用户身份呢?

由于网关发送请求到微服务依然采用的是Http请求,因此我们可以将用户信息以请求头的方式传递到下游微服务。然后微服务可以从请求头中获取登录用户信息。考虑到微服务内部可能很多地方都需要用到登录用户信息,因此我们可以利用SpringMVC的拦截器来实现登录用户信息获取,并存入ThreadLocal,方便后续使用。

据图流程图如下:

 

因此,接下来我们要做的事情有:

改造网关过滤器,在获取用户信息后保存到请求头,转发到下游微服务

java">String userInfo = userId.toString();
exchange.mutate().request(builder -> builder.header("user-info",userInfo)).build();

编写微服务拦截器,拦截请求获取用户信息,保存到ThreadLocal后放行

ThreadLocal相关的类:

java">package com.hmall.common.utils;public class UserContext {private static final ThreadLocal<Long> tl = new ThreadLocal<>();/*** 保存当前登录用户信息到ThreadLocal* @param userId 用户id*/public static void setUser(Long userId) {tl.set(userId);}/*** 获取当前登录用户信息* @return 用户id*/public static Long getUser() {return tl.get();}/*** 移除当前登录用户信息*/public static void removeUser(){tl.remove();}
}

 拦截器:

java">package com.hmall.common.interceptor;import cn.hutool.core.util.StrUtil;
import com.hmall.common.utils.UserContext;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class UserInfoInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler) throws Exception {String userId = request.getHeader("User-info");if(StrUtil.isNotEmpty(userId)){UserContext.setUser(Long.parseLong(userId));}return true;}@Overridepublic void afterCompletion(final HttpServletRequest request, final HttpServletResponse response, final Object handler, final Exception ex) throws Exception {UserContext.removeUser();}
}

配置类:

java">package com.hmall.common.config;import com.hmall.common.interceptor.UserInfoInterceptor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
@ConditionalOnClass(DispatcherServlet.class) //排除网关服务
public class MvcConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new UserInfoInterceptor()).addPathPatterns("/**");}
}

基于SpringBoot的自动装配原理,我们要将其添加到resources目录下的META-INF/spring.factories文件中:

 内容如下:

java">org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.hmall.common.config.MyBatisConfig,\com.hmall.common.config.MvcConfig

问题二:

前端发起的请求都会经过网关再到微服务,由于我们之前编写的过滤器和拦截器功能,微服务可以轻松获取登录用户信息。

但有些业务是比较复杂的,请求到达微服务后还需要调用其它多个微服务。比如下单业务,流程如下:

 下单的过程中,需要调用商品服务扣减库存,调用购物车服务清理用户购物车。而清理购物车时必须知道当前登录的用户身份。但是,订单服务调用购物车时并没有传递用户信息,购物车服务无法知道当前用户是谁!

这里要借助Feign中提供的一个拦截器接口:feign.RequestInterceptor

java">@Bean
public RequestInterceptor userInfoRequestInterceptor(){return new RequestInterceptor() {@Overridepublic void apply(RequestTemplate template) {// 获取登录用户Long userId = UserContext.getUser();if(userId == null) {// 如果为空则直接跳过return;}// 如果不为空则放入请求头中,传递给下游微服务template.header("user-info", userId.toString());}};
}

此外还需要在调用服务的启动类上加上:

java">@EnableFeignClients(basePackages = "com.hmall.api.client",defaultConfiguration = DefaultFeignConfig.class)


http://www.ppmy.cn/server/129879.html

相关文章

Oracle EBS中 税务报告 模块的财务流程概览

Oracle E-Business Suite (EBS) 中的税务报告模块是企业用来管理税务相关流程的关键组件&#xff0c;与PO、AP、AR模块的关系非常紧密&#xff0c;它支持从税款计算、申报到支付的全过程。这个模块帮助企业确保其税务操作符合当地法律法规&#xff0c;并能够高效地处理复杂的税…

Unity3D Shader的阴影部分法线效果详解

在Unity3D开发中&#xff0c;阴影处理是提升场景真实感和视觉质量的重要一环。法线贴图&#xff08;Normal Mapping&#xff09;作为一种高效的纹理映射技术&#xff0c;在增强模型表面细节和凹凸感方面扮演着重要角色。本文将详细解析UnityShader中阴影部分的法线效果&#xf…

Ubuntu 22.04.4 LTS更换下载源

方法1&#xff1a;使用图形界面更换下载源 1. 打开软件和更新应用 2. 在Ubuntu 软件标签中&#xff0c;点击“下载自”旁边的下拉菜单&#xff0c;选择“其他” 3. 点击“选择最佳服务器”来自动选择最快的服务器 4. 选择服务器 5. 确定并关闭窗口&#xff0c;系统会提示您重新…

【redis-06】redis的stream流实现消息中间件

redis系列整体栏目 内容链接地址【一】redis基本数据类型和使用场景https://zhenghuisheng.blog.csdn.net/article/details/142406325【二】redis的持久化机制和原理https://zhenghuisheng.blog.csdn.net/article/details/142441756【三】redis缓存穿透、缓存击穿、缓存雪崩htt…

【d61】【Java】【力扣】【递归】3304. 找出第 K 个字符 I

思路 递归考虑&#xff1a;就像正常一样想出来思路&#xff0c;然后递归调用的地方&#xff0c;当作一个已经确定的量&#xff08;可直接说一个值&#xff0c;这样就不会一直向下层想&#xff09; 注意绝对不要在递归调用的地方一直往下层想&#xff0c;绝对不要&#xff0c;…

高级java每日一道面试题-2024年10月1日-服务器篇[Redis篇]-Redis数据结构压缩列表和跳跃表的区别?

如果有遗漏,评论区告诉我进行补充 面试官: Redis数据结构压缩列表和跳跃表的区别&#xff1f; 我回答: 关于Redis数据结构的理解是一个重要的考察点&#xff0c;特别是压缩列表&#xff08;ziplist&#xff09;和跳跃表&#xff08;skiplist&#xff09;这两种数据结构&…

【CF2021E】Digital Village(All Version)

题目 给你一张 n n n 个点 m m m 条边的无向图&#xff0c;有 p p p 个关键点。你需要选择 k k k 个点染黑&#xff0c;使得这 p p p 个关键点到这 k k k 个黑点的代价和最小。定义代价为两点之间边权最大的边的最小值。 你需要求出 k 1,2,…,n 的所有答案 E1 n,m,p&l…

速盾:休闲类游戏如何选择高防cdn?

休闲类游戏的流行度日益增长&#xff0c;越来越多的玩家在业余时间里选择放松自己&#xff0c;享受游戏带来的乐趣。然而&#xff0c;在休闲类游戏中&#xff0c;网络延迟和游戏载入速度的问题常常会影响到玩家的游戏体验。为了解决这些问题&#xff0c;选择一个高防CDN&#x…