前言:
在微服务盛行的今天,做接口开发请求第三方服务的接口,大概率会用feign做请求,而feign也是最常用的一种rpc框架;
这里主要是说明在进行feign请求的时候,第三方服务的url和接口也是可以通过读取配置文件的配置,来进行请求的;
至于为什么要把接口和url写在配置中呢,其实也是看需求了;
若是该接口是作为基础服务可能会请求多个第三方使用(我们就是不同分支的代码作为独立项目部署,请求不同的客户接口),不同客户的接口地址可能不同,此时就需要做成配置方式;
若是不常改动,其实也没必要做成配置了;
常用方式:
通常我们是这么请求第三方接口的:(用feign方式)
@FeignClient(name = "feignCustomerService", url = "${customer.url}",configuration = FeignClientConfig.class)
public interface FeignCustomerService {
/**
* 请求客户的接口
*/
@RequestMapping(value = "order/update", method = RequestMethod.POST)
@Headers(value = "Content-Type: application/json")
OrderHttpResponse updateOrder(@RequestBody OrderUpdateDTO orderUpdateDTO);
}
说明:
请求客户的url是读取的配置文件中的值,
调用客户的具体的目标方法是:order/update 这个方法
我们配置文件(yml文件):
# 请求客户,客户的接口配置
customer:
url: http://127.0.0.1:8888/
这样的话,最终请求客户这个接口的url就是:
http://127.0.0.1:8888/order/update
问题来了:
这整个url可以看成两部分,一部分是ip和端口,一部分是请求的路径
第一部分:[http://127.0.0.1:8888/]
第二部分:[order/update]
那其实上面我们已经把第一部分写到配置文件中了,第二部分还是写死在代码中,怎么实现第二部分也在配置中配置呢?
@Value(“”)
这种方式可以读取配置文件中的值,但是我们这里都是feign接口,接口中定义的变量仅可以为static final的,
说白了:就是要interface中的常量必须要初始化的,
这种是动态读取的,达不到我们的要求;
利用@PathVariable注解的特性;
用于接收请求路径中占位符的值
@PathVariable(“xxx”)
通过 @PathVariable 可以将URL中占位符参数{xxx}绑定到处理器类的方法形参中
如:
@RequestMapping(value=”user/{id}/{name}”)
请求路径:http://localhost:8080/hello/show/1/lisi
所以改造下我们的方法:
@FeignClient(name = "feignCustomerService", url = "${customer.url}",configuration = FeignClientConfig.class)
public interface FeignCustomerService {
/**
* 请求客户的接口
*/
@RequestMapping(value = "{apiName}", method = RequestMethod.POST)
@Headers(value = "Content-Type: application/json")
OrderHttpResponse updateOrder(@PathVariable("apiName") String apiName, @RequestBody OrderUpdateDTO orderUpdateDTO);
}
然后在配置文件中增加:
# 请求客户,客户的接口配置
customer:
url: http://127.0.0.1:8888/
updateOrderApiName: order/update
insertOrderApiName: order/insert
然后再增加一个配置类,用于读取该配置:
@Component
@ConfigurationProperties(prefix = "customer")
@Setter
public class FeignConsumerConfig {
public String url;
public String updateOrderApiName;
public String insertOrderApiName;
}
然后就可以这样请求这个feign方法:
@Slf4j
@RestController
@RequestMapping(value = "")
public class TestController {
@Autowired
private FeignCustomerService feignCustomerService;
@Autowired
private FeignConsumerConfig feignConsumerConfig;
@RequestMapping(value = "/testFeign", method = RequestMethod.POST)
public void testFeign() {
OrderUpdateDTO orderUpdateDTO = new OrderUpdateDTO();
orderUpdateDTO.setOrderId(22222);
orderUpdateDTO.setxxx(111111111);
OrderHttpResponse orderHttpResponse = feignCustomerService.updateOrder(feignConsumerConfig.updateOrderApiName,orderUpdateDTO);
log.info("orderHttpResponse :{}",JSONObject.toJSONString(orderHttpResponse));
}
}
其实就是比之前的调用多了一个参数(不影响),而且这个参数会替换到url中去,变相的实现了可配置;
最终的url:
http://127.0.0.1:8888/order/update
缺点:
只是会多一个参数,我觉得不影响,客户那边接收业务参数的话,只需要接收orderUpdateDTO即可,因为我们的业务参数都是写在这个类的,对于客户和我们来说,不影响业务执行;
@FeignClient(name = "feignCustomerService", url = "${customer.url}",configuration = FeignClientConfig.class)
public interface FeignCustomerService {
/**
* 请求客户的接口
*/
@RequestMapping(value = "${customer.updateOrderApiName}", method = RequestMethod.POST)
@Headers(value = "Content-Type: application/json")
OrderHttpResponse updateOrder(@RequestBody OrderUpdateDTO orderUpdateDTO);
}
只要配置文件配置了方法名,那我们这里直接用${}的方式读取就可以了,这也是最简单的一种方式;
建议使用这种;
说明:
看情况使用具体哪种方式:
方式二:适合通用的接口,具体调用哪个接口可能由url决定,也可能由请求体中某一个参数决定,
他们的相同点就是可以公用一个请求体的参数;
方式三:适合不同业务不同调用不同的方法,我们只需要写上这些方法,再请求不同的方法即可。
目前我想到的是这种方式,既可以把url可配置,请求路径也可实现可配置化,
如果有其它方式还请留言多交流;