Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >[享学Feign] 二、原生Feign的注解介绍及使用示例

[享学Feign] 二、原生Feign的注解介绍及使用示例

作者头像
YourBatman
发布于 2020-02-21 08:33:52
发布于 2020-02-21 08:33:52
7.6K00
代码可运行
举报
文章被收录于专栏:BAT的乌托邦BAT的乌托邦
运行总次数:0
代码可运行

人无远虑,必有近忧。

代码下载地址:https://github.com/f641385712/feign-learning

前言

通过第一篇文章了解了Feign的最基础知识,作为一个有态度的程序员,我们势必要搞清楚它整个执行的脉络,了解它的执行过程和原理才算结束,这是最后最后最后进行个性化定制的基础,一切都为了“玩”嘛。

本文将讲解它原生支持的注解,毕竟Feign并不强依赖于Spring MVC,在Java环境也是可以作为HC来使用的,了解起来不难,建议你掌握。

说明:本文依旧仅仅只导入核心包feign-core包,因为所有的注解支持均在它的核心包内。


正文

本文内容依旧站在使用的角度看Feign,并且会结合具体的使用示例来辅以说明,相信不会让人觉得枯燥。

由于大多数人了解Feign、使用Feign都是出于Spring Cloud,平时使用的均是Spring MVC的注解。所以未免对Feign的原生注解了解并不多,本文就来帮你扫盲,让你在实际使用过程中能更加的得心应手。 源生注解并不多,此处逐个介绍:


@RequestLine

它只能标注在Method方法上。为请求定义HttpMethodUriTemplate(标注在方法上的就是一个HttpMethod,且写好了URI(可是绝对路径,也可是相对的,一般写后部分即可))。表达式、用大括号括起来的值{expression}最终会用对应的@Param注解填进去(根据key匹配)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@java.lang.annotation.Target(METHOD)
@Retention(RUNTIME)
public @interface RequestLine {
	
  // 书写请求方法 + URI	
  String value(); 
  // 是否编码/符号,默认是会编码的,也就是转义的意思
  boolean decodeSlash() default true;
  // 默认支持URL传多值,是通过key来传输的。形如:key=value1&key=value2&key=value3
  // CollectionFormat不同的取值对应不同的分隔符,一般不建议改
  CollectionFormat collectionFormat() default CollectionFormat.EXPLODED;

}

使用示例

在介绍使用示例之前,为了更好的看到效果,要求把Feign的日志打印出来,而Feign内置的Logger实现:

  • feign.Logger.JavaLogger:使用的java.util.logging.Logger输出,但是日志级别的FINE级别,默认不会输出到控制台
  • feign.Logger.ErrorLogger:错误输出。使用的System.err.printf()输出
  • feign.Logger.NoOpLogger:什么都不输出,它是Feign的默认使用的Logger实现,也就是不会给控制台输出

鉴于此,为了在控制台看到效果,因此本例(下同)所有的Logger实现均采用ErrorLogger~,并且不开启重试,统一由如下工厂创建出Client实例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public abstract class FeignClientFactory {
    static <T> T create(Class<T> clazz) {
        return Feign.builder()
                .logger(new Logger.ErrorLogger()).logLevel(Logger.Level.FULL) // 输出日志到控制台
                .retryer(Retryer.NEVER_RETRY) // 关闭重试
                .decode404() // 把404也解码 -> 这样就不会以一场形式抛出,中断程序喽,方便我测试嘛
                .target(clazz, "http://localhost:8080");
    }
}

