最少的配置(使用默认配置)
最少/默认配置示例如下(使用Nacos作为服务的注册与发现中心):
- application.properties
server.port=8082
spring.application.name=nacos-consumer
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.cloud.nacos.discovery.enabled=true
spring.cloud.nacos.username=nacos
spring.cloud.nacos.password=nacos
#开启热部署
spring.devtools.restart.enabled=true
- 主启动类
package com.xl.projects;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class NacosConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(NacosConsumerApplication.class, args);
}
}
注意! 以上需添加注解@EnableFeignClients
- @FeignClient接口
package com.xl.projects.feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(name = "nacos-provider")
public interface TestConsumerFeign {
/**
* 注意!!!,这里需要显示的指定@RquestParam,否者调用的时候会报错!
* @param param
* @return
*/
@GetMapping("/provider/test")
String invokeProvider(@RequestParam String param);
}
说明 :
- 编写测试Controller,调用@FeignClient接口,从而调用服务提供者nacos-provider的服务
package com.xl.projects.controller;
import javax.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.xl.projects.feign.TestConsumerFeign;
@RestController
public class TestConsumerController {
@Resource
private TestConsumerFeign testConsumerFeign;
@GetMapping("/consumer/invoke")
public String testInovke() {
return testConsumerFeign.invokeProvider("cosuming now!!!");
}
}
说明 :
-
测试,访问http://localhost:8082/consumer/invoke
使用OpenFeign调用成功:
如何自定义配置,或者叫重写默认配置
见官网 :
https://docs.spring.io/spring-cloud-openfeign/docs/current/reference/html/#spring-cloud-feign-overriding-defaults
可以通过@EnableFeignClients的属性defaultConfiguration 来指定使用哪一种配置方式:java代码配置还是配置文件配置
第一种方式,使用Java代码完成自定义/重写
- 示例说明,重写编写一个@FeignClient客户端JustForTestFeign 以及配置类FooConfiguration
JustForTestFeign
package com.xl.projects.feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(contextId = "sameNameDifferentId",name="nacos-provider",configuration=FooConfiguration.class)
public interface JustForTestFeign {
@GetMapping("/provider/test")
public String justTest(@RequestParam String param);
}
FooConfiguration
package com.xl.projects.feign;
import org.springframework.context.annotation.Bean;
import feign.Contract;
public class FooConfiguration {
/**
* 配置Builder
* @return
*/
@Bean
@Scope("prototype")
public Feign.Builder feignBuilder() {
System.out.println("<<<<<<<<<<<<<<<<<<<<<<<<<<< feign自定义配置<<<<<<<<<<<<<<<<<<<<<<<<<<<");
return Feign.builder();
}
}
FooConfiguration does not need to be annotated with @Configuration. However, if it is, then take
care to exclude it from any @ComponentScan that would otherwise include this configuration as it
will become the default source for feign.Decoder, feign.Encoder, feign.Contract, etc., when
specified. This can be avoided by putting it in a separate, non-overlapping package from any
@ComponentScan or @SpringBootApplication, or it can be explicitly excluded in @ComponentScan.
以上英文原文说明如下:
配置类FooConfiguration 上可以不加@Configuration注解:项目在加载@FeignClient客户端时,如果配置了属性configuration=FooConfiguration.class,那么FooConfiguration 会被自动加载并且会加载FooConfiguration 中配置的@Bean方法生成配置实例。
测试: 编写测试类如下,
package com.xl.projects.controller;
import javax.annotation.Resource;
import org.springframework.web.bind.annotation.RestController;
import com.xl.projects.feign.JustForTestFeign;
@RestController
public class TestConsumerController {
/**
* 注入Feign客户端/Client,项目启动时会去加载JustForTestFeign及对应的配置类FooConfiguration
*/
@Resource
private JustForTestFeign justForTestFeign;
// @Resource
// private TestConsumerFeign testConsumerFeign;
//
// @GetMapping("/consumer/invoke")
// public String testInovke() {
// return testConsumerFeign.invokeProvider("cosuming now!!!");
// }
// @GetMapping("/consumer/invoke")
// public String testInovke() {
// return justForTestFeign.justTest("cosuming now!!!");
// }
}
启动项目:
但是,如果FooConfiguration 类加了@Configuration注解会有什么问题呢?如何避免/解决呢? :
问题 : 加了@Configuration注解并且FooConfiguration 类是在@ComponentScan注解扫描路径下,那么Feign的feign.Decoder, feign.Encoder, feign.Contract的默认配置将来源于FooConfiguration 类(前提是指定了对应的配置)
解决:方法一,将FooConfiguration 类放在@ComponentScan or @SpringBootApplication注解扫描的包路径之外,或者在@ComponentScan注解中显示的排除FooConfiguration 类。
第二种方式,使用配置文件
形如:
spring:
cloud:
openfeign:
client:
config:
feignName:
url: http://remote-service.com
connectTimeout: 5000
readTimeout: 5000
loggerLevel: full
errorDecoder: com.example.SimpleErrorDecoder
retryer: com.example.SimpleRetryer
defaultQueryParameters:
query: queryValue
defaultRequestHeaders:
header: headerValue
requestInterceptors:
- com.example.FooRequestInterceptor
- com.example.BarRequestInterceptor
responseInterceptor: com.example.BazResponseInterceptor
dismiss404: false
encoder: com.example.SimpleEncoder
decoder: com.example.SimpleDecoder
contract: com.example.SimpleContract
capabilities:
- com.example.FooCapability
- com.example.BarCapability
queryMapEncoder: com.example.SimpleQueryMapEncoder
micrometer.enabled: false
两种方式的比较
前提知识:
- 一个项目中可以使用多个@FeignClient(name值不一样)接口调用不同的服务提供者
- 如下
一个项目中也可以有多个带@FeignClient注解的接口调用同一个服务提供者,即是
@FeignClient的名字name可以相同,但是必须要有contextId。如果没有配置
contextId,项目启动时会报错!
官方解释:
If we want to create multiple feign clients with the same name or url so
that they would point to the same server but each with a different custom
configuration then we have to use contextId attribute of the @FeignClient
in order to avoid name collision of these configuration beans.
@FeignClient(contextId = "fooClient", name = "stores", configuration = FooConfiguration.class)
public interface FooClient {
//..
}
@FeignClient(contextId = "barClient", name = "stores", configuration = BarConfiguration.class)
public interface BarClient {
//..
}
java代码方式:可以针对每一个@FeignClient接口作定制化配置,只需要编写不同的配置类,然后配置到@FeignClien的属性configuration中即可
配置文件的方式:针对所有的@FeignClient接口。
同时使用,默认情况下,配置文件方式会覆盖java代码方式,当然,也可以更改这种优先级。