Feign远程调用
场景:很多时候可能我们需要调用第三方平台,例如OSS、alipay或者是未在注册中心注册的服务,通常我们可以选用RestTemplate来操作,但是有时候我们更想通过Feign的方式来直接调用远程的接口。
# 方式一
application.properties
# 启用Apollo配置开关 在应用启动阶段是否向Spring容器注入被托管的properties文件配置信息。
apollo.bootstrap.enabled=true
# 将Apollo配置加载提到初始化日志系统之前。
apollo.bootstrap.eagerLoad.enabled=true
1
2
3
4
2
3
4
在@FeignClient上声明url
@FeignClient(qualifier = "mytestClient",name = "report-platform-api",path = "/reportApi/qc",url = "${report.api.url}")
public interface MytestClient {
@PostMapping("/list")
Result<List<MytestClientModel>> listQcSiteList(@RequestBody MytestQuery param);
}
1
2
3
4
5
2
3
4
5
# 方式二(旧)
public interface DispatchCodeFeign {
@RequestLine(value = "POST /testcode/fetchCodes")
@Headers("Content-Type: application/json")
DispatchCodeResult<Map<String, DispatchCodeVo>> fetchCodes(URI baseUri, @RequestBody List<DisPatchCodeDto> disPatchCodeDtos);
}
1
2
3
4
5
2
3
4
5
参数说明:
@ReqeustLine:相当于WebMvc中的@RequestMapping
@Headers: 请求头
1.baseUri:需要调用的地址路径
2.disPatchCodeDto:具体的参数
提示
没有使用FeignClient(url="${动态配置}")?
因为在Spring的加载顺序会先加载FeignClient再去加载apollo的配置,所以url不能解析到动态配置的属性,通过Feign原生api的方式来进行动态的传入uri。
方式一已经解决该问题!
@Configuration
public class OmsApiFeignConfig {
/**请求连接超时时间1S**/
private final int CONNECT_TIME_OUT = 1000;
/**请求读取超时时间10S**/
private final int READ_TIME_OUT = 10000;
/**feign command**/
private final String FEIGN_COMMAND = "dispatchCode";
@Bean
public DispatchCodeFeign dispatchCodeFeign(Decoder decoder, Encoder encoder, DispatchCodeFallBack fallback) {
Target<DispatchCodeFeign> target = Target.EmptyTarget.create(DispatchCodeFeign.class, FEIGN_COMMAND);
HystrixFeign.Builder builder = HystrixFeign.builder();
DispatchCodeFeign orderReportFeign = builder
.options(new Request.Options(CONNECT_TIME_OUT, READ_TIME_OUT))
.encoder(encoder)
.decoder(decoder)
.target(target, fallback);
return orderReportFeign;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
需要引用此feign的Service 需要加入注解 @Import(FeignClientsConfiguration.class)
@Service
@Slf4j
@Import(FeignClientsConfiguration.class)
public class DispatchCodeServiceImpl extends AbstractCacheServiceImpl implements IDispatchCodeService {
@Value("${dispatch.code.uri}")
private String dispatchCodeUri;
private URI uri = null;
private final Integer RES_FAIL = 0;
@Autowired
private DispatchCodeFeign dispatchCodeFeign;
@Override
public DispatchCodeVo fetch(DisPatchCodeDto disPatchCodeDto) {
URI uri = getUri();
Long startTime = System.currentTimeMillis();
log.info("地址:{},入参: {}", uri, JSONUtil.toJsonStr(disPatchCodeDto));
DispatchCodeResult<Map<String, DispatchCodeVo>> result = dispatchCodeFeign.fetchCodes(uri, Arrays.asList(disPatchCodeDto));
log.info("耗时:{},返回值: {}", System.currentTimeMillis() - startTime, JSONUtil.toJsonStr(result));
//请求成功
if (isSuccess(result) && Objects.nonNull(result.getData()) && result.getData().containsKey(disPatchCodeDto.getUniqueSequence())) {
return result.getData().get(disPatchCodeDto.getUniqueSequence());
}
return null;
}
private <T> boolean isSuccess(DispatchCodeResult<T> dispatchCodeResult) {
if (Objects.isNull(dispatchCodeResult)) {
return false;
}
if (RES_FAIL.equals(dispatchCodeResult.getCode())) {
return false;
}
return true;
}
private URI getUri() {
if (Objects.isNull(uri) || !dispatchCodeUri.equals(uri.toString())) {
synchronized (DispatchCodeServiceImpl.class) {
if (Objects.isNull(uri) || !dispatchCodeUri.equals(uri.toString())) {
try {
uri = new URI(dispatchCodeUri);
} catch (Exception e) {
log.error("【创建uri发生异常】异常信息: {}", e);
throw new ServiceException(ResultCodeEnum.FAIL);
}
}
}
}
return uri;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55