39

@FeignClient(name = "test", url="http://xxxx")

如何在运行时更改 feign URL (url="http://xxxx")?因为 URL 只能在运行时确定。

4

8 回答 8

37

您可以添加一个未注释的 URI 参数(可能在运行时确定),这将是用于请求的基本路径。例如:

    @FeignClient(name = "dummy-name", url = "https://this-is-a-placeholder.com")
    public interface MyClient {
        @PostMapping(path = "/create")
        UserDto createUser(URI baseUrl, @RequestBody UserDto userDto);
    }

然后用法将是:

    @Autowired 
    private MyClient myClient;
    ...
    URI determinedBasePathUri = URI.create("https://my-determined-host.com");
    myClient.createUser(determinedBasePathUri, userDto);

这将向( source )发送POST请求。https://my-determined-host.com/create

于 2018-11-27T16:41:54.487 回答
24

Feign 有一种方法可以在运行时提供动态 URL 和端点。

必须遵循以下步骤:

  1. FeignClient界面中,我们必须删除 URL 参数。我们必须使用@RequestLine注解来提及 REST 方法(GET、PUT、POST 等):
@FeignClient(name="customerProfileAdapter")
public interface CustomerProfileAdaptor {

    // @RequestMapping(method=RequestMethod.GET, value="/get_all")
    @RequestLine("GET")
    public List<Customer> getAllCustomers(URI baseUri); 
 
    // @RequestMapping(method=RequestMethod.POST, value="/add")
    @RequestLine("POST")
    public ResponseEntity<CustomerProfileResponse> addCustomer(URI baseUri, Customer customer);
 
    @RequestLine("DELETE")
    public ResponseEntity<CustomerProfileResponse> deleteCustomer(URI baseUri, String mobile);
}
  1. 在 RestController 你必须导入 FeignClientConfiguration
  2. 您必须编写一个带有编码器和解码器作为参数的 RestController 构造函数。
  3. 你需要FeignClient用编码器、解码器来构建。
  4. 调用FeignClient方法时,提供 URI(BaserUrl + 端点)以及其他调用参数(如果有)。
@RestController
@Import(FeignClientsConfiguration.class)
public class FeignDemoController {

    CustomerProfileAdaptor customerProfileAdaptor;

    @Autowired
    public FeignDemoController(Decoder decoder, Encoder encoder) {
        customerProfileAdaptor = Feign.builder().encoder(encoder).decoder(decoder) 
           .target(Target.EmptyTarget.create(CustomerProfileAdaptor.class));
    }

    @RequestMapping(value = "/get_all", method = RequestMethod.GET)
    public List<Customer> getAllCustomers() throws URISyntaxException {
        return customerProfileAdaptor
            .getAllCustomers(new URI("http://localhost:8090/customer-profile/get_all"));
    }

    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public ResponseEntity<CustomerProfileResponse> addCustomer(@RequestBody Customer customer) 
            throws URISyntaxException {
        return customerProfileAdaptor
            .addCustomer(new URI("http://localhost:8090/customer-profile/add"), customer);
    }

    @RequestMapping(value = "/delete", method = RequestMethod.POST)
    public ResponseEntity<CustomerProfileResponse> deleteCustomer(@RequestBody String mobile)
            throws URISyntaxException {
        return customerProfileAdaptor
            .deleteCustomer(new URI("http://localhost:8090/customer-profile/delete"), mobile);
    }
}
于 2018-07-18T14:30:31.053 回答
9

使用 feign.Target.EmptyTarget

@Bean
public BotRemoteClient botRemoteClient(){
    return Feign.builder().target(Target.EmptyTarget.create(BotRemoteClient.class));
}

public interface BotRemoteClient {

    @RequestLine("POST /message")
    @Headers("Content-Type: application/json")
    BotMessageRs sendMessage(URI url, BotMessageRq message);
}

botRemoteClient.sendMessage(new URI("http://google.com"), rq)
于 2020-10-15T15:40:02.060 回答
9

我不知道您是否使用弹簧依赖于多个配置文件。例如:like(dev,beta,prod 等等)

