文档

泛化调用

更新时间:

相对于需要依赖业务客户端JAR包的正常调用,泛化调用不需要依赖二方包,使用其特定的GenericService接口,传入需要调用的方法名、方法签名和参数值进行调用服务。 泛化调用适用于一些网关应用(没办法依赖所有服务的二方包),其中hsfops服务测试也是依赖泛化调用功能。

前提条件

API形式配置HSF服务

HSFConsumerBean配置generictrue,HSF客户端将忽略加载不到接口的异常。

HSFApiConsumerBean hsfApiConsumerBean = new HSFApiConsumerBean();
hsfApiConsumerBean.setInterfaceName("com.alibaba.middleware.hsf.guide.api.service.OrderService");
hsfApiConsumerBean.setVersion("1.0.0");
hsfApiConsumerBean.setGroup("HSF");
// [设置] 泛化配置
hsfApiConsumerBean.setGeneric("true");
hsfApiConsumerBean.init(true);

// 使用泛化接口获取代理
GenericService genericOrderService = (GenericService) hsfApiConsumerBean.getObject();
// ---------------------- 调用 -----------------------//
// [调用] 发起HSF泛化调用, 返回map类型的result
Map orderModelMap = (Map) genericOrderService.$invoke("queryOrder",
                            // 方法入参类型数组(xxx.getClass().getName())
                            new String[] { Long.class.getName() },
                            // 参数,如果是pojo,则需要转成Map
                            new Object[] { 1L});

GenericService提供的$invoke方法包含了真实调用的方法名、入参类型和参数,以便服务端找到该方法。由于没有依赖服务端的API JAR包,传入的参数如果是自定义的DTO,需要转成客户端可以序列化的Map类型。

调用方法和参数说明

  • 方法没有入参,可以只传:methodName:service.$invoke("sayHello", null, null)

  • 方法类型有泛型的,例如List<String>,只需要传java.util.List,即List.class.getName()的值,不要传成java.util.List<String>,否则会出现方法找不到的错误。

  • 调用方法在不确定格式的情况下,可以写个单元测试,测试时依赖需要泛化调用的二方包,使用HSF提供的工具类com.taobao.hsf.util.PojoUtilsgeneralize()方法来生成一个pojo Bean的Map描述格式。

    Map pojoMap = (Map) PojoUtils.generalize(new OrderModel());
  • 传递参数为pojo的Demo。

     class User {
        private String name;
        private int age;
        // 需要是标准的pojo格式,这里省略getter setter
       }
    
       // 直接使用map去构造pojo对应的泛化参数
       Map param = new HashMap<String, Object>();
       param.put("age", 11);
       param.put("name","Miles");
       // 当传递的参数是声明参数类型的子类时,需要传入class字段,标明该pojo的真实类型(服务端需要有该类型)
       param.put("class", "com.taobao.User");

Spring配置HSF服务

Spring框架是在应用中广泛使用的组件,如果不想通过API的形式配置HSF服务,可以使用Spring XML的形式进行配置,上述例子中的API配置等同于如下XML配置。

<bean id="CallHelloWorld" class="com.taobao.hsf.app.spring.util.HSFSpringConsumerBean">
    <!--[设置] 订阅服务的接口 -->
    <property name="interfaceName" value="com.alibaba.middleware.hsf.guide.api.service.OrderService"/>
    <!--[设置] 服务的版本 -->
    <property name="version" value="1.0.0"/>
    <!--[设置] 服务的归组 -->
    <property name="group" value="HSF"/>
    <property name="generic" value="true"/>
</bean>

注意事项

  • 泛化调用,如果客户端没有接口类,路由规则默认不生效。

  • 泛化调用性能会比正常调用差。

  • 配置-Dhsf.generic.throw.exception=true (默认是false, 把异常泛化成map返回)抛出业务异常。

    本地存在异常类,如果不是RuntimeException类型或其子类,则会抛出UndeclaredThrowableException,这是由于com.taobao.hsf.remoting.service.GenericService上没有声明该异常,可以通过getCause获取真实异常。

    本地没有该异常类,则抛出com.taobao.hsf.util.GenericInvocationException

  • 本页导读 (1)
文档反馈