测试代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface RequestLineClient {

    // 1、正常使用、正常书写
    @Headers({"Accept:*/*", "Accept-Language:    zh-cn"})
    @RequestLine("GET /feign/demo1?name={name}")
    String testRequestLine(@Param("name") String name);

    // 2、GET后不止一个空格,有多个空格
    @RequestLine("GET             /feign/demo1?name={name}")
    String testRequestLine2(@Param("name") String name);

    // 3、使用Map一次性传递多个查询参数,使用注解为@QueryMap
    @RequestLine("GET /feign/demo1")
    String testRequestLine3(@QueryMap Map<String, Object> params);

    // 4、方法参数上不使用任何注解
    @RequestLine("GET /feign/demo1")
    String testRequestLine4(String name);

    // 5、方法上标注有@Body注解,然后把方法参数传递给它
    @RequestLine("GET /feign/demo1")
    @Body("{name}")
    String testRequestLine5(@Param("name") String name);

    // 6、方法两个参数,均不使用注解标注
    // 启动直接报错:Method has too many Body parameters:
    // @RequestLine("GET /feign/demo1")
    // String testRequestLine6(String name,Integer age);

    // 7、启动直接报错:Body parameters cannot be used with form parameters.
    // @RequestLine("GET /feign/demo1")
    // @Body("{name}")
    // String testRequestLine7(@Param("name") String name, Integer age);

    // 8、如果你既想要body参数,又想要查询参数,请这么写
    @RequestLine("GET /feign/demo1?name={name}")
    @Body("{age}")
    String testRequestLine8(@Param("name") String name, @Param("age") Integer age);
}

说明:模版表达式必须用{}包起来才算一个表达式(变量),里面的值就是name(key),才会被@Param匹配然后替换掉~

测试程序:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void fun1() {
    RequestLineClient client = FeignClientFactory.create(RequestLineClient.class);
    client.testRequestLine("YourBatman");
    System.err.println(" ------------------ ");
    client.testRequestLine2("YourBatman2");
    System.err.println(" ------------------ ");

    // 使用Map一次传多个请求参数
    Map<String, Object> map = new HashMap<>();
    map.put("name", "YourBatman3");
    map.put("age", Arrays.asList(16, 18, 20));
    client.testRequestLine3(map);
    System.err.println(" ------------------ ");

    try {
        client.testRequestLine4("YourBatman4");
    } catch (Exception e) {
    }
    System.err.println(" ------------------ ");

    try {
        client.testRequestLine5("YourBatman4");
    } catch (Exception e) {
    }
    System.err.println(" ------------------ ");


    try {
        client.testRequestLine8("YourBatman4", 18);
    } catch (Exception e) {
    }
}

