Esper教程 —— Esper 事件类型有几种(2)

二、事件类型

Esper 对事件有特殊的数据结构约定。能处理的事件结构有:POJOjava.util.MapObject ArrayXML

1、POJO

对于POJO,Esper要求对每一个私有属性要有 getter 方法。Esper允许不必按照JavaBean规定的格式,但是getter方法是必须的。简单示例如下

@Getter
public class Person {
    private int name;
    private int age;
}

Esper 支持复杂的数据类型以及嵌套。稍微复杂的如下

@Getter
public class Person {
    private int id;
    private int price;
    
    List<Child> children; 
    Map<String, Integer> phones;
    Address address;
}

@Getter
class Child {
    String name;
    int gender;
}

@Getter
class Address {
    String road;
    String street;
    int houseNo;
}

如上所示,Esper 能支持包含了集合类型和嵌套类的POJO,示例的EPL语句如下

-- 当Person类型的事件中name为 tingfeng 时,Esper能得到对应的 age,children和address
select age,children,address from Person where name="tingfeng"

如果我不想要所有的 child,而是想要第二个。并且我想得到家里的电话号码,那么 Person 需要增加一下 getter 方法

@Getter
public class Person {
    private int id;
    private int price;
    
    List<Child> children; 
    Map<String, Integer> phones;
    Address address;

    public Child getChildren(int index) {  
        return children.get(index);  
    }

    public int getPhones(String name) {  
        return phones.get(name);  
    }
}

对应的EPL如下

-- 当Person类型的事件中name为 tingfeng 时,Esper能得到对应的第二个孩子,家里的电话和家庭住址在哪条路上
select children[1], phones('home'), address.road where Person where name="tingfeng"

Esper支持事件的更新,对此Esper要求提供对应的 setter 方法。如下改动增加一个 setPhones 方法。

/**
 * 此方法用于phones属性的更新 
 */
 public void setPhones(String name, Integer number){
    phones.put(name, number);
}

对应的EPL如下

-- 当Person类型的事件中name为 tingfeng 时,更新家里的电话
update Person set phones('home') = 123456789 where name="tingfeng"

另外 Esper 还支持实现了多个接口类或者抽象类的POJO,使用方法和普通的POJO没什么区别。

2、Map

Esper 支持原生 Java Map 结构的事件。相对于POJO来说,Map 的结构更利于事件类型的热加载,毕竟不是 class,所以不需要重启JVM。所以如果系统对重启比较敏感,建议使用Map来定义事件的结构。

Map的结构很简单,主要分为事件定义名事件属性列表。我们继续拿Person来讲解。

import java.util.HashMap;  
import java.util.List;  
import java.util.Map;  

import com.espertech.esper.client.EPAdministrator;
import com.espertech.esper.client.EPServiceProvider;
import com.espertech.esper.client.EPServiceProviderManager;

public class PersonMap  {

    public static void main(String[] args) {
        EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider();
        EPAdministrator admin = epService.getEPAdministrator();
    
        // Person定义
        Map<String,Object> person = new HashMap<String,Object>();
        person.put("name", String.class);
        person.put("age", int.class);
        person.put("children", List.class);
        person.put("phones", Map.class);
    
        // 注册Person到Esper
        admin.getConfiguration().addEventType("Person", person);
    }
}

Map 结构的事件需要将属性名作为 key,属性的数据类型作为 value 保存到Map中,然后再通过Esper的接口注册到Esper。其中 addEventType 的两个参数分别代表事件定义的名称和所定义的结构。

对应的EPL和POJO的没有区别.

-- 当Person类型的事件中name为 tingfeng 时,Esper能得到对应的 age,children和address  
select age,children,address from Person where name="tingfeng"

Map 对于嵌套类的定义比较特别。如果嵌套的类是POJO,那就如上面所示。如果嵌套的还是Map,那么定义方式就需要改变。我们为 Person 加上Address,示例如下.

