如何优雅使用feign调用微服务及转发token
完整项目地址: micro-service-plus
系列文章入口:
前言
有时我们微服务需要相互调用,这时就需要feign了,但是当网关转发到微服务时token还在请求头中,假设请求gateway-A-B,到B服务时token没了,这时就需要重新写feign配置了,下面我们就来详解如何更优雅的feign调用及转发请求头参数
我们先看看配置和使用
在ty-example引入feign配置
micro-service-plus\ty-example\src\main\java\top\kuanghua\tyexample\config\BaseConfig.java
@Configuration
//将integration-front服务的feign扫描引入
@EnableFeignClients(basePackages = {"top.kuanghua.feign.integrationfront"})
public class BaseConfig {
}
如何使用
@Service
public class SeataTestService {
@Resource
private UserFeign userFeign;
@GlobalTransactional(rollbackFor = Exception.class)
public void testSeataRollback(){
userFeign.insertUser("jzfai");
int i=10/0;
}
}
注:本架构所有的微服务的feign统一放到ty-common/feign下,方便统一管理和调用
解决feign id重复问题
spring:
main:
allow-bean-definition-overriding: true
请求头转发token
默认feign转发到其他服务后,请求头的东西会丢失,例如我们在网关设置的token信息
feign核心头转发文件
ty-common\src\main\java\top\kuanghua\feign\config\FeignConfiguration.java
/*feign转发时将请求的参数设转发到请求头上*/
@Configuration
@Log4j2
public class FeignConfiguration implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
//获取到头参数
ServletRequestAttributes attributes = (ServletRequestAttributes)
RequestContextHolder.getRequestAttributes();
if (!ObjectUtils.isEmpty(attributes)) {
HttpServletRequest request = attributes.getRequest();
Enumeration headerNames = request.getHeaderNames();
if (headerNames != null) {
//循环设置头参数,进行转发
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String values = request.getHeader(name);
template.header(name, values);
}
}
}
}
}
使用 ty-common\src\main\java\top\kuanghua\feign\tyauth\feign\TestGetTokenFeign.java
//configuration:自定义feign转发配置
@FeignClient(name = "ty-auth", configuration = FeignConfiguration.class)
@RequestMapping("feignTest")
public interface TestGetTokenFeign {
@PostMapping("getTokenInfo")
public ResResult getTokenInfo();
}
体验例子
gateway->ty-example->ty-auth输出
ty-example\src\main\java\top\kuanghua\tyexample\controller\GetTokenFromOtherService.java
@RestController
@Api(tags = "feign转发请求头测试")
@RequestMapping("testFeign")
@Slf4j
public class GetTokenFromOtherService {
@Resource
private TestGetTokenFeign testGetTokenFeign;
@ApiOperation(value = "上传图片或文件")
@PostMapping("getTokenFromService")
public void getTokenFromService() {
ResResult tokenInfo = testGetTokenFeign.getTokenInfo();
log.info(tokenInfo.getData().toString());
}
ty-auth\src\main\java\top\kuanghua\tyauth\controller\TestGetTokenController.java
@RestController
@RequestMapping("feignTest")
@Slf4j
public class TestGetTokenController {
/*
* 解析token
* */
@PostMapping("getTokenInfo")
public ResResult getTokenInfo(
@ApiIgnore @RequestHeader("TOKEN_INFO") String TOKEN_INFO,
@ApiIgnore @RequestHeader("AUTHORIZE_TOKEN") String AUTHORIZE_TOKEN
) {
try {
Map tokenInfo = JSON.parseObject(URLDecoder.decode(TOKEN_INFO, "utf-8"));
//得到转发信息
log.info(tokenInfo.toString());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
log.info(AUTHORIZE_TOKEN);
return new ResResult().success(TOKEN_INFO);
}
}
所有从网关转发的微服务中可以通过
@RequestHeader("TOKEN_INFO"):获取token解析后的信息 @RequestHeader("AUTHORIZE_TOKEN"):获取到未解析的token