总结:服务间的调用,其实就是令牌的传递.
一、认证服务器(shop-user-oauth)通过Feign调用User服务(shop-service-user)
1、shop-user-oauth中创建 RequestInterceptor拦截器,当调用Feign前,生成令牌放到Head中。
1.1 请求拦截器
1.2 生成管理员令牌
1.3 调用Feign
2、shop-service-user服务,ResourceServerConfig中关闭资源放行
3、测试
http://localhost:9001/user/login?username=heima&password=111111
二、shop-service-user服务 通过 Feign 调用 shop-service-goods服务
1、shop-service-goods开启资源授权
1.1 public.key 公钥放到 resources 文件夹
1.2 添加解析令牌依赖
<!--解析令牌-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
1.3 ResourceServerConfig.java 配置文件中开启资源校验服务,及放行地址
2、shop-service-goods-api 创建BrandFeign 接口
@FeignClient(value = "goods")//要访问的服务名称
@RequestMapping(value = "/brand")
public interface BrandFeign {
@GetMapping
public Result<List<Brand>> findAll();
}
3、shop-service-user 调用shop-service-goods-api的feign
在调用feign前,将先进行拦截,将头文件,放到新的头文件上。
3.1 导入shop-service-goods-api依赖
<!--依赖 shop-service-goods-api 调用feign-->
<dependency>
<groupId>org.example</groupId>
<artifactId>shop-service-goods-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
3.2 启动类开启 feign
3.3 注入 BrandFeign
@Autowired private BrandFeign brandFeign;
3.4 调用
3.5 Feign请求前进行拦截,将head头放到新head头上
@Configuration
public class FeignInterceptorA implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
try {
/* 用户当前请求的时对应线程的数据。
如果开启了熔断,默认时线程隔离,会开启新的线程,需要将熔断策略换成信号量隔离,此时不会开启新的线程。*/
//使用RequestContextHolder工具获取request相关变量
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes != null) {
//取出request
HttpServletRequest request = attributes.getRequest();
//获取所有头文件信息的key
Enumeration<String> headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
//头文件的key
String name = headerNames.nextElement();
//头文件的value
String values = request.getHeader(name);
//将头信息添加到新头文件中
requestTemplate.header(name, values);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
用户当前请求的是对应线程的数据。
如果开启了熔断,默认时线程隔离,会开启新的线程(将获取到不请求数据),需要将熔断策略换成信号量隔离,此时不会开启新的线程。
需要:
#hystrix 配置
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 10000 #超时时间
strategy: SEMAPHORE #信号量隔离
3.6 、测试
首先获取令牌: http://localhost:9001/user/login?username=heima&password=111111
通过网关访问: http://localhost:8001/api/user
4、拦截器封装
4.1 shop-common中封装拦截器
@Component
public class FeignInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
//传递令牌
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes != null){
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
if (request != null){
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()){
String headerName = headerNames.nextElement();
if ("authorization".equals(headerName)){
String headerValue = request.getHeader(headerName); // Bearer jwt
//传递令牌
requestTemplate.header(headerName,headerValue);
}
}
}
}
}
}
4.2 需要使用的时候,在启动类上注入
//将feign调用拦截器注入到容器中
@Bean
public FeignInterceptor feignInterceptor(){
return new FeignInterceptor();
}