您的位置:首页 > 其它

Esper学习之二:事件类型 .

2015-06-01 09:42 393 查看
上周我们介绍了Esper,它是一个适合实时分析数据的内存计算引擎。若有不了解的同学可以看一下Esper学习之一:Esper介绍。如果各位自己运行过之前的程序,应该对Esper的处理机制和EPL比较感兴趣。不过这篇文章就先来介绍一下Esper能处理的数据结构,即“事件”。

Esper对事件有特殊的数据结构约定。能处理的事件结构有:POJO,java.util.Map,Object Array,XML

1.POJO

对于POJO,Esper要求对每一个私有属性要有getter方法。Esper允许不必按照JavaBean规定的格式,但是getter方法是必须的。又或者可以在配置文件中配置可访问的方法来代替getter。简单示例如下

[java]
view plaincopyprint?

public class Person { String name; int age; public String getName() { return name; } public int getAge() { return age; } }

public class Person
{
String name;
int age;

public String getName()
{
return name;
}

public int getAge()
{
return age;
}
}
Esper同样也能支持复杂的数据类型以及嵌套。稍微复杂的Person如下

[java]
view plaincopyprint?

import java.util.List; import java.util.Map; public class Person { String name; int age; List<Child> children; Map<String, Integer> phones; Address address; public String getName() { return name; } public int getAge() { return age; } public List<Child> getChildren() { return children; } public Map<String, Integer> getPhones() { return phones; } public Address getAddress() { return address; } } class Child { String name; int gender; // 省略getter方法 } class Address { String road; String street; int houseNo; // 省略getter方法 }

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

public class Person
{
String name;
int age;
List<Child> children;
Map<String, Integer> phones;
Address address;

public String getName()
{
return name;
}

public int getAge()
{
return age;
}

public List<Child> getChildren()
{
return children;
}

public Map<String, Integer> getPhones()
{
return phones;
}

public Address getAddress()
{
return address;
}

}

class Child
{
String name;
int gender;
// 省略getter方法
}

class Address
{
String road;
String street;
int houseNo;
// 省略getter方法
}
如上所示,Esper能支持包含了集合类型和嵌套类的POJO,示例的EPL语句如下

[sql]
view plaincopyprint?

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


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

[java]
view plaincopyprint?

import java.util.List; import java.util.Map; public class Person { String name; int age; List<Child> children; Map<String, Integer> phones; Address address; public String getName() { return name; } public int getAge() { return age; } public Child getChildren(int index) { return children.get(index); } public int getPhones(String name) { return phones.get(name); } public Address getAddress() { return address; } // Address,Child不变 }

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

public class Person
{
String name;
int age;
List<Child> children;
Map<String, Integer> phones;
Address address;

public String getName()
{
return name;
}

public int getAge()
{
return age;
}

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

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

public Address getAddress()
{
return address;
}
// Address,Child不变
}
对应的EPL如下

[java]
view plaincopyprint?

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

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


Esper支持事件的更新,对此Esper要求提供对应的setter方法。Person需要再有点小该度。示例如下

[java]
view plaincopyprint?

import java.util.List; import java.util.Map; public class Person { String name; int age; List<Child> children; Map<String, Integer> phones; Address address; public String getName() { return name; } public int getAge() { return age; } public Child getChildren(int index) { return children.get(index); } // 此方法用于phones属性的更新 public void setPhones(String name, Integer number){ phones.put(name, number); } public int getPhones(String name) { return phones.get(name); } public Address getAddress() { return address; } // Address,Child不变 }

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

public class Person
{
String name;
int age;
List<Child> children;
Map<String, Integer> phones;
Address address;

public String getName()
{
return name;
}

public int getAge()
{
return age;
}

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

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

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

public Address getAddress()
{
return address;
}
// Address,Child不变
}
对应的EPL如下

[sql]
view plaincopyprint?

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

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

Esper对POJO的支持基本上就是上面所说的,另外他还支持实现了多个接口类或者抽象类的POJO,使用方法和普通的POJO没什么区别,这里就不列举了。

2.Map

Esper支持原生Java Map结构的事件。相对于POJO来说,Map的结构更利于事件类型的热加载,毕竟不是class,所以不需要重启JVM。所以如果系统对重启比较敏感,建议使用Map来定义事件的结构。Map的结构很简单,主要分为事件定义名和事件属性列表。我们继续拿Person来讲解

[java]
view plaincopyprint?

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); } }

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的没有区别

[sql]
view plaincopyprint?

// 当Person类型的事件中name为luonanqin时,Esper能得到对应的age,children select age,children from Person where name="luonanqin"
// 当Person类型的事件中name为luonanqin时,Esper能得到对应的age,children
select age,children from Person where name="luonanqin"
Map对于嵌套类的定义比较特别。如果嵌套的类是POJO,那就如上面所示。如果嵌套的还是Map,那么定义方式就需要改变。我们为Person加上Address,示例如下

[java]
view plaincopyprint?

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(); // 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); } }

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();

// 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);
}
}
如上所示,有两个关键点:

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

2.事件定义注册必须是Address先于Person,因为Person用到了Address,而引擎是根据Address注册时用的名字去查找Address定义的,所以如果名字写错,引擎就找不到Address了

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

[java]
view plaincopyprint?

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

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


另外对于Map,Esper只支持增量更新,也就是说只能增加Map中的属性定义,而不能修改或者删除某个属性(实际上属性增多并不影响其处理性能,所以没有删除在我看来也没什么。至于修改,也只能是先注销再注册了)。我们为Person增加一个gender属性,示例如下

[java]
view plaincopyprint?

import java.util.Arrays;
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;
import com.espertech.esper.client.EventType;

public class PersonMap
{
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()));
}
}

import java.util.Arrays;
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;
import com.espertech.esper.client.EventType;

public class PersonMap
{
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同样也只支持增量更新。这里继续用Person为大家做例子

[java]
view plaincopyprint?

import java.util.Arrays;
import java.util.Map;

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

public class PersonArray
{

/**
* @param args
*/
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()));
}
}

import java.util.Arrays;
import java.util.Map;

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

public class PersonArray
{

/**
* @param args
*/
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

很抱歉我没有实际研究过XML,所以这一节就先不写了,免得误导大家就不好了。假以时日我研究之后,一定会把这节补上的。各位请见谅!!

上面列出的4种事件格式,在实际的应用过程中,对于其对应的事件数据,发送到引擎的方式有点区别。下一篇将会说到这一点,并且有比较新奇的东西哦,你会瞬间感受到Esper的魅力所在。敬请关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: