「Feign」OpenFeign入门以及远程调用

一、OpenFeign介绍

OpenFeign是 种声明式,模版化的HTTP客户端。使 OpenFeign进 远程调 时,开发者完全感知不到这是在进 远程调 , 是像在调 本地 法 样。使 式是注解+接 形式,把需要调 的远程接 封装到接 当中,映射地址为远程接 的地址。在启动SpringCloud应 时,Feign会扫描标有@FeignClient注解的接 , 成代理并且注册到Spring容器当中。 成代理时Feign会为每个接 法创建 个RequestTemplate对象,该对象封装HTTP请求需要的全部信息,请求参数名、请求 法等信息都是在这个过程中确定的,模版化就体现在这 。

二、OpenFeign的使用

  • 搭建前置环境,在pom.xml文件中引入依赖,可以选择使用注册中心或者配置中心

org.springframework.cloud spring-cloud-dependencies 2020.0.3 pom import org.springframework.cloud spring-cloud-starter-consul-config org.springframework.cloud spring-cloud-starter-consul-discovery org.springframework.boot spring-boot-starter-actuator org.springframework.cloud spring-cloud-starter-openfeign

1.使用注册中心

  • 使 注册中 ,将服务注册到consul(nacos),调 者拿到被调 服务的地址端 进 调

spring.cloud.consul.host=192.168.0.124#consul地址spring.cloud.consul.port=8080#端 号spring.cloud.consul.discovery.service-name=service-test-01#服务名称spring.cloud.consul.discovery.health-check-interval=1m#健康检查间隔时间server.port=10000#服务端 号

  • 在配置类上开启服务发现以及允许远程调

@EnableDiscoveryClient //开启服务发现@EnableFeignClients //开启服务调 ,只需要在调 开启即可

  • 服务运 之后可以在consul的UI界 看到运 的服务,consul会定时检查服务的健康状态
  • 创建远程调用接口

@FeignClient(“serviceName”)public interface Service2Remote { /** 这 有 定义解码器对远程调 的结果进 解析,拿到真正的返回类型,所以接 返回值类型和远程接 返回类型保持 致 **/ @PostMapping(“/page”) List pageQuestion(PageQuestionReq req);}

  • 简单使用

