我的编程空间,编程开发者的网络收藏夹
学习永远不晚

SpringCloud的Gateway怎么使用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

SpringCloud的Gateway怎么使用

这篇文章主要讲解了“SpringCloud的Gateway怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“SpringCloud的Gateway怎么使用”吧!

SpringCloud微服务项目之间调用是通过httprest请求来进行服务调用的,之前我们会用到HttpClient等工具来进行服务请求,Spring对这种请求进行了处理,封装成了可声明式的web客户端,使得编写web客户端更容易,feign还支持可插拔的编码器和解码器,Spring在用的时候增加了对@requestMapping的处理,同时,SpringCloud还对feign集成了注册中心(eureka)和客户端负载均衡(ribbon),使得我们拥有一个客户端负载均衡的web请求客户端。

Feign源码分析

  @Override    public void refresh() throws BeansException, IllegalStateException {        synchronized (this.startupShutdownMonitor) {            // 扫描本项目里面的java文件,把bean对象封装成BeanDefinitiaon对象,然后调用DefaultListableBeanFactory#registerBeanDefinition()方法把beanName放到DefaultListableBeanFactory 的 List<String> beanDefinitionNames 中去            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();            // Prepare the bean factory for use in this context.            prepareBeanFactory(beanFactory);            try {                postProcessBeanFactory(beanFactory);                // 在这里调用到FeignClientsRegistrar对象的registerBeanDefinitions()方法                invokeBeanFactoryPostProcessors(beanFactory);                //从DefaultListableBeanFactory里面的beanDefinitionNames中找到所有实现了BeanPostProcessor接口的方法,如果有排序进行排序后放到list中                registerBeanPostProcessors(beanFactory);                //Spring的国际化                initMessageSource();                //                 initApplicationEventMulticaster();                // Initialize other special beans in specific context subclasses.                onRefresh();                //                 registerListeners();                // Spring的IOC、ID处理。Spring的AOP。事务都是在IOC完成之后调用了BeanPostProcessor#postProcessBeforeInitialization()和postProcessBeforeInitialization()方法,AOP(事务)就是在这里处理的                finishBeanFactoryInitialization(beanFactory);                // 执行完之后调用实现了所有LifecycleProcessor接口的类的onRefresh()方法,同时调用所有观察了ApplicationEvent接口的事件(观察者模式)                finishRefresh();            }            catch (BeansException ex) {                // 找到所有实现了DisposableBean接口的方法,调用了destroy()方法,这就是bean的销毁                destroyBeans();                // Reset 'active' flag.                cancelRefresh(ex);                throw ex;            }            finally {                resetCommonCaches();            }        }    }

根据上面整理的代码发现,FeignClientsRegistrar#registerBeanDefinitions()方法是在扫描完bean之后,只放了一个beanname的情况下, 并没有进行IOC注册的时候调用的,这就是Spring动态扩展Bean,实现BeanDefinitionRegistryPostProcessor接口的所有方法也会在这里调用下postProcessBeanDefinitionRegistry()方法。关于Spring的东西就分析到这里。下面回到正题,分析FeignClientsRegistrar#registerBeanDefinitions()方法:

 @Override    public void registerBeanDefinitions(AnnotationMetadata metadata,            BeanDefinitionRegistry registry) {        registerDefaultConfiguration(metadata, registry);//扫描EnableFeignClients标签里配置的信息,注册到beanDefinitionNames中。        registerFeignClients(metadata, registry);    }     public void registerFeignClients(AnnotationMetadata metadata,            BeanDefinitionRegistry registry) {        AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(                FeignClient.class);        //省略代码...根据EnableFeignClients配置的basePackages找到包下所有FeignClient注解的类,Spring的Commponet也是这么干的        for (String basePackage : basePackages) {            Set<BeanDefinition> candidateComponents = scanner                    .findCandidateComponents(basePackage);            for (BeanDefinition candidateComponent : candidateComponents) {                if (candidateComponent instanceof AnnotatedBeanDefinition) {                    // verify annotated class is an interface                    AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent;                    AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();                    Assert.isTrue(annotationMetadata.isInterface(),                            "@FeignClient can only be specified on an interface");                    Map<String, Object> attributes = annotationMetadata                            .getAnnotationAttributes(                                    FeignClient.class.getCanonicalName());                    String name = getClientName(attributes);                                       //这个方法就是在ioc容器中塞入一个FeignClientSpecification对象,从而构建FeignContext子容器。                    registerClientConfiguration(registry, name,                            attributes.get("configuration"));                           //重点分析这个                    registerFeignClient(registry, annotationMetadata, attributes);                }            }        }    }    private void registerFeignClient(BeanDefinitionRegistry registry,            AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {        String className = annotationMetadata.getClassName();        BeanDefinitionBuilder definition = BeanDefinitionBuilder                .genericBeanDefinition(FeignClientFactoryBean.class);//对FeignClientFactoryBean对象生成一个BeanDefinition对象        ...读取配置        String alias = name + "FeignClient";        AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();        boolean primary = (Boolean)attributes.get("primary"); // has a default, won't be null        beanDefinition.setPrimary(primary);        String qualifier = getQualifier(attributes);        if (StringUtils.hasText(qualifier)) {            alias = qualifier;        }        BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className,                new String[] { alias });        //注册到beanDefinitionNames中对象        BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);//    }

读过Dubbo源码的同学都知道,当在DubboNamespaceHandler中解析reference标签的时候,传入了一个ReferenceBean对象,把xml中配置的属性都塞到这个对象上,也是装到了beanDefinitionNames中,然后发现ReferenceBean类和FeignClientFactoryBean都实现了FactoryBean的接口,并且里面都有getObject()和getObjectType()方法。当接口调用到这个feign客户端的时候,会从IOC中读取这个FeignClientFactoryBean并且调用getObject方法。下面就是分析getObject方法:

 @Override    public Object getObject() throws Exception {        FeignContext context = applicationContext.getBean(FeignContext.class);        //从上文中的子容器中获取编码器,解码器等自定义类,然后封装一个Feign.Builder类        Feign.Builder builder = feign(context);        if (!StringUtils.hasText(this.url)) {//当@FeignClient没有配置url的时候            String url;            if (!this.name.startsWith("http")) {                url = "http://" + this.name;            }            else {                url = this.name;            }            url += cleanPath();            return loadBalance(builder, context, new HardCodedTarget<>(this.type,                    this.name, url));//集成了ribbon客户端负载均衡,下一篇分析        }        //当@FeignClient配置了url的时候        if (StringUtils.hasText(this.url) && !this.url.startsWith("http")) {            this.url = "http://" + this.url;        }        String url = this.url + cleanPath();        Client client = getOptional(context, Client.class);        if (client != null) {            if (client instanceof LoadBalancerFeignClient) {                // not lod balancing because we have a url,                // but ribbon is on the classpath, so unwrap                client = ((LoadBalancerFeignClient)client).getDelegate();            }            builder.client(client);        }        Targeter targeter = get(context, Targeter.class);        return targeter.target(this, builder, context, new HardCodedTarget<>(                this.type, this.name, url));    }

首先看配置了url的,指定了url的feignclient解析,一直跟着代码跟到了Feign.Builder#target()方法:

   public <T> T target(Target<T> target) {      return build().newInstance(target);    }    public Feign build() {      SynchronousMethodHandler.Factory synchronousMethodHandlerFactory =          new SynchronousMethodHandler.Factory(client, retryer, requestInterceptors, logger,                                               logLevel, decode404);      ParseHandlersByName handlersByName =          new ParseHandlersByName(contract, options, encoder, decoder,                                  errorDecoder, synchronousMethodHandlerFactory);      return new ReflectiveFeign(handlersByName, invocationHandlerFactory);    }

直接看ReflectiveFeign#newInstance()方法:

//ReflectiveFeign#newInstance()    public <T> T newInstance(Target<T> target) {                                                //动态代理的handler类目前穿进来的是ParseHandlersByName类,所以这里要看ParseHandlersByName#apply()直接看下一个方法      Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target);      Map<Method, MethodHandler> methodToHandler = new LinkedHashMap<Method, MethodHandler>();      List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList<DefaultMethodHandler>();      for (Method method : target.type().getMethods()) {        if (method.getDeclaringClass() == Object.class) {          continue;        } else if(Util.isDefault(method)) {//默认方法会走到这里,比如toString(),hashCode()等方法          DefaultMethodHandler handler = new DefaultMethodHandler(method);          defaultMethodHandlers.add(handler);          methodToHandler.put(method, handler);        } else {//这里才是装配的调用类,上文分析到计息的handler是SynchronousMethodHandler#invoke()          methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));        }      }      InvocationHandler handler = factory.create(target, methodToHandler);      T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(), new Class<?>[]{target.type()}, handler);//jdk动态代理      for(DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) {        defaultMethodHandler.bindTo(proxy);      }      return proxy;    }    //ParseHandlersByName#apply类,构建动态代理的handler    public Map<String, MethodHandler> apply(Target key) {        List<MethodMetadata> metadata = contract.parseAndValidatateMetadata(key.type());        Map<String, MethodHandler> result = new LinkedHashMap<String, MethodHandler>();        for (MethodMetadata md : metadata) {          BuildTemplateByResolvingArgs buildTemplate;          if (!md.formParams().isEmpty() && md.template().bodyTemplate() == null) {            buildTemplate = new BuildFormEncodedTemplateFromArgs(md, encoder);//通过自定义的encoder去解析参数          } else if (md.bodyIndex() != null) {            buildTemplate = new BuildEncodedTemplateFromArgs(md, encoder);//通过自定义的encoder去解析参数          } else {            buildTemplate = new BuildTemplateByResolvingArgs(md);          }          //创建handler,再看Factory#create()方法,下一个方法          result.put(md.configKey(),                     factory.create(key, md, buildTemplate, options, decoder, errorDecoder));        }        return result;      }    //Factory#create(),构建一个SynchronousMethodHandler去处理请求,调用invoke方法    public MethodHandler create(Target<?> target, MethodMetadata md,            RequestTemplate.Factory buildTemplateFromArgs,            Options options, Decoder decoder, ErrorDecoder errorDecoder) {        return new SynchronousMethodHandler(target, client, retryer, requestInterceptors, logger,                      logLevel, md, buildTemplateFromArgs, options, decoder,                      errorDecoder, decode404);    }    //SynchronousMethodHandler#invoke()方法:实际调用的方法    //@Override    public Object invoke(Object[] argv) throws Throwable {        RequestTemplate template = buildTemplateFromArgs.create(argv);//构建requestTemplate对象        Retryer retryer = this.retryer.clone();        while (true) {          try {            return executeAndDecode(template);//下面不分析了,就是执行execute方法并且解码饭后返回值          } catch (RetryableException e) {            retryer.continueOrPropagate(e);            if (logLevel != Logger.Level.NONE) {              logger.logRetry(metadata.configKey(), logLevel);            }            continue;          }        }      }

感谢各位的阅读,以上就是“SpringCloud的Gateway怎么使用”的内容了,经过本文的学习后,相信大家对SpringCloud的Gateway怎么使用这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

SpringCloud的Gateway怎么使用

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

SpringCloud的Gateway怎么使用

这篇文章主要讲解了“SpringCloud的Gateway怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“SpringCloud的Gateway怎么使用”吧!SpringCloud微服
2023-06-05

SpringCloud Gateway路由组件怎么使用

这篇文章主要介绍“SpringCloud Gateway路由组件怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“SpringCloud Gateway路由组件怎么使用”文章能帮助大家解决问题。
2023-07-05

SpringCloud中Gateway的使用教程详解

SpringCloud Gateway是Spring体系内的一个全新项目,它旨在为微服务架构提供一种简单有效的统一的API路由管理方式。本文就来为大家详细讲讲Gateway的使用教程,需要的可以参考一下
2022-11-13

SpringCloud GateWay网关怎么配置

本文小编为大家详细介绍“SpringCloud GateWay网关怎么配置”,内容详细,步骤清晰,细节处理妥当,希望这篇“SpringCloud GateWay网关怎么配置”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知
2023-06-30

SpringCloud之SpringCloud gateway网关路由怎么配置

本篇内容介绍了“SpringCloud之SpringCloud gateway网关路由怎么配置”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
2023-07-05

使用SpringCloud Gateway解决跨域问题

本文介绍了使用SpringCloudGateway解决跨域问题。跨域问题是一种安全机制,限制来自不同域或协议的请求。SpringCloudGateway提供了一个内置的CORS处理机制,可以轻松解决跨域请求被浏览器阻止的问题。用户可以通过启用CORS支持、配置CORS规则和将CORS处理添加到Gateway路由来配置SpringCloudGateway以支持CORS。使用SpringCloudGateway解决跨域问题具有简单易用、灵活可配置和集中管理等优点。需要注意的是,在启用CORS时要谨慎并采取适当
使用SpringCloud Gateway解决跨域问题
2024-04-02

SpringCloud Gateway动态路由怎么配置

这篇“SpringCloud Gateway动态路由怎么配置”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“SpringClo
2023-07-05

springcloud整合gateway怎么实现网关

这篇文章主要介绍了springcloud整合gateway怎么实现网关的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇springcloud整合gateway怎么实现网关文章都会有所收获,下面我们一起来看看吧。1
2023-06-26

引入SpringCloud-gateway报错怎么解决

本篇内容介绍了“引入SpringCloud-gateway报错怎么解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1.问题描述在我引入Sp
2023-06-20

SpringCloud微服务网关Gateway怎么创建

这篇文章主要介绍“SpringCloud微服务网关Gateway怎么创建”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“SpringCloud微服务网关Gateway怎么创建”文章能帮助大家解决问题。
2023-07-02

springcloud gateway集成knife4j的方法是什么

这篇文章主要介绍“springcloud gateway集成knife4j的方法是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“springcloud gateway集成knife4j的方法是什
2023-07-05

SpringCloud Gateway服务网关的部署与使用的方法是什么

这篇文章主要介绍“SpringCloud Gateway服务网关的部署与使用的方法是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“SpringCloud Gateway服务网关的部署与使用的方法
2023-07-05

springcloud gateway怎么实现路由和负载均衡

这篇文章将为大家详细讲解有关springcloud gateway怎么实现路由和负载均衡,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。简介:gateway主要是做路由 负载,过滤 主要是替代zuul 1.
2023-06-20

SpringCloud Gateway中怎么配置fastjson序列化验证

本篇内容主要讲解“SpringCloud Gateway中怎么配置fastjson序列化验证”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“SpringCloud Gateway中怎么配置fast
2023-06-05

Nginx+SpringCloud Gateway怎么搭建项目访问环境

这篇文章主要讲解了“Nginx+SpringCloud Gateway怎么搭建项目访问环境”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Nginx+SpringCloud Gateway怎么
2023-06-20

java springcloud的Stream怎么使用

本篇内容主要讲解“java springcloud的Stream怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“java springcloud的Stream怎么使用”吧!Spring C
2023-06-05

SpringCloud Hystrix怎么使用

这篇文章主要介绍“SpringCloud Hystrix怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“SpringCloud Hystrix怎么使用”文章能帮助大家解决问题。Hystrix是
2023-07-02

SpringCloud中Gateway实现鉴权的方法是什么

本篇内容介绍了“SpringCloud中Gateway实现鉴权的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、JWT 实现微服
2023-06-21

SpringCloud怎么实现服务调用feign、熔断hystrix和网关gateway

本文小编为大家详细介绍“SpringCloud怎么实现服务调用feign、熔断hystrix和网关gateway”,内容详细,步骤清晰,细节处理妥当,希望这篇“SpringCloud怎么实现服务调用feign、熔断hystrix和网关gat
2023-07-05

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录