• Java spring cloud gateway GlobalFilter通过feign调用其他服务


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

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

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

    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)}

     

    1.GlobalFilter过滤类

     1 @Component
     2 public class InnerFilter implements GlobalFilter, Ordered {
     3 
     4     @SneakyThrows
     5     @Override
     6     public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
     7         SysLog sysLog = new SysLog();
     8         sysLog.setLoginName("lsz");
     9 
    10         //获取的关键看这里,在用的时候在获取bean  
    11         SysLogClient sysLogClient = AutowiredBean.getBean(SysLogClient.class);
    12      //异步调用feign服务接口   
    13         CompletableFuture<HttpResult> f = CompletableFuture.supplyAsync(()->{
    14             return sysLogClient.getSysLogListWithPage(0, 10, "ad");
    15         });
    16 
    17         HttpResult result = f.get();
    18         // TODO 这里未来还可以限制一些格式
    19         return chain.filter(exchange.mutate().request(exchange.getRequest()).build());
    20     }
    21     
    22     /**
    23      * 优先级默认设置为最高
    24      *
    25      * @return
    26      */
    27     @Override
    28     public int getOrder() {
    29         return -800;
    30     }
    31 }

    2.获取feign服务类AutowiredBean

     1  2 
     3 import org.springframework.beans.BeansException;
     4 import org.springframework.context.ApplicationContext;
     5 
     6 public class AutowiredBean{
     7 
     8     private static ApplicationContext applicationContext;
     9 
    10     public static void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    11         if (AutowiredBean.applicationContext == null) {
    12             AutowiredBean.applicationContext = applicationContext;
    13         }
    14     }
    15 
    16     public static ApplicationContext getApplicationContext() {
    17         return applicationContext;
    18     }
    19 
    20     public static Object getBean(String name) {
    21         return getApplicationContext().getBean(name);
    22     }
    23 
    24     public static <T> T getBean(Class<T> clazz) {
    25         return getApplicationContext().getBean(clazz);
    26     }
    27 
    28     public static <T> T getBean(String name, Class<T> clazz) {
    29         return getApplicationContext().getBean(name, clazz);
    30     }
    31 
    32 }

    3. Feign配置类,解决异步调用 feign 的错误

    package com.hnlt.cloud.gateway.config;
    
    import feign.Logger;
    import feign.codec.Decoder;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.ObjectFactory;
    import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
    import org.springframework.cloud.openfeign.support.ResponseEntityDecoder;
    import org.springframework.cloud.openfeign.support.SpringDecoder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.MediaType;
    import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 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);
            }
        }
    }

     

  • 相关阅读:
    win7_64 下redis安装并进行php-redis扩展
    redis 与 memcache 性能测试比较
    前端一班:HTML5当天学习总结-摘抄张果博客园
    Hibernate ORM框架——项目一:Hibernate事务的生命周期,不建议使用openSession而改造
    Hibernate ORM框架——Hibernate查询之Criteria接口、Native SQL 查询、Query接口(批量操作)
    Hibernate ORM框架——Hibernate分页查询and多表查询
    Hibernate ORM框架——项目一:Hibernate查询;项目二:集合相关查询
    Hibernate ORM框架——连接池相关
    Hibernate ORM框架——综合
    Hibernate ORM框架——续第二章:Hibernate映射关系:双向关联
  • 原文地址:https://www.cnblogs.com/zou-zou/p/15419772.html
Copyright © 2020-2023  润新知