背景:
跨境支付行业下游需要对接很多个下发渠道,每个渠道的对接方式和接口、参数、逻辑都有所不同。各自需要一个独立的对接渠道的服务。
简单流程图:
知识点:
- WebClient
SpringWebFlux下面的一个功能模块。
是响应式编程的一个小小体现。
响应式编程定义:
在计算机领域,响应式编程是一个专注于数据流和变化传递的异步编程范式。
编程范式定义:
编程是为了解决问题,而解决问题可以有多种视角和思路,其中具有普适性的模式被归结为范式。 面向对象、面向过程都是编程范式。
响应式编程是一种从数据流和变化出发的解决问题的模式。 响应式编程,本质上是对数据流或某种变化所作出的反应,但是这个变化什么时候发生是未知的,所以是基于异步、回调的方式在处理问题。
配置:
implementation 'org.springframework.boot:spring-boot-starter-webflux:2.3.0.RELEASE'
@Bean
public WebClient getWebClient() {
TcpClient tcpClient = TcpClient
.create()
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectTimeOut)
.doOnConnected(connection -> {
connection.addHandlerLast(new ReadTimeoutHandler(readTimeout, TimeUnit.MILLISECONDS));
connection.addHandlerLast(new WriteTimeoutHandler(writeTimeout, TimeUnit.MILLISECONDS));
});
WebClient webClient = WebClient.builder()
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.clientConnector(new ReactorClientHttpConnector(HttpClient.from(tcpClient)))
.build();
return webClient;
}
通用方法
public WebClient.ResponseSpec post(String url, String bodyData, String token) {
WebClient.ResponseSpec responseSpec = webClient.method(HttpMethod.POST)
.uri(url)
.header("Authorization", "Bearer " + token)
.header("partnerkey", eastWestBankPropertyConfig.getPartnerkey())
.header("x-correlation-id", "ew-" + idWorker.nextId())
.contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(bodyData))
.retrieve();
return responseSpec;
}
public WebClient.ResponseSpec postToken(String url, MultiValueMap<String, String> formData) {
return webClient.method(HttpMethod.POST)
.uri(url)
.contentType(MediaType.APPLICATION_FORM_URLENCODED).body(BodyInserters.fromFormData(formData))
.retrieve();
}
同步调用
private SubAccountOpenResponse postOpenSubAccount(SubAccountOpenRequest subAccountOpenRequest, EastWestBankPropertyConfig eastWestBankPropertyConfig, String token) {
return webClientUtil.post(eastWestBankPropertyConfig.getSubAccountOpenUrl(), commonService.buildCommonRequestParam(subAccountOpenRequest), token)
.bodyToMono(SubAccountOpenResponse.class).onErrorResume(Mono::error).block();
}
- RabbitMQ
- Mock
Mock渠道API文档的demo数据,方便测试,不影响交易系统的正常测试进度。
json数据存到.json文件里面,然后IO读取返回,开关控制。
private JSONObject parseJsonFromFile() {
JSONObject jsonResult = new JSONObject();
try {
File jsonFile = ResourceUtils.getFile("classpath:MockData.json");
String json = FileUtil.readAsString(jsonFile);
jsonResult = JSON.parseObject(json);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return jsonResult;
}
注入
private final MockData mockData;
@Autowired
public TradeService(WebClientUtil webClientUtil, CommonService<T> commonService, MockData mockData) {
this.webClientUtil = webClientUtil;
this.commonService = commonService;
this.mockData = mockData;
}
- 全局异常处理
@ControllerAdvice
@ExceptionHandler(WebClientResponseException.class)
总结:
未来可以整理一个通用的脚手架,简单的标准、模型。