一步步构建轻量级http-contract客户端

http-client-plus是一个类似于Feign一样的申明式ESB请求代理组件,使用ESB请求代理组件,面向SpringCloud微服务的,老的项目spring3.x也支持.

背景

习惯于玩rpc的同学都知道,透明化调用对客户端来说很高效及方便,同时组件升级和客户端升级(更新下jar版本)本来都是很轻松的事情。而http-client-plus是对XX公司mule-esb-api的简单封装,用于发送http请求到esb,减少代码冗余简化操作,应用代码只需要写个interface的声明即可。

支持特性

1:通过@BeforeRequest注解,支持请求前置处理
2:通过@AfterResponse注解,支持响应后置处理
3:默认实现了响应状态的判断,和返回结果的转换
4:支持void,基本数据类型及其包装类,Object,自定义对象,
    List,List<T>,Map,Future,Future<T>,Future<List>,Future<List<T>>类型的返回
5:支持各式的请求参数
6:提供@HttpParam这种简单的生成Map类型的请求参数的方法
7:支持两种方式的异步请求
    7.1:通过将返回类型设置为Future或ListenableFuture
    7.2:返回类型设置为void,并添加@CallBack回调方法(回调方法的[P param]默认为第一个参数,当然也可以指定其他的)
8:支持ESB(post)和HTTP(get/post)两种请求方式
9:支持自定义请求执行Bean
10:支持防重复提交
11:支持Optional(再也不需要像以前一样写一大堆代码去判断空指针)

基本用法

第一步配置xml

<bean id="httpAdapterPostProcessor" class="com.kxtx.httpadapter.spring.HttpAdapterPostProcessor">
              <property name="annotationClz" value="com.kxtx.httpadapter.core.annotation.KxRequestAgent"></property>
              <property name="basePackages">
                     <list>
                            <value>com.kxtx</value>
                     </list>
              </property>
              <property name="executorDelegatesClzs">
                     <list>
                            <value>com.gillion.esb.api.client.ESBClient</value>
                            <value>com.kxtx.httpadapter.httpClient.KxHttpClient</value>
                     </list>
              </property>
       </bean>

       <!-- 设置异步执行的线程池 -->
       <bean name="threadPoolInstance"
             class="com.kxtx.httpadapter.core.util.ThreadManager"
             factory-method="getThreadPoolInstance">
       </bean>

       <!-- 设置一些属性的配置 -->
       <bean id="requestConfiguration" class="com.kxtx.httpadapter.spring.RequestConfigurationBean">
              <property name="httpUrlPrefix" value="dev-"></property>
              <property name="executorService" ref="threadPoolInstance"></property>
</bean>

第二部配置contract

如何书写申明式请求接口(这里列出最核心的几个使用方法,更多扩展方法,自己探索吧)?

@KxRequestAgent:必须:标记一个class,如果该接口在扫描类下,在项目启动时,会被扫描到,并被动态代理

@AfterResponse:必须:标记一个class或method(你们应该很难用到method级别),被标记的class下的所有方法,在执行完ESB请求后,会执行afterMethods,去进行状态校验和反序列化。其中状态校验的默认实现,建议你们用自己的系统的方法覆盖掉,可以参考Market系统的覆盖类,在文章最后给出

@Request:必须:标记一个method,url填上你想要访问的接口编号即可

@KxRequestParam:可选:如果你要访问的接口参数是key-value格式的,可以使用这个注解,注解内的内容就是key,后面的传递参数会转换成JSON格式的value

~当然,如果你不想使用上面的@KxRequestParam,或者说你很容易就封装一个Map出来,可以直接把Map当成参数即可

~如果你还不满意,想直接使用对象,那也可以,直接传递一个对象,我们会给你封装成JSON格式,放入EBS的请求参数中

~如果你不要返回结果,那简单啊,void就行了

~如果你想要异步请求,也可以,返回结果使用Future即可

~其实还有很多其他的玩法,不过感觉上面的足够你们使用了

@KxRequestAgent
@BeforeRequest(beforeMethods = TestBeforeRequest.class)
@AfterResponse(afterMethods = {DefaultStatusCheckResponseHandle.class, DefaultGenericTypeResponseHandler.class})
public interface TestRequestExecutor {

    @Request(url = "OMS_S_00076_ZL")//esb
    @AfterResponse(afterMethods = TestKosProductAfterResponse.class)
    KosProduct kxRequestParamTest(@KxRequestParam("productUniqueKeyStr") String productUniqueKeyStr);

    @Request(url = "OMS_S_00076_ZL")
    @AfterResponse(overrideMethods = {DefaultStatusCheckResponseHandle.class, DefaultGenericTypeResponseHandler.class, TestAfterResponse.class})
    KosProduct requestBodyTest(QueryParam queryParam);

    @Request(url = "OMS_S_00076_ZL")
    KosProduct mapTest(Map<String, String> param);

    @Request(url = "OMS_S_00076_ZL")
    String stringTest(@KxRequestParam("productUniqueKeyStr") String productUniqueKeyStr);

    @Request(url = "OMS_S_00076_ZL")
    void voidTest(@KxRequestParam("productUniqueKeyStr") String productUniqueKeyStr);

    @Request(url = "MSHIP_S_00135")
    List<OrgInfo> listTest(@KxRequestParam("memberIds") List<String> companyIds);

    @Request(url = "MSHIP_S_00135")
    List listWithoutTTest(@KxRequestParam("memberIds") List<String> companyIds);

    @Request(url = "OMS_S_00076_ZL")
    Future<KosProduct> asyncFutureTest(@KxRequestParam("productUniqueKeyStr") String productUniqueKeyStr);

    @Request(url = "OMS_S_00076_ZL")
    Future asyncFutureWithoutTTest(@KxRequestParam("productUniqueKeyStr") String productUniqueKeyStr);

    @Request(url = "MSHIP_S_00135")
    Future<List<OrgInfo>> asyncFutureListTest(@KxRequestParam("memberIds") List<String> companyIds);

    @Request(url = "MSHIP_S_00135")
    Future<List> asyncFutureListWithoutTTest(@KxRequestParam("memberIds") List<String> companyIds);

    @Request(url = "OMS_S_00076_ZL")
    @Callback(TestCallBack.class)
    void callBackTest(@KxRequestParam("productUniqueKeyStr") String productUniqueKeyStr);

    @Request(url = "oms.kxtx.cn/kxtx-oms/omsConfig/setConfig", requestExecutor = "defaultHttpAsyncPoolClient")//http
    Object httpGetTest(@KxRequestParam(value = "key")String key, @KxRequestParam(value = "value")Integer value);

    @Request(url = "oms.kxtx.cn/kxtx-oms/kosProduct/calculatePriceByProIds", requestExecutor = "defaultHttpAsyncPoolClient", httpMethod = HttpMethod.POST)//http
    KosProduct httpPostTest(QueryParam queryParam);

    @Request(url = "OMS_S_00076_ZL")
    @UnRepeatable(0)//防止重复提交
    KosProduct lockTest(@KxRequestParam("productUniqueKeyStr") String productUniqueKeyStr);
}

第三步使用

/**
** spring环境下
**/
@Autowired
private TestRequestExecutor testRequestExecutor;
@Test
public void memTest() {
    Test2RequestExecutor test2RequestExecutor = this.getTestRequestExecutor(Test2RequestExecutor.class);
    String productKey = "2|4*NoPick*NoRoute*2cb666ea-5342-4634-8cf7-5cfc99097498*NoInten|NoSmal|00000000-0000-0000-0000-000000000002|NoHub";
    KosProduct r1 = testRequestExecutor.kxRequestParamTest(productKey);
    Assert.isTrue(productKey.equals(r1.getProductUniqueKeyStr()), "R1 WRONG WRONG WRONG");
	
	List companyIds = new ArrayList<String>() {{
            add("000189d7-456e-e511-9d72-40a8f0257e10");
            add("003d12ef-34d5-4256-ba61-458aaa5e7728");
        }};
	Future<List> f4 = testRequestExecutor.asyncFutureListWithoutTTest(companyIds);
    List r11 = f4.get();
    Assert.isTrue(r11.size() == 2, "R10 WRONG WRONG WRONG");
}

实现源码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Oracle Instant Client 11.2.0.1.0是轻量级Oracle客户端,用于连接访问Oracle 9i、10g、11g 11.2.0.1.0版本的Oracle数据库。 Oracle Instant Client11.2.0.1.0 安装程序包含OCI/ OCCI、JDBC-OCI SDK(软件开发工具包),软件开发时所需的全部头文件和链接库。 此版本不支持 Pro*C/C++和.NET程序所需的Oracle Provider for OLE DB,如需支持上述功能,请访问并下载ODAC(Oracle Data Access Components,其包含 ODP.NET, Oracle Services for MTS, Oracle Providers for ASP.NET):  http://www.oracle.com/technetwork/database/windows/downloads/utilsoft-087491.html  http://www.oracle.com/technetwork/cn/database/windows/downloads/index-101312-zhs.html 此版本集成了Oracle 11g 11.2.0.1.0中的实用工具tnsping、exp/imp,支持 Object Browser、TOAD等 Oracle 管理工具,并在Windows XP、Windows Vista、Windows 7平台下测试通过。 注意: 1. 请勿使用高版本的exp/imp工具对低版本的Oralce数据库进行导出,导入操作。 2. 安装完成后需手工配置 %TNS_ADMIN%\tnsnames.ora 文件,内容如下: ??? = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = xxx.xxx.xxx.xxx)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = xxxxxx) ) ) 1. 将 ??? 改为任意名字,这个名字将在你的程序或程序配置中用到。 2. 将 xxx.xxx.xxx.xxx 改为要连接的 Oracle 服务器的机器名或IP地址。 3. 将 xxxxxx 改为要连接的 Oracle 服务器的 SID,如不知道 SID,请询问安装 Oracle 数据库的管理人员。 相关网站: Oracle Instant Client 主页 http://www.oracle.com/technetwork/database/features/instant-client/index-100365.html Oracle Instant Client 常见问题 http://www.oracle.com/technetwork/database/features/oci/ic-faq-094177.html#A3661 SQL*Plus http://download.oracle.com/docs/cd/E11882_01/server.112/e16604/apd.htm#sthref3169 SDK: OCI(Oracle Call Interface) http://download.oracle.com/docs/cd/E11882_01/appdev.112/e10646/oci01int.htm#i423362 OCCI(Oracle C++ Call Interface) http://download.oracle.com/docs/cd/E11882_01/appdev.112/e10764/install.htm#CACFFGHF 如需源码或技术支持: Email: gosearcher@gmail.com
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值