@FeignClient(name = "test", url="http://xxxx")
在运行时,如何更改假un(url =" http://xxxx"(?因为只能在运行时确定URL。
您可以添加一个未注释的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);
这将发送POST
请求到https://my-determined-host.com/create
(源(。
feign可以在运行时提供动态URL和端点。
必须遵循以下步骤:
- 在
FeignClient
接口中,我们必须删除URL参数。我们必须使用@RequestLine
注释来提及其余方法(获取,放置,发布等(:
@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);
}
- 在RestController中,您必须导入FeignClientConfiguration
- 您必须用编码器和解码器作为参数编写一个RestController构造函数。
- 您需要使用编码器,解码器构建
FeignClient
。 - 在调用
FeignClient
方法时,请提供URI(baserurl 端点(以及REST调用参数(如果有(。
@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);
}
}
我不知道您是否使用Spring取决于多个配置文件。例如:喜欢(开发,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(。
......
谢谢上帝。
使用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)
您可以手动创建客户端:
@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-cloud-feign.html#_creating_feign_feign_feign_feign_feign_clients_meraly
接口中您可以通过弹簧注释更改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);
}
一种简单的方法是使用interceptor:requestInterceptor
假装如果您在Interceptor中设置了目标主机:
将替换目标URL。 // source code of feign
Request targetRequest(RequestTemplate template) {
for (RequestInterceptor interceptor : requestInterceptors) {
interceptor.apply(template);
}
return target.apply(template);
}
public Request apply(RequestTemplate input) {
if (input.url().indexOf("http") != 0) {
input.target(url());
}
return input.request();
}
自定义拦截器:
public class DynamicFeignUrlInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
if (isNotDynamicPath(template)) {
return;
}
template.target(getHost());
}
private boolean isNotDynamicPath(RequestTemplate template) {
// TODO Determine whether it is dynamic according to your logic
return false;
}
private String getHost() {
// use any host you want, host must be contained key word of 'http'
return "http://example.com";
}
}
这样的优点是,如果已经有大量的假端代码,则可以在不修改代码的情况下实现。
@Service
@FeignClient(name = "otherservicename", decode404 = true)
public interface myService {
@RequestMapping(method = RequestMethod.POST, value = "/basepath/{request-path}")
ResponseEntity<String> getResult(@RequestHeader("Authorization") String token,
@RequestBody HashMap<String, String> reqBody,
@PathVariable(value = "request-path") String requestPath);
}
然后从服务中,构建动态URL路径并发送请求:
String requestPath = "approve-req";
ResponseEntity<String> responseEntity = myService.getResult(
token, reqBody, requestPath);
您的请求URL将在:&quot; basepath/onerve-req&quot;
我更喜欢通过配置来构建假装客户端以在运行时传递URL(在我的情况下,我从领事发现服务中获得服务名称(
所以我将假装目标类扩展如下:
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);
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)));
}
}