spring cloud的gateway通过feign调用其他服务

需求说明:在gateway服务里面需要调用其他服务的接口

问题分析:1.在GlobalFilter过滤类中获取feign服务类时,用@Autowired注解获取会报错,这和servlet, filter的加载顺序有关,所以使用AutowiredBean类,原理是从spring上下文中获取feign的自定义Bean,然后在正常调用接口。获取feign服务类AutowiredBean代码如下:

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;

public class AutowiredBean{

    private static ApplicationContext applicationContext;

    public static void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (AutowiredBean.applicationContext == null) {
            AutowiredBean.applicationContext = applicationContext;
        }
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }

}

2.在过滤类中正常调用feign服务接口时,会抛出一个java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-2,意思是线程堵塞,使用CompletableFuture.supplyAsync异步调用解决。

解决代码,GlobalFilter过滤类代码如下::

@Component
public class InnerFilter implements GlobalFilter, Ordered {

    @SneakyThrows
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取的关键看这里,在用的时候在获取服务bean  
        SysLogClient sysLogClient = AutowiredBean.getBean(SysLogClient.class);
     //异步调用feign服务接口   
        CompletableFuture<HttpResult> f = CompletableFuture.supplyAsync(()->{
            // 此时就去调用服务的接口方法
            return sysLogClient.getSysLogListWithPage(0, 10, "cs");
        });

        HttpResult result = f.get();
        // TODO 这里未来还可以限制一些格式
        return chain.filter(exchange.mutate().request(exchange.getRequest()).build());
    }
    
    /**
     * 优先级默认设置为最高
     *
     * @return
     */
    @Override
    public int getOrder() {
        return -800;
    }
}

3.FeignConfig类解决异步调用 feign 的错误,不加这个类会抛一个异常java.util.concurrent.ExecutionException: feign.codec.DecodeException: No qualifying bean of type 'org.springframework.boot.autoconfigure.http.HttpMessageConverters' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

解决代码,Feign配置类,解决异步调用 feign 的错误:

/**
 * Feign 配置
 * @author: lsz
 * @time: 2021/10/15
 */
@Configuration
public class FeignConfig {

    @Bean
    Logger.Level feignLevel() {
        //这里记录所有
        return Logger.Level.FULL;
    }

    @Bean
    public Decoder feignDecoder() {
        return new ResponseEntityDecoder(new SpringDecoder(feignHttpMessageConverter()));
    }

    public ObjectFactory<HttpMessageConverters> feignHttpMessageConverter() {
        final HttpMessageConverters httpMessageConverters = new HttpMessageConverters(new PhpMappingJackson2HttpMessageConverter());
        return new ObjectFactory<HttpMessageConverters>() {
            @Override
            public HttpMessageConverters getObject() throws BeansException {
                return httpMessageConverters;
            }
        };
    }

    public class PhpMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {
        PhpMappingJackson2HttpMessageConverter(){
            List<MediaType> mediaTypes = new ArrayList<>();
            mediaTypes.add(MediaType.valueOf(MediaType.TEXT_HTML_VALUE + ";charset=UTF-8"));
            setSupportedMediaTypes(mediaTypes);
        }
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: Spring Cloud Gateway 本身并不能直接使用 FeignFeign 是一个用于声明式、模板化 HTTP 客户端的库,它可以帮助我们更方便地编写基于 HTTP 的服务调用代码。但是 Spring Cloud Gateway 更多地是作为一个 API 网关来使用,用于在微服务架构中进行请求路由、限流、熔断等操作。 虽然 Spring Cloud GatewayFeign 都是基于 Spring 框架的,但它们的使用场景和功能不同,不能直接进行集成。不过,在实际的项目中,我们通常会同时使用 Spring Cloud GatewayFeign 来完成不同的任务。比如,我们可以使用 Spring Cloud Gateway 进行路由、过滤等操作,而使用 Feign 进行服务间的调用。 ### 回答2: Spring Cloud Gateway 确实无法直接使用 Feign 进行服务间的通信。这是因为 Spring Cloud GatewayFeign 是两个不同的组件,具有不同的设计理念和用途。 Spring Cloud Gateway 是一个基于 Spring WebFlux 和 Reactor 的网关服务,用于处理请求路由和转发。它支持使用各种方式定义路由规则,并且具有强大的过滤器功能,可以对请求进行修改和验证。Spring Cloud Gateway 更加注重对请求的处理和转发,而不是直接进行服务间的通信。 相比之下,Feign 是一个基于注解的轻量级 HTTP 客户端,用于服务间的通信。通过定义接口和注解,Feign 可以帮助我们简化 HTTP 请求的编写和发送,从而实现服务之间的互通。Feign 的设计初衷是为了简化服务间通信的代码编写和维护,而不是用于路由和转发请求。 然而,我们可以在 Spring Cloud Gateway 中使用 WebClient 进行服务间的通信。WebClient 是 Spring WebFlux 提供的用于发送 HTTP 请求的非阻塞客户端。我们可以在 Gateway 的过滤器中使用 WebClient 发送请求到目标服务,然后将响应返回给客户端。 综上所述,尽管 Spring Cloud Gateway 无法直接使用 Feign 进行服务间的通信,但我们仍然可以利用 WebClient 在 Gateway 中实现服务间的通信。这种方式可以更好地符合 Spring Cloud Gateway 的设计理念和用途。 ### 回答3: Spring Cloud GatewayFeign是两个完全不同的组件,分别属于Spring Cloud的不同子项目。Spring Cloud Gateway是一个基于Spring Framework5,Spring Boot2和Project Reactor的新一代微服务网关,主要用于路由请求和进行过滤处理。而Feign是一个声明式的HTTP客户端,用于在微服务之间进行远程服务调用。 不能说Spring Cloud Gateway无法集成Feign,因为它们并不是相互替代的关系。在使用Spring Cloud Gateway时,一般是将Feign用作微服务之间的远程服务调用工具,而不是直接集成到Spring Cloud Gateway中。 当需要在Spring Cloud Gateway中进行远程服务调用时,可以使用Spring WebFlux提供的WebClient来实现。WebClient是一个响应式的HTTP客户端,可以用于发送请求并接收响应。通过使用WebClient,可以轻松地在Spring Cloud Gateway中进行远程服务调用。 总结来说,虽然Spring Cloud Gateway本身不直接支持Feign,但可以使用Spring WebFlux提供的WebClient在Spring Cloud Gateway中进行远程服务调用。在使用Spring Cloud Gateway时,可以结合Feign在微服务之间进行远程服务调用

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值