运行,控制台打印详细请求日志如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[RequestLineClient#testRequestLine] ---> GET http://localhost:8080/feign/demo1?name=YourBatman HTTP/1.1
[RequestLineClient#testRequestLine] Accept: */*
[RequestLineClient#testRequestLine] Accept-Language: zh-cn
[RequestLineClient#testRequestLine] ---> END HTTP (0-byte body)
[RequestLineClient#testRequestLine] <--- HTTP/1.1 200 (357ms)
[RequestLineClient#testRequestLine] content-length: 18
[RequestLineClient#testRequestLine] content-type: text/plain;charset=ISO-8859-1
[RequestLineClient#testRequestLine] date: Tue, 11 Feb 2020 09:53:09 GMT
[RequestLineClient#testRequestLine] vary: Access-Control-Request-Headers
[RequestLineClient#testRequestLine] vary: Access-Control-Request-Method
[RequestLineClient#testRequestLine] vary: Origin
[RequestLineClient#testRequestLine] 
[RequestLineClient#testRequestLine] success:YourBatman
[RequestLineClient#testRequestLine] <--- END HTTP (18-byte body)
 ------------------ 
[RequestLineClient#testRequestLine2] ---> GET http://localhost:8080/feign/demo1?name=YourBatman2 HTTP/1.1
[RequestLineClient#testRequestLine2] ---> END HTTP (0-byte body)
[RequestLineClient#testRequestLine2] <--- HTTP/1.1 200 (20ms)
[RequestLineClient#testRequestLine2] content-length: 19
[RequestLineClient#testRequestLine2] content-type: text/plain;charset=ISO-8859-1
[RequestLineClient#testRequestLine2] date: Tue, 11 Feb 2020 09:53:09 GMT
[RequestLineClient#testRequestLine2] vary: Access-Control-Request-Headers
[RequestLineClient#testRequestLine2] vary: Access-Control-Request-Method
[RequestLineClient#testRequestLine2] vary: Origin
[RequestLineClient#testRequestLine2] 
[RequestLineClient#testRequestLine2] success:YourBatman2
[RequestLineClient#testRequestLine2] <--- END HTTP (19-byte body)
 ------------------ 
[RequestLineClient#testRequestLine3] ---> GET http://localhost:8080/feign/demo1?name=YourBatman3&age=16&age=18&age=20 HTTP/1.1
[RequestLineClient#testRequestLine3] ---> END HTTP (0-byte body)
[RequestLineClient#testRequestLine3] <--- HTTP/1.1 200 (6ms)
[RequestLineClient#testRequestLine3] content-length: 19
[RequestLineClient#testRequestLine3] content-type: text/plain;charset=ISO-8859-1
[RequestLineClient#testRequestLine3] date: Tue, 11 Feb 2020 09:53:09 GMT
[RequestLineClient#testRequestLine3] vary: Access-Control-Request-Headers
[RequestLineClient#testRequestLine3] vary: Access-Control-Request-Method
[RequestLineClient#testRequestLine3] vary: Origin
[RequestLineClient#testRequestLine3] 
[RequestLineClient#testRequestLine3] success:YourBatman3
[RequestLineClient#testRequestLine3] <--- END HTTP (19-byte body)
 ------------------ 
[RequestLineClient#testRequestLine4] ---> GET http://localhost:8080/feign/demo1 HTTP/1.1
[RequestLineClient#testRequestLine4] Content-Length: 11
[RequestLineClient#testRequestLine4] 
[RequestLineClient#testRequestLine4] YourBatman4
[RequestLineClient#testRequestLine4] ---> END HTTP (11-byte body)
[RequestLineClient#testRequestLine4] <--- HTTP/1.1 400 (26ms)
[RequestLineClient#testRequestLine4] connection: close
[RequestLineClient#testRequestLine4] content-length: 47
[RequestLineClient#testRequestLine4] content-type: text/plain;charset=ISO-8859-1
[RequestLineClient#testRequestLine4] date: Tue, 11 Feb 2020 09:53:09 GMT
[RequestLineClient#testRequestLine4] 
[RequestLineClient#testRequestLine4] hello error:Request method 'POST' not supported
[RequestLineClient#testRequestLine4] <--- END HTTP (47-byte body)
 ------------------ 
[RequestLineClient#testRequestLine5] ---> GET http://localhost:8080/feign/demo1 HTTP/1.1
[RequestLineClient#testRequestLine5] Content-Length: 11
[RequestLineClient#testRequestLine5] 
[RequestLineClient#testRequestLine5] YourBatman4
[RequestLineClient#testRequestLine5] ---> END HTTP (11-byte body)
[RequestLineClient#testRequestLine5] <--- HTTP/1.1 400 (77ms)
[RequestLineClient#testRequestLine5] connection: close
[RequestLineClient#testRequestLine5] content-length: 47
[RequestLineClient#testRequestLine5] content-type: text/plain;charset=ISO-8859-1
[RequestLineClient#testRequestLine5] date: Tue, 11 Feb 2020 09:53:09 GMT
[RequestLineClient#testRequestLine5] 
[RequestLineClient#testRequestLine5] hello error:Request method 'POST' not supported
[RequestLineClient#testRequestLine5] <--- END HTTP (47-byte body)
 ------------------ 
[RequestLineClient#testRequestLine8] ---> GET http://localhost:8080/feign/demo1?name=YourBatman4 HTTP/1.1
[RequestLineClient#testRequestLine8] Content-Length: 2
[RequestLineClient#testRequestLine8] 
[RequestLineClient#testRequestLine8] 18
[RequestLineClient#testRequestLine8] ---> END HTTP (2-byte body)
[RequestLineClient#testRequestLine8] <--- HTTP/1.1 400 (7ms)
[RequestLineClient#testRequestLine8] connection: close
[RequestLineClient#testRequestLine8] content-length: 47
[RequestLineClient#testRequestLine8] content-type: text/plain;charset=ISO-8859-1
[RequestLineClient#testRequestLine8] date: Tue, 11 Feb 2020 09:53:09 GMT
[RequestLineClient#testRequestLine8] 
[RequestLineClient#testRequestLine8] hello error:Request method 'POST' not supported
[RequestLineClient#testRequestLine8] <--- END HTTP (47-byte body)

从日志中也能看出一点小细节:

  • @RequestLine注解的首个单词必须是HTTP方法,且必须顶格写(前面不允许有空格),但后面是需要有空格的且可以是多个空格
  • @Headers它的key连接符用的是:而不是=,请务必注意。另外:对空格不敏感
  • 但凡只要body体不为空,最终就会以POST请求的形式发出
    • 这是由默认实现:JDK底层实现HttpURLConnection决定的,如果你换成OkHttp将不会是这样
  • 方法参数若没标注@Param注解,最终会被放进请求Body体里
    • 方法参数中URI、feign.Request.Options类型除外,他俩不用注解
  • 若你@Body既想用模版,@RequestLine里也想用模版,那么请务必保证每个方法参数都有@Param注解
请求日志解读

我摘抄出来一条日志进行详细解释,因为是首次所以比较详细,下面就会一带而过了。


@Param

只能标注在方法参数Parameter上。 通过名称定义模板变量,其值将用于填入上面的模版:@Headers/@RequestLine/@Body均可使用模版表达式。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Retention(RUNTIME)
@java.lang.annotation.Target(PARAMETER)
public @interface Param {

	// 名称(key),和模版会进行匹配然后填充 必填项
	String value();
	// 如何把值填充上去,默认是调用其toString方法直接填上去
	Class<? extends Expander> expander() default ToStringExpander.class;
	// 是否转义,默认不转义,直接放上去
	boolean encoded() default false;


  interface Expander {
    String expand(Object value);
  }
  final class ToStringExpander implements Expander {
    @Override
    public String expand(Object value) {
      return value.toString();
    }
  }
}

使用示例

说明:测试此注解的作用,仅需要看看日志的发送即可,并不要求能ping通哦~。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface ParamClient {

    // 1、参数为数组类型
    @RequestLine("GET /feign/demo2?name={name}")
    String testParam(@Param("name") String[] names);

    // 2、参数为List类型
    @RequestLine("GET /feign/demo2?name={name}")
    String testParam2(@Param("name") Collection<String> names);

    // 3、参数值包含特殊字符:? / 这种
    @RequestLine("GET /feign/demo2?name={name}")
    String testParam3(@Param("name") String name);
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void fun2() {
    ParamClient client = FeignClientFactory.create(ParamClient.class);
    client.testParam(new String[]{"YourBatman", "fsx"});
    System.err.println(" ------------------ ");
    client.testParam2(Arrays.asList("1", "2", "3"));
    System.err.println(" ------------------ ");

    client.testParam3("/?YourBatman/");
    System.err.println(" ------------------ ");
}

运行程序打印情况:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
GET http://localhost:8080/feign/demo2?name=%5BLjava.lang.String&name=@19bb089b HTTP/1.1
...
GET http://localhost:8080/feign/demo2?name=1&name=2&name=3 HTTP/1.1
...
GET http://localhost:8080/feign/demo2?name=%2F%3FYourBatman%2F HTTP/1.1

可以看到,如果是Collection类型是能够很好的被解析成多值的,但是数组不行,因此多用集合少用数组哦(数组直接调用toString()方法了)。


@Headers

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Target({METHOD, TYPE})
@Retention(RUNTIME)
public @interface Headers {
  String[] value();
}

能标注在类上和方法上。用于传请求头,使用起来比较简单,形如这样即可:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Headers({"Accept:*/*", "Accept-Language:zh-cn"})

唯一注意的一点:k-v使用的是:链接,而不是=


@QueryMap

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Retention(RUNTIME)
@java.lang.annotation.Target(PARAMETER)
public @interface QueryMap {
  boolean encoded() default false;
}

只能标注在方法参数上。用于传递多个查询值,拼接在URL后面,上面已经给出示例了,本处略。 仅需注意一点:只能标注在Map类型的参数前面,否则报错。


@HeaderMap

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Retention(RUNTIME)
@java.lang.annotation.Target(PARAMETER)
public @interface HeaderMap {
}

同上,只是用在Header上而已


@Body

它只能标注在方法上

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Target(METHOD)
@Retention(RUNTIME)
public @interface Body {
  String value();
}

比如:@Body("{body}"),这样就可以通过方法参数的@Param("body") String body传值喽。注意:这个值最终是以http body体的形式发送的(并非URL参数哦),body体的内容并不要求必须是json,一般请配合请求头使用。


使用示例

准备一个POJO:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Getter
@Setter
@ToString
public class Person {
    private String name = "YourBatman";
    private Integer age = 18;
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface BodyClient {

    // 1、@Body里可以是写死的字符串
    @Body("{\"name\" : \"YourBatman\"}")
    @RequestLine("POST /feign/demo3")
    String testBody();

    // 2、@Body可以使用模版{} 取值
    @Body("{body}")
    @RequestLine("POST /feign/demo3")
    String testBody2(@Param("body") String name);

    // 3、@Body里取值来自于一个JavaBean
    @Body("{person}")
    @RequestLine("POST /feign/demo3")
    String testBody3(@Param("person") Person person);
}

测试程序:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void fun3() {
    BodyClient client = FeignClientFactory.create(BodyClient.class);
    client.testBody();
    System.err.println(" ------------------ ");
    client.testBody2("my name is YourBatman");
    System.err.println(" ------------------ ");
    client.testBody3(new Person());
}

运行,控制台打印如下(只摘抄主要信息):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[BodyClient#testBody] ---> POST http://localhost:8080/feign/demo3 HTTP/1.1
[BodyClient#testBody] Content-Length: 23
[BodyClient#testBody] 
[BodyClient#testBody] {"name" : "YourBatman"}
[BodyClient#testBody] ---> END HTTP (23-byte body)
...
 ------------------ 
[BodyClient#testBody2] ---> POST http://localhost:8080/feign/demo3 HTTP/1.1
[BodyClient#testBody2] Content-Length: 21
[BodyClient#testBody2] 
[BodyClient#testBody2] my name is YourBatman
[BodyClient#testBody2] ---> END HTTP (21-byte body)
 ------------------ 
[BodyClient#testBody3] ---> POST http://localhost:8080/feign/demo3 HTTP/1.1
[BodyClient#testBody3] Content-Length: 31
[BodyClient#testBody3] 
[BodyClient#testBody3] Person(name=YourBatman, age=18)
[BodyClient#testBody3] ---> END HTTP (31-byte body)
...

可以看到body里是可以是任意格式的数据的,包括POJO(只不过默认是调用它的toString方法而已~)。

说明:Feign默认情况下只能支持文本消息,但后来feign提供了feign-form这个扩展模块,所以也就能够支持二进制、文件上传喽。 需要说明的是:feign-form并不属于官方直接子模块,是后续新增的所以它的大版本号不跟主版本号走,GAV也有所不同:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// feign-form和feign-form-spring共用一个父工程,版本号保持一致
// feign-form-spring依赖于feign-form工程

<dependency>
    <groupId>io.github.openfeign.form</groupId>
    <artifactId>feign-form</artifactId>
    <!-- <artifactId>feign-form-spring</artifactId> -->
    <version>3.8.0</version>
</dependency>

Spring Cloud的Feign除了导入了core包,也导入了feign-form-spring(包含feign-form),所以默认也是支持到了二进制数据传递的

关于POJO那个Person对象为何最终调用的是toString()而非序列化成了一个JSON,这和RequestTemplate的构建有关。以及为何在Spring Cloud下是能成为JSON的,这些原因后文会分解。。。


总结

关于原生Feign的原生注解就讲解到这了,还是蛮有意思的。总体来说这些原生注解使用起来并不难,它的语法规范遵循的是RFC6570规范,这是区别于Spring MVC的(它是Ant规范)。

声明

原创不易,码字不易,多谢你的点赞、收藏、关注。把本文分享到你的朋友圈是被允许的,但拒绝抄袭

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
[享学Feign] 十、Feign通过feign-jackson模块天然支持POJO的编码和解码
上文介绍了Feign的Client相关模块,体验到Feign核心内容的高扩展性同时,亦能明显感觉到其子模块其实为对Feign核心功能的延伸,让其更能适应复杂的生产环境要求。
YourBatman
2020/02/21
6K0
[享学Feign] 五、原生Feign的编码器Encoder、QueryMapEncoder
代码下载地址:https://github.com/f641385712/feign-learning
YourBatman
2020/02/21
8.9K0
[享学Feign] 五、原生Feign的编码器Encoder、QueryMapEncoder
[享学Feign] 六、原生Feign的解码器Decoder、ErrorDecoder
代码下载地址:https://github.com/f641385712/feign-learning
YourBatman
2020/02/21
19.4K0
[享学Feign] 六、原生Feign的解码器Decoder、ErrorDecoder
[享学Feign] 九、Feign + OkHttp和Feign + Apache HttpClient哪个更香?
代码下载地址:https://github.com/f641385712/feign-learning
YourBatman
2020/02/21
6.4K0
[享学Feign] 九、Feign + OkHttp和Feign + Apache HttpClient哪个更香?
[享学Feign] 四、原生Feign的核心API详解(二):Contract、SynchronousMethodHandler...
代码下载地址:https://github.com/f641385712/feign-learning
YourBatman
2020/02/21
3.9K0
[享学Feign] 四、原生Feign的核心API详解(二):Contract、SynchronousMethodHandler...
[享学Feign] 一、原生Feign初体验,Netflix Feign or Open Feign?
代码下载地址:https://github.com/f641385712/feign-learning
YourBatman
2020/02/21
5.6K0
[享学Feign] 一、原生Feign初体验,Netflix Feign or Open Feign?
Feign实现文件上传下载
Feign框架对于文件上传消息体格式并没有做原生支持,需要集成模块feign-form来实现。
编程随笔
2022/04/29
1.3K0
[享学Feign] 三、原生Feign的核心API详解(一):UriTemplate、HardCodedTarget...
代码下载地址:https://github.com/f641385712/feign-learning
YourBatman
2020/02/21
4.3K0
[享学Feign] 三、原生Feign的核心API详解(一):UriTemplate、HardCodedTarget...
Feign-声明式java Http客户端
Feign 是Netfilx开源的一个声明web服务客户端,这便得编写web服务客户端更容易,使用Feign 创建一个接口并对它进行注解,它具有可插拔的注解支持包括Feign注解与JAX-RS注解,Feign还支持可插拔的编码器与解码器,Spring Cloud 增加了对 Spring MVC的注解,Spring Web 默认使用了HttpMessageConverters, Spring Cloud 集成 Ribbon 和 Eureka 提供的负载均衡的HTTP客户端 Feign
kl博主
2018/04/13
4K0
[享学Feign] 十一、Feign通过feign-slf4j模块整合logback记录日志
代码下载地址:https://github.com/f641385712/feign-learning
YourBatman
2020/02/21
5.2K0
[享学Feign] 十一、Feign通过feign-slf4j模块整合logback记录日志
快捷实现http客户端神器-feign(私人定制扩展篇)
Feign允许我们通过注解的方式实现http客户端的功能,Feign能用最小的性能开销,让我们调用web服务器上基于文本的接口。同时允许我们自定义编码器、解码器和错误处理器等等
lyb-geek
2019/07/22
2.8K0
快捷实现http客户端神器-feign(私人定制扩展篇)
Feign实现动态URL
动态URL的需求场景: 有一个异步服务S,它为其他业务(业务A,业务B...)提供异步服务接口,在这些异步接口中执行完指定逻辑之后需要回调相应业务方的接口。
编程随笔
2022/04/29
2.8K0
Feign实现动态URL
Feign上传文件
今天给大家介绍下在Feign中如何调用文件上传接口,进行文件上传操作。 这边文章讲的Feign不是Spring Cloud Feign,是原始Feign的使用。 在一些比较老的,不是Spring Cloud的项目中,我们也可以用Feign来进行接口的调用。 关于Feign的使用可以参考我的这篇文章:如何优雅的使用Feign调用接口 使用Feign来上传文件,首先你得有一个上传文件的接口,我们假设上传地址如下: POST http://localhost:8080/file/upload 参数的话就一个fil
猿天地
2018/04/03
1.6K0
我用 Dubbo 传输文件,差点被开除。。。
点击上方“芋道源码”,选择“设为星标” 管她前浪,还是后浪? 能浪的浪,才是好浪! 每天 10:33 更新文章,每天掉亿点点头发... 源码精品专栏 原创 | Java 2021 超神之路,很肝~ 中文详细注释的开源项目 RPC 框架 Dubbo 源码解析 网络应用框架 Netty 源码解析 消息中间件 RocketMQ 源码解析 数据库中间件 Sharding-JDBC 和 MyCAT 源码解析 作业调度中间件 Elastic-Job 源码解析 分布式事务中间件 TCC-Transaction
芋道源码
2022/07/06
3930
我用 Dubbo 传输文件,差点被开除。。。
非Spring环境下的Ribbon+Feign使用宝典
Ribbon是一个负载均衡客户端,可以很好的控制http和tcp的一些行为,一般都是Ribbon搭配Feign一起使用;Feign默认集成了ribbon
白石
2019/08/23
1.3K0
[享学Feign] 八、Feign是如何生成接口代理对象的?Feign实例的构建器Feign.Builder详解
代码下载地址:https://github.com/f641385712/feign-learning
YourBatman
2020/02/21
7.2K0
每天20分钟之feign
feign对各类http调用包进行了抽象,我们不必自己去调用http包,feign进行了封装
李子健
2022/07/24
2320
同事使用 Dubbo 传输文件,被点名批评!
公司之前有一个 Dubbo 服务,其内部封装了腾讯云的对象存储服务 SDK,目的是统一管理这种三方服务的SDK,其他系统直接调用这个对象存储的 Dubbo 服务。这样可以避免因平台 SDK 出现不兼容的大版本更新,从而导致公司所有系统修改跟着升级的问题。
业余草
2021/12/06
3930
同事使用 Dubbo 传输文件,被点名批评!
SpringCloud原理之feign
前面一节我们学习了一下eureka,我们来回顾一下,首先它是一个cs架构,分为客户端和服务端,
用户9927510
2022/07/29
6550
SpringCloud原理之feign
Spring Cloud-Feign设计原理
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://louluan.blog.csdn.net/article/details/82821294
亦山
2019/05/25
2.7K0
推荐阅读
相关推荐
[享学Feign] 十、Feign通过feign-jackson模块天然支持POJO的编码和解码
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验