如何优雅使用feign调用微服务及转发token

2,859 阅读2分钟

完整项目地址:micro-service-plus

系列文章入口:

前言

有时我们微服务需要相互调用,这时就需要feign了,但是当网关转发到微服务时token还在请求头中,假设请求gateway-A-B,到B服务时token没了,这时就需要重新写feign配置了,下面我们就来详解如何更优雅的feign调用及转发请求头参数

我们先看看配置和使用

1642151423583

在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<String> 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