public static void main(String[] args) {
    EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider();
    EPAdministrator admin = epService.getEPAdministrator();

    // Address定义
    Map<String, Object> address = new HashMap<String, Object>();
    address.put("road", String.class);
    address.put("street", String.class);
    address.put("houseNo", int.class);

    // Person定义
    Map<String, Object> person = new HashMap<String, Object>();
    person.put("name", String.class);
    person.put("age", int.class);
    person.put("children", List.class);
    person.put("phones", Map.class);
    person.put("address", "Address");

    // 注册Address到Esper
    admin.getConfiguration().addEventType("Address", address);
    // 注册Person到Esper
    admin.getConfiguration().addEventType("Person", person);
}

有两个关键点:

  • Person 在定义 Address 属性时,value 不是 Address.class,而是 Address 字符串,而这就代表引擎里的Address对应的Map结构定义。

  • 事件定义注册必须是Address先于Person,因为Person用到了Address,而引擎是根据Address注册时用的名字去查找Address定义的。

如果 Person 有多个 Address,则以数组方式定义 Person 的多个 Address 时,代码又变成下面的样子了。

person.put("addresses", "Address[]");

Esper 中 Map 只支持增量更新,也就是说只能增加 Map 中的属性定义,而 不能修改或者删除某个属性。我们为 Person 增加一个 gender 属性,示例如下

public static void main(String[] args) {
    EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider();
    EPAdministrator admin = epService.getEPAdministrator();

    // Address定义
    Map<String, Object> address = new HashMap<String, Object>();
    address.put("road", String.class);
    address.put("street", String.class);
    address.put("houseNo", int.class);

    // Person定义
    Map<String, Object> person = new HashMap<String, Object>();
    person.put("name", String.class);
    person.put("age", int.class);
    person.put("children", List.class);
    person.put("phones", Map.class); 
    person.put("address", "Address");

    // 注册Address到Esper
    admin.getConfiguration().addEventType("Address", address);
    // 注册Person到Esper
    admin.getConfiguration().addEventType("Person", person);

    // 新增一个gender属性
    person.put("gender", int.class);
    admin.getConfiguration().updateMapEventType("Person", person);

    /** 输出结果
        * Person props: [address, age, name, children, phones, gender]
        */
    EventType event = admin.getConfiguration().getEventType("Person");
    System.out.println("Person props: " + Arrays.asList(event.getPropertyNames()));
}

3、Object Array

对象数组和 Map 很像,基本没有差别。只是定义方式不一样,Esper也同样对 Object Array 只支持增量更新。继续用Person为例子.

public class PersonArray {

    public static void main(String[] args) {  
        EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider();
        EPAdministrator admin = epService.getEPAdministrator();

        // Address定义
        String[] addressPropNames = { "road", "street", "houseNo" };
        Object[] addressPropTypes = { String.class, String.class, int.class };

        // Child定义
        String[] childPropNames = { "name", "age" };
        Object[] childPropTypes = { String.class, int.class };

        // Person定义
        String[] personPropNames = { "name", "age", "children", "phones", "address" };
        Object[] personPropTypes = { String.class, int.class, "Child[]", Map.class, "Address" };

        // 注册Address到Esper
        admin.getConfiguration().addEventType("Address", addressPropNames, addressPropTypes);
        // 注册Child到Esper
        admin.getConfiguration().addEventType("Child", childPropNames, childPropTypes);
        // 注册Person到Esper
        admin.getConfiguration().addEventType("Person", personPropNames, personPropTypes);

        // 新增一个gender属性
        admin.getConfiguration().updateObjectArrayEventType("Person", new String[] { "gender" }, new Object[] { int.class });

        /** 输出结果:
         * Person props: [name, age, children, phones, address, gender]
         */
        EventType event = admin.getConfiguration().getEventType("Person");
        System.out.println("Person props: " + Arrays.asList(event.getPropertyNames()));
    }
}

4、XML

待补充


未经允许请勿转载:程序喵 » Esper教程 —— Esper 事件类型有几种(2)

点  赞 (0) 打  赏
分享到: