java feign请求pathvariable_Feign架构及原理解析

998eb013e4c6d199b24dd7f9680b465f.gif    阅读本文约需要8分钟 

大家好,我是你们的导师,我每天都会在这里给大家分享一些干货内容(当然了,周末也要允许老师休息一下哈)。上次老师跟大家分享了下SQL注入的相关知识,今天跟大家分享Feign架构及原理解析的知识。

1 什么是feign?

来自官网的解释:Feign makes writing java http clients easier

https://github.com/OpenFeign/feign

2 在使用feign之前,我们怎么发送请求?

拿okhttp举例:

public static void post(String url, HashMap<String, String > paramsMap){        OkHttpClient mOkHttpClient = new OkHttpClient();        FormBody.Builder formBodyBuilder = new FormBody.Builder();        Set<String> keySet = paramsMap.keySet();        for(String key:keySet) {            String value = paramsMap.get(key);            formBodyBuilder.add(key,value);        }        FormBody formBody = formBodyBuilder.build();        Request request = new Request                .Builder()                .post(formBody)                .url(url)                .build();        try (Response response = mOkHttpClient.newCall(request).execute()) {            System.out.println(response.body().string());        }catch (Exception e){            e.printStackTrace();        }    }    public static void main(String[] args) {        HashMap<String,String> paramsMap = new HashMap<String, String>() ;        paramsMap.put("name","小明");        paramsMap.put("html","...");        post("https://10.0.4.147:8015/crcc",paramsMap);    }

3 有了feign之后我们怎么发送请求

18ac1fb731e64f4cc241fd179b8e0324.png

@FeignClient(value = "FooBarService", configuration = FooBarServiceFeignConfiguration.class)public interface FooBarService {    @RequestMapping(value = "/foo", method = RequestMethod.GET)    String foo(@RequestParam(value = "param1") String param1);    @RequestMapping(value = "/bar", method = RequestMethod.POST)    String bar(@RequestParam(value = "param1") String param1, @RequestParam(value = "param2") String param2);}
@AutowiredFooBarService fooBarService;public String foo() {    return fooBarService.foo("rt");}

几行代码就能搞定,很大程度的节省了工作量,而且客户端和服务端关于接口的定义只需要写一次

具体的利弊我们这里就不做分析,在微服务盛行的现在,服务之间的调用单纯使用http client的场景已经基本不存在 

4 spring cloud openfeign的加载过程

上面的代码为什么接口没有实现类也可以使用,是不是跟mybatis一样使用了代理?

没错,接口最后都会生成代理实现

(右键新标签打开可查看大图)

7decbedd09e5e1e6912dbdac0e53ee19.png

spring cloud openfeign关于代理的生成过程

(右键新标签打开可看大图)

9bd952c0e97a577db8950f97144b4cc5.png

5 feign的REST Client API思想

JAX-RS标准

最新的REST接口标准为JAX-RS2.0,但是标准是供参考不能拿来直接吃的,具体还是要通过实现了标准的中间件来进行使用

JAX-RS2.0 之 REST Client API

摘自《Java RESTful Web Service实战(第2版)》

1adfd0e4364f0c7d29a1c420beb8dd6c.png

为什么JAX-RS2.0这么去抽象,我们这里暂不深入去思考,先拿来主义

jersey

jersey是JAX-RS标准的参考实现,是Java领域中最纯正的REST服务开发框架,例如eureka也是使用jersey来做REST接口和客户端发送请求,详见《服务发现之eureka》 

jersey 之 REST Client API