@RestController@RequestMapping(“/service/remote”)public class RemoteController { @Autowired private Service2Remote service2Remote; @PostMapping(“/getQuestionList”) public List getQuestionList(@RequestBody PageQuestionReq req){ List result = service2Remote.pageQuestion(req); //对拿到的数据进 处理… return result; }}

2.使用配置中心

  • 将请求的URL写在配置中 进 读取修改配置 件

spring.cloud.consul.config.format=KEY_VALUE#consul 持yaml格式和Key-value形式spring.cloud.consul.config.enabled=true#开启配置spring.cloud.consul.config.prefixes=glab/plat/wt/application/test#consul配置存放的外层 件夹 录spring.cloud.consul.config.default-context=config# 级 件夹spring.cloud.consul.config.watch.delay=1000#轮询时间spring.cloud.consul.discovery.enabled=false#关闭注册remote.url=www.baidu.com#请求地址

  • 创建远程调用接口

@FeignClient(name = “service2RemoteByUrl”,url = “${remote.url}”) //name需要配置,URL从配置中 读取public interface Service2RemoteByUrl { @PostMapping(“/page”) List pageQuestion(PageQuestionReq req);}

3.自定义解码器(编码器)

// 定义解码器实现Decoder接 ,重写decode 法即可,根据具体需求进 编写//如果是 定义编码器,需要实现Encoder接 ,重写encode 法public class FeignDecoder implements Decoder { @Override public Object decode(Response response, Type type) throws IOException,DecodeException, FeignException { if (response.body() == null){ throw new DecodeException(ErrorEnum.EXECUTE_ERR.getErrno(),”没有获取到有效结果值”,response.request()); } // 拿到值 String result = Util.toString(response.body().asReader(Util.UTF_8)); Map resMap = null; try { resMap = JSON.parseObject(result, Map.class); } catch (Exception e) { //返回结果是字符串 return result; }}

4.远程调用携带Cookie

  • 由于feign调 是新创建 个Request,因此在请求时不会携带 些原本就有的信息,例如Cookie,因此需要 定义RequestInterceptor对Request进 额外设置, 般情况下,写 Cookie是 较常 的做法,如下设置

@Configurationpublic class BeanConfig { @Bean public RequestInterceptor requestInterceptor(){ return template -> { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); //此处可以根据业务 具体定制携带规则 String data = request.getParameter(“data”); String code = null; try { //这 需要转码,否则会报错 code = URLEncoder.encode(data, “UTF-8”); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } template.query(“data”,code); //请求头中携带Cookie String cookie = request.getHeader(“Cookie”); template.header(“Cookie”,cookie); }; } @Bean public Decoder decoder(){ return new FeignDecoder(); }}

三、调用流程解析

//在使 EnableFeignClients开启feign功能时,点击进 会看到该注解是通过ImportFeignClientsRegistrar类 效的,其中有个 法//registerBeanDefinitions执 两条语句registerDefaultConfiguration(metadata, registry); //加载默认配置信息registerFeignClients(metadata, registry); //注册扫描标有FeignClient的接 //关注registerFeignClients 法for (String basePackage : basePackages) { candidateComponents.addAll(scanner.findCandidateComponents(basePackage)); //在basePackage路径下扫描并添加标有FeignClient的接 }for (BeanDefinition candidateComponent : candidateComponents) { //遍历 if (candidateComponent instanceof AnnotatedBeanDefinition) { registerClientConfiguration(registry, name, attributes.get(“configuration”)); // registerFeignClient(registry, annotationMetadata, attributes); //注册到Spring容器当中, 法详细在FeignClientsRegistrar类当中 }}//在对feign调 时进 断点调试//在 成Feign远程接 的代理类时,调 处理器是Feign提供的FeignInvocationHandlerpublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (“equals”.equals(method.getName())) { //equals,hashCode,toString三个 法直接本地执 } else if (“hashCode”.equals(method.getName())) { return hashCode(); } else if (“toString”.equals(method.getName())) { return toString(); } //执 法对应的 法处理器MethodHandler,这个接 是Feign提供的,与InvocationHandler 任何关系,只有 个invoke 法 return dispatch.get(method).invoke(args);}//点进上 的invoke 法public Object invoke(Object[] argv) throws Throwable { //创建 个request模版 RequestTemplate template = buildTemplateFromArgs.create(argv); while (true) { try { return executeAndDecode(template, options); //创建request执 并且解码 } }}Object executeAndDecode(RequestTemplate template, Options options) throws Throwable { Request request = targetRequest(template); //创建Request并增强 Response response = client.execute(request, options); //执 调用请求,不再继续分析了 response = response.toBuilder().request(request).requestTemplate(template).build(); //如果有重写解码器,使 定义的解码器,feign默认使 SpringEncoder if (decoder != null) return decoder.decode(response, metadata.returnType()); } Request targetRequest(RequestTemplate template) { //如果 定义了RequestInterceptor,在这 可以对Request进 增强 for (RequestInterceptor interceptor : requestInterceptors) { //执 定义的apply 法 interceptor.apply(template); } //创建Request return target.apply(template);}

四、补充

  • 关于Client接 的实现类,使 注册中 和使 配置中 其流程稍有区别

//使 配置中 拿url 式进 调 ,使 的是Client的默认内部实现类 Default ,其中Default使 的是HttpURLConnection进 Http请求的HttpURLConnection connection = convertAndSend(request, options);//如果使 的是服务发现,使 的使 Client的实现类FeignBlockingLoadBalancerClient,它会去根据配置的服务名去注册中 查找服务的IP地址和端 号,执 使 的仍然是默认实现类Default,通过HttpURLConnection请求//FeignBlockingLoadBalancerClient,根据服务名称查找服务IP地址、端 88 ServiceInstance instance = loadBalancerClient.choose(serviceId, lbRequest);//具体实现 法,BlockingLoadBalancerClient类中 145 Response loadBalancerResponse = Mono.from(loadBalancer.choose(request)).block();//还有其他实现Client接 的客户端,例如ApacheHttpClient,ApacheHttpClient带有连接池功能,具有优秀的HTTP连接复 能 ,需要通过引 依赖来使

郑重声明:本文内容及图片均整理自互联网,不代表本站立场,版权归原作者所有,如有侵权请联系管理员(admin#wlmqw.com)删除。
用户投稿
上一篇 2022年6月13日 21:14
下一篇 2022年6月13日 21:14

相关推荐

  • 计算机网络技术论文(计算机网络技术论文七千字)

    今天小编给各位分享计算机网络技术论文的知识,其中也会对计算机网络技术论文七千字进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧! 计算机网络方面的论文3000字…

    2022年11月26日
  • 抖音带货怎么做入门(抖音带货怎么做入门教学)

    相信很多小伙伴都有注意到,现在抖音已经成为大家最常光顾的一个平台了,作为一个日活破亿的流量池,如今抖音上的用户数量极大。因此,现在在抖音上带货、卖货的人也是越来越多了,那么想在抖音…

    2022年11月25日
  • 沈阳茂业中心

    由深圳赢商网茂业集团与上海建工集团联袂打造的沈阳金廊第一高楼沈阳茂业中心于2011年11月8日顺利实现主塔楼结构封顶至此,历经四年,沈阳茂业中心以31095m的高度雄踞东北超高层建…

    2022年11月25日
  • 前三季度,市场规模超过五万亿元 信息消费展现蓬勃生机

    家居企业个性化全屋定制系统,备受消费者青睐;主打专业电竞的新款高性能便携式计算机,销量表现创新高;物流企业推出数智化供应链兴农服务项目,助力优质农产品出深山…… 不久前,工信部发布…

    2022年11月24日
  • 1千克等于多少磅

    克,此定义在1958年被美国以及其他英联邦会员国承认换算回来,一千克等于262磅,一磅等于037千克英国在1963年开始,依据度量衡法案的规;1 磅=16 盎司=04536 千克 …

    2022年11月24日
  • 广州花都岭南批发地女装在哪拿货好(广州花都岭南批发地女装)

    广州的服装批发市场人气一直也都挺高的,不过很多商家第一次来广州进货,对于一些女装货源批发还不是很了解。广州花都岭南批发地女装在哪拿货好?现在广州服装货源批发哪里最便宜呢?今天小编整…

    2022年11月23日
  • 微信健康码怎么注销重新申请健康码 怎么更换绑定人

    在疫情常态化的管理之下,出行都需要健康码,那么如果因为种种原因注销了健康码怎么办呢?这种情况下是否还可以再申请健康码呢?下面一起来看看了解一下吧! 微信健康码注销了还能申请吗 健康…

    2022年11月22日
  • 拼多多免费领商品有什么规则(拼多多免费领商品金币后面是什么)

    拼多多免费领商品活动相信不少小伙伴都参加过,吸引力还是很大的,只要砍价成功就可以免费领到商品,一些小伙伴第一次参加不知道拼多多免费领商品有什么规则?下面小编为大家带来拼多多免费领商…

    2022年11月21日
  • 个人核心能力有哪些一个人想要成长,需要具备这5项核心能力

    能力。Enjoy~ 01 培养成长型心态 斯坦福大学心理学教授卡罗尔·德维克在做“如何应对失败”的研究时,曾做过一个试验:她给一群小学生一些特别难的字谜,然后观察他们的反应。 她发…

    2022年11月20日
  • 京东店铺类型有哪些京东入驻有什么资质要求

    今天的互联网发展迅速,让传统企业有了更多选择,但也同样也对刚触网的商家增添了许多迷茫,近日知舟电商就收到很多商家朋友询问京东入驻相关问题,今天知舟君就给大家分享下。 一.京东入驻准…

    2022年11月18日

联系我们

联系邮箱:admin#wlmqw.com
工作时间:周一至周五,10:30-18:30,节假日休息