背景:与第三方系统对接时通常需要建立一个中转站,而中转站负责统一去调用第三方接口服务;
而自身的系统业务就需要通过中转站去调用第三方服务,当涉及的业务越来越多时,自身系统与中专站相互建立的请求接口资源就会越来越多,管理请求的接口就越复杂;根据这个占用资源及接口的管理进行统一的泛化优化,而公共的请求接口则可以在中转站中完成;
首先定义个请求第三方接口的方法:
public interface CommonInvokeHandler {
/**
* 统一方法提交
*
* @param params the params
* @return the string
*/
String invoke(String params);
}
然后再定义一个容器类,将需求请求的第三方接口操作的实例放在其中,以便使用:
public class CommonInvokeContainer {
public static final Map<String, CommonInvokeHandler> CONTAINER = Maps.newConcurrentMap();
public static void register(String apiName, CommonInvokeHandler handler) {
CONTAINER.put(apiName, handler);
}
public static String invoke(String apiName, String params) {
return CONTAINER.get(apiName).invoke(params);
}
}
然后再编写实现此接口及Spring 的InitializingBean接口的抽象类:
/**
BaseInvokeRequest 为请求入参实体基类
BaseInvokeResponse 为返回数据实体基类
*/
public abstract class AbstractCommonInvokeHandler<T extends BaseInvokeRequest,
R extends BaseInvokeResponse> implements CommonInvokeHandler, InitializingBean {
@Override
public String invoke(String params) {
T param = resovle(params);
return toStringResponse(doInvoke(param));
}
/**
* 将返回数据转string
*
* @param result the result
* @return the string
*/
protected String toStringResponse(R result) {
// default with fast json
return JSON.toJSONString(result);
}
/**
* 执行第三方请求接口
*
* @param param the param
* @return the r
*/
protected abstract R doInvoke(T param);
/**
* 将请求参数统一转换成第三方入参
*
* @param params the params
* @return the t
*/
protected abstract T resovle(String params);
@Override
public void afterPropertiesSet() throws Exception {
CommonInvokeContainer.register(getApiName(),this);
}
/**
* 根据定义的名称获取对应实例(自定义名称可统一使用枚举类型维护)
*
* @return the api name
*/
protected abstract String getApiName();
}
然后需要实现具体第三方接口的业务便可继承此抽象类
@Component
public class XXXQueryHandler extends AbstractCommonInvokeHandler<XXXQueryRequest, XXXQueryResponse> {
@Autowired
private XXXTransfer XXXTransfer;
@Override
protected XXXQueryResponse doInvoke(XXXQueryRequest param) {
if(param == null){
return null;
}
Response<List<XXXInfoDTO>> XXXInfo = XXXTransfer.findXXXInfo(param.getIds());
if (XXXInfo == null || CollectionUtils.isEmpty(XXXInfo.getData()) ||
!Response.SUCCESS_CODE.equals(XXXInfo.getStatusCode())) {
return null;
}
XXXQueryResponse response = new XXXQueryResponse();
response.setXXXInfoDTOS(XXXInfo.getData());
return response;
}
@Override
protected XXXQueryRequest resovle(String params) {
if(StringUtils.isBlank(params)){
return null;
}
XXXQueryRequest request = JSON.parseObject(params, XXXQueryRequest.class);
return queryRequest;
}
@Override
protected String getApiName() {
return CommonEnum.XXX_QUERY.getApiName();
}
}
以上便可根据Spring 的InitializingBean接口完成自定义实例化Bean完成第三方业务的请求优化;
扩展:
Java JNDI: 在环境启动时加载本地自定义配置;或者使用 java agen 方式
类似于在一个中心注册一个东西,以后要用的时候,只需要根据名字去注册中心查找,注册中心返回你要的东西。
web程序,我们可以将一些东西(比如数据库相关的)交给服务器软件去配置和管理(有全局配置和单个web程序的配置),
在程序代码中只要通过名称查找就能得到我们注册的东西,而且如果注册的东西有变,比如更换了数据库,我们只需要修改注册信息,名称不改,因此代码也不需要修改;
--------------------------------------------------
spring 在容器启动时加载本地自定义配置时可使用Spring ApplicationRunner接口或者 Spring InitializingBean 接口等;