ClientConfig clientConfig = new ClientConfig();clientConfig.register(MyClientResponseFilter.class);clientConfig.register(new AnotherClientFilter()); Client client = ClientBuilder.newClient(clientConfig);client.register(ThirdClientFilter.class); WebTarget webTarget = client.target("http://example.com/rest");webTarget.register(FilterForExampleCom.class);WebTarget resourceWebTarget = webTarget.path("resource");WebTarget helloworldWebTarget = resourceWebTarget.path("helloworld");WebTarget helloworldWebTargetWithQueryParam =        helloworldWebTarget.queryParam("greeting", "Hi World!"); Invocation.Builder invocationBuilder =        helloworldWebTargetWithQueryParam.request(MediaType.TEXT_PLAIN_TYPE);invocationBuilder.header("some-header", "true"); Response response = invocationBuilder.get();System.out.println(response.getStatus());System.out.println(response.readEntity(String.class));

feign与JAX-RS2.0

feign主要是作为客户端发送请求,所以也是参考对照了JAX-RS2.0标准

feign并不是REST Client,只是参考了REST Client的实现,具体的目标还是为了更简单的实现http client请求

feign中怎么进行对应呢?

955c8629ba5e07c2c938ab89bd908f78.png

为什么这么去抽象我们这里也暂不深入研究(更深层的JAX-RS为什么这么抽象还未探明) 

6 feign代理的执行流程和关键对象

代理生成时用到了什么组件、代理执行时用到了什么组件?

上文我们知道,所有请求最后都交给了MethodHandler来执行,所以我们重点关注MethodHandler即可

(右键新标签打开可查看大图)

7decbedd09e5e1e6912dbdac0e53ee19.png

MethodHandler的关键对象和执行请求的流程

fb9e21abaa2b4db7d4650fc21ff3abdf.png

1.RequestTemplate.Factory

创建RequestTemplate的工厂,包含MethodMetadata和Encoder对象

其中MethodMetadata是应用初始化时Contract解析@RequestMapping @RequestParam等注解而来的中间数据

2.Encoder 

报文压缩gzip等

3.RequestInterceptor

为请求附加一些信息,类似spring mvc的interceptor拦截器

4.Target

主要是把@FeignClient里的url拼接到RequestTemplate

5.Options

用于请求的参数配置

6.Decoder 

解析返回报文,如果返回404,判断decode404==true则解析,否则交给ErrorDecoder解析

7.ErrorDecoder

请求错误处理

8.Logger.Level

日志等级,包含四种 none basic headers full

9.Logger

对应的配置为LoggerFactory,记录日志用

10.Retryer

重试,DefaultRetryer默认会重试5次

11.Client

真正执行http请求的客户端,可以配置,默认由FeignRibbonClientAutoConfiguration进行配置结合ribbon使用

7 spring cloud openfeign的配置

配置的优先级顺序

(右键新标签打开可查看大图)

520854ffc9642e07ef538ff7e4c72b39.png

properties和spring bean可以配置的内容

主要还是配置我们上面feign的关键对象,properties和spring bean可配置的项如下 

439575a47a1f7a630b731ab73d63ead7.png

同ribbon一样,spring-cloud-openfeign的配置也是懒加载,每个feignclient都可以有自己个性化的配置,且配置是懒加载的,但是为每个接口生成代理的时候已经去注册和使用了相关的配置,其实懒加载没有用了。

所以只实现了最终目的:每个feignclient 都可以有自己个性化的配置

这里的FeignContext跟ribbon的SpringClientFactory同理 

public class FeignContext extends NamedContextFactory<FeignClientSpecification> {   public FeignContext() {      super(FeignClientsConfiguration.class, "feign", "feign.client.name");   }}

feign与ribbon对接的关键点

feign与ribbon对接主要还是在Client对象上做文章,将Client替换为继承Ribbon模板的实现类,这样就可以对执行请求前后做一些负载逻辑,详见《负载均衡之ribbon》

参考来源:https://www.cnblogs.com/roytian/p/12196790.html

今天就分享这么多,于Feign架构及原理解析会了多少欢迎在留言区评论,对于有价值的留言,我们都会一一回复的。如果觉得文章对你有一丢丢帮助,请点右下角【在看】,让更多人看到该文章。

5650b884657216781fcdf64b2a5fe59b.gif

828797b867792bc5ec7ac30d69d6fbaf.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值