如果您依赖于不同的 yml 或属性。您可以定义FeignClient如下:(@FeignClient(url = "${feign.client.url.TestUrl}", configuration = FeignConf.class)

然后

定义

feign:
  client:
    url:
      TestUrl: http://dev:dev

在你的 application-dev.yml

定义

feign:
  client:
    url:
      TestUrl: http://beta:beta

在您的 application-beta.yml 中(我更喜欢 yml)。

……

感谢上帝。享受。

于 2019-01-31T07:54:29.877 回答
5

您可以手动创建客户端:

@Import(FeignClientsConfiguration.class)
class FooController {

    private FooClient fooClient;

    private FooClient adminClient;

    @Autowired
    public FooController(ResponseEntityDecoder decoder, SpringEncoder encoder, Client client) {
        this.fooClient = Feign.builder().client(client)
            .encoder(encoder)
            .decoder(decoder)
            .requestInterceptor(new BasicAuthRequestInterceptor("user", "user"))
            .target(FooClient.class, "http://PROD-SVC");
        this.adminClient = Feign.builder().client(client)
            .encoder(encoder)
            .decoder(decoder)
            .requestInterceptor(new BasicAuthRequestInterceptor("admin", "admin"))
            .target(FooClient.class, "http://PROD-SVC");
     }
}

请参阅文档:https ://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-feign.html#_creating_feign_clients_manually

于 2017-05-04T09:05:32.490 回答
3

在界面中,您可以通过 Spring 注释更改 url。基础 URI 在 yml Spring 配置中配置。

   @FeignClient(
            name = "some.client",
            url = "${some.serviceUrl:}",
            configuration = FeignClientConfiguration.class
    )

public interface SomeClient {

    @GetMapping("/metadata/search")
    String search(@RequestBody SearchCriteria criteria);

    @GetMapping("/files/{id}")
    StreamingResponseBody downloadFileById(@PathVariable("id") UUID id);

}
于 2019-06-21T10:13:34.963 回答
-1

我更喜欢通过配置构建 feign 客户端以在运行时传递一个 url(在我的情况下,我从 consul 发现服务中通过服务名称获取 url)

所以我扩展了 feign 目标类如下:

public class DynamicTarget<T> implements Target<T> {
private final CustomLoadBalancer loadBalancer;
private final String serviceId;
private final Class<T> type;

public DynamicTarget(String serviceId, Class<T> type, CustomLoadBalancer loadBalancer) {
    this.loadBalancer = loadBalancer;
    this.serviceId = serviceId;
    this.type = type;
}

@Override
public Class<T> type() {
    return type;
}

@Override
public String name() {
    return serviceId;
}

@Override
public String url() {
    return loadBalancer.getServiceUrl(name());
}

@Override
public Request apply(RequestTemplate requestTemplate) {
    requestTemplate.target(url());
    return requestTemplate.request();
}
}


 var target = new DynamicTarget<>(Services.service_id, ExamsAdapter.class, loadBalancer);
于 2022-01-30T22:35:31.257 回答
-2
                package commxx;

                import java.net.URI;
                import java.net.URISyntaxException;

                import feign.Client;
                import feign.Feign;
                import feign.RequestLine;
                import feign.Retryer;
                import feign.Target;
                import feign.codec.Encoder;
                import feign.codec.Encoder.Default;
                import feign.codec.StringDecoder;

                public class FeignTest {

                    public interface someItfs {

                 
                        @RequestLine("GET")
                        String getx(URI baseUri);
                    }

                    public static void main(String[] args) throws URISyntaxException {
                        String url = "http://www.baidu.com/s?wd=ddd";  //ok..
                        someItfs someItfs1 = Feign.builder()
                                // .logger(new FeignInfoLogger()) // 自定义日志类,继承 feign.Logger
                                // .logLevel(Logger.Level.BASIC)// 日志级别
                                // Default(long period, long maxPeriod, int maxAttempts)
                                .client(new Client.Default(null, null))// 默认 http
                                .retryer(new Retryer.Default(5000, 5000, 1))// 5s超时,仅1次重试
                            //  .encoder(Encoder)
                            //  .decoder(new StringDecoder())
                                .target(Target.EmptyTarget.create(someItfs.class));

                //       String url = "http://localhost:9104/";
                //         
                        System.out.println(someItfs1.getx(new URI(url)));
                    }

                }
于 2020-11-20T18:03:53.607 回答