Esper學習之二:事件類型

轉載請註明出處:http://blog.csdn.net/luonanqin



        上週我們介紹了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 plaincopy
  1. public class Person  
  2. {  
  3.     String name;  
  4.     int age;  
  5.   
  6.     public String getName()  
  7.     {  
  8.         return name;  
  9.     }  
  10.   
  11.     public int getAge()  
  12.     {  
  13.         return age;  
  14.     }  
  15. }  
Esper同樣也能支持複雜的數據類型以及嵌套。稍微複雜的Person如下

[java] view plaincopy
  1. import java.util.List;  
  2. import java.util.Map;  
  3.   
  4. public class Person  
  5. {  
  6.     String name;  
  7.     int age;  
  8.     List<Child> children;  
  9.     Map<String, Integer> phones;  
  10.     Address address;  
  11.   
  12.     public String getName()  
  13.     {  
  14.         return name;  
  15.     }  
  16.   
  17.     public int getAge()  
  18.     {  
  19.         return age;  
  20.     }  
  21.   
  22.     public List<Child> getChildren()  
  23.     {  
  24.         return children;  
  25.     }  
  26.   
  27.     public Map<String, Integer> getPhones()  
  28.     {  
  29.         return phones;  
  30.     }  
  31.   
  32.     public Address getAddress()  
  33.     {  
  34.         return address;  
  35.     }  
  36.       
  37. }  
  38.   
  39. class Child  
  40. {  
  41.     String name;  
  42.     int gender;  
  43.     // 省略getter方法  
  44. }  
  45.   
  46. class Address  
  47. {  
  48.     String road;  
  49.     String street;  
  50.     int houseNo;  
  51.     // 省略getter方法  
  52. }  
如上所示,Esper能支持包含了集合類型和嵌套類的POJO,示例的EPL語句如下

  1. // 當Person類型的事件中name爲luonanqin時,Esper能得到對應的age,children和address  
  2. select age,children,address from Person where name="luonanqin"   

如果我不想要所有的child,而是想要第二個。並且我想得到家裏的電話號碼,那麼Person需要改動一下

[java] view plaincopy
  1. import java.util.List;  
  2. import java.util.Map;  
  3.   
  4. public class Person  
  5. {  
  6.     String name;  
  7.     int age;  
  8.     List<Child> children;  
  9.     Map<String, Integer> phones;  
  10.     Address address;  
  11.   
  12.     public String getName()  
  13.     {  
  14.         return name;  
  15.     }  
  16.   
  17.     public int getAge()  
  18.     {  
  19.         return age;  
  20.     }  
  21.   
  22.     public Child getChildren(int index)  
  23.     {  
  24.         return children.get(index);  
  25.     }  
  26.   
  27.     public int getPhones(String name)  
  28.     {  
  29.         return phones.get(name);  
  30.     }  
  31.   
  32.     public Address getAddress()  
  33.     {  
  34.         return address;  
  35.     }  
  36.     // Address,Child不變  
  37. }  
對應的EPL如下

[java] view plaincopy
  1. // 當Person類型的事件中name爲luonanqin時,Esper能得到對應的第二個孩子,家裏的電話和家庭住址在哪條路上  
  2. select children[1], phones('home'), address.road where Person where name="luonanqin"  

Esper支持事件的更新,對此Esper要求提供對應的setter方法。Person需要再有點小該度。示例如下

[java] view plaincopy
  1. import java.util.List;  
  2. import java.util.Map;  
  3.   
  4. public class Person  
  5. {  
  6.     String name;  
  7.     int age;  
  8.     List<Child> children;  
  9.     Map<String, Integer> phones;  
  10.     Address address;  
  11.   
  12.     public String getName()  
  13.     {  
  14.         return name;  
  15.     }  
  16.   
  17.     public int getAge()  
  18.     {  
  19.         return age;  
  20.     }  
  21.   
  22.     public Child getChildren(int index)  
  23.     {  
  24.         return children.get(index);  
  25.     }  
  26.       
  27.     // 此方法用於phones屬性的更新  
  28.     public void setPhones(String name, Integer number){  
  29.         phones.put(name, number);  
  30.     }  
  31.   
  32.     public int getPhones(String name)  
  33.     {  
  34.         return phones.get(name);  
  35.     }  
  36.   
  37.     public Address getAddress()  
  38.     {  
  39.         return address;  
  40.     }  
  41.     // Address,Child不變  
  42. }  
對應的EPL如下

  1. // 當Person類型的事件中name爲luonanqin時,更新家裏的電話  
  2. 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 plaincopy
  1. import java.util.HashMap;  
  2. import java.util.List;  
  3. import java.util.Map;  
  4.   
  5. import com.espertech.esper.client.EPAdministrator;  
  6. import com.espertech.esper.client.EPServiceProvider;  
  7. import com.espertech.esper.client.EPServiceProviderManager;  
  8.   
  9.   
  10. public class PersonMap  
  11. {  
  12.     public static void main(String[] args)  
  13.     {  
  14.         EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider();  
  15.         EPAdministrator admin = epService.getEPAdministrator();  
  16.           
  17.         // Person定義  
  18.         Map<String,Object> person = new HashMap<String,Object>();  
  19.         person.put("name", String.class);  
  20.         person.put("age"int.class);  
  21.         person.put("children", List.class);  
  22.         person.put("phones", Map.class);  
  23.           
  24.         // 註冊Person到Esper  
  25.         admin.getConfiguration().addEventType("Person", person);  
  26.     }  
  27. }  
如上所示,Map結構的事件需要將屬性名作爲key,屬性的數據類型作爲value保存到Map中,然後再通過Esper的接口註冊到Esper。其中addEventType的兩個參數分別代表事件定義的名稱和所定義的結構。

對應的EPL和POJO的沒有區別

  1. // 當Person類型的事件中name爲luonanqin時,Esper能得到對應的age,children  
  2. select age,children from Person where name="luonanqin"   
Map對於嵌套類的定義比較特別。如果嵌套的類是POJO,那就如上面所示。如果嵌套的還是Map,那麼定義方式就需要改變。我們爲Person加上Address,示例如下

[java] view plaincopy
  1. import java.util.HashMap;  
  2. import java.util.List;  
  3. import java.util.Map;  
  4.   
  5. import com.espertech.esper.client.EPAdministrator;  
  6. import com.espertech.esper.client.EPServiceProvider;  
  7. import com.espertech.esper.client.EPServiceProviderManager;  
  8.   
  9. public class PersonMap  
  10. {  
  11.     public static void main(String[] args)  
  12.     {  
  13.         EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider();  
  14.         EPAdministrator admin = epService.getEPAdministrator();  
  15.   
  16.         // Address定義  
  17.         Map<String, Object> address = new HashMap<String, Object>();  
  18.         address.put("road", String.class);  
  19.         address.put("street", String.class);  
  20.         address.put("houseNo"int.class);  
  21.   
  22.         // Person定義  
  23.         Map<String, Object> person = new HashMap<String, Object>();  
  24.         person.put("name", String.class);  
  25.         person.put("age"int.class);  
  26.         person.put("children", List.class);  
  27.         person.put("phones", Map.class);  
  28.         person.put("address""Address");  
  29.   
  30.         // 註冊Address到Esper  
  31.         admin.getConfiguration().addEventType("Address", address);  
  32.         // 註冊Person到Esper  
  33.         admin.getConfiguration().addEventType("Person", person);  
  34.     }  
  35. }  
如上所示,有兩個關鍵點:

1.Person在定義Address屬性時,map的value不是Address.class,而是Address字符串,而這就代表引擎裏的Address對應的Map結構定義

2.事件定義註冊必須是Address先於Person,因爲Person用到了Address,而引擎是根據Address註冊時用的名字去查找Address定義的,所以如果名字寫錯,引擎就找不到Address了

如果Person有多個Address,則以數組方式定義Person的多個Address時,代碼又變成下面的樣子了

[java] view plaincopy
  1. person.put("addresses""Address[]");  

另外對於Map,Esper只支持增量更新,也就是說只能增加Map中的屬性定義,而不能修改或者刪除某個屬性(實際上屬性增多並不影響其處理性能,所以沒有刪除在我看來也沒什麼。至於修改,也只能是先註銷再註冊了)。我們爲Person增加一個gender屬性,示例如下

[java] view plaincopy
  1. import java.util.Arrays;  
  2. import java.util.HashMap;  
  3. import java.util.List;  
  4. import java.util.Map;  
  5.   
  6. import com.espertech.esper.client.EPAdministrator;  
  7. import com.espertech.esper.client.EPServiceProvider;  
  8. import com.espertech.esper.client.EPServiceProviderManager;  
  9. import com.espertech.esper.client.EventType;  
  10.   
  11. public class PersonMap  
  12. {  
  13.     public static void main(String[] args)  
  14.     {  
  15.         EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider();  
  16.         EPAdministrator admin = epService.getEPAdministrator();  
  17.   
  18.         // Address定義  
  19.         Map<String, Object> address = new HashMap<String, Object>();  
  20.         address.put("road", String.class);  
  21.         address.put("street", String.class);  
  22.         address.put("houseNo"int.class);  
  23.   
  24.         // Person定義  
  25.         Map<String, Object> person = new HashMap<String, Object>();  
  26.         person.put("name", String.class);  
  27.         person.put("age"int.class);  
  28.         person.put("children", List.class);  
  29.         person.put("phones", Map.class);  
  30.         person.put("address""Address");  
  31.   
  32.         // 註冊Address到Esper  
  33.         admin.getConfiguration().addEventType("Address", address);  
  34.         // 註冊Person到Esper  
  35.         admin.getConfiguration().addEventType("Person", person);  
  36.   
  37.         // 新增一個gender屬性  
  38.         person.put("gender"int.class);  
  39.         admin.getConfiguration().updateMapEventType("Person", person);  
  40.           
  41.         /** 輸出結果: 
  42.          * Person props: [address, age, name, children, phones, gender] 
  43.          */  
  44.         EventType event = admin.getConfiguration().getEventType("Person");  
  45.         System.out.println("Person props: " + Arrays.asList(event.getPropertyNames()));  
  46.     }  
  47. }  


3.Object Array

對象數組和Map很像,基本沒有差別。只是定義方式不一樣,Esper同樣也只支持增量更新。這裏繼續用Person爲大家做例子

[java] view plaincopy
  1. import java.util.Arrays;  
  2. import java.util.Map;  
  3.   
  4. import com.espertech.esper.client.EPAdministrator;  
  5. import com.espertech.esper.client.EPServiceProvider;  
  6. import com.espertech.esper.client.EPServiceProviderManager;  
  7. import com.espertech.esper.client.EventType;  
  8.   
  9. public class PersonArray  
  10. {  
  11.   
  12.     /** 
  13.      * @param args 
  14.      */  
  15.     public static void main(String[] args)  
  16.     {  
  17.         EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider();  
  18.         EPAdministrator admin = epService.getEPAdministrator();  
  19.   
  20.         // Address定義  
  21.         String[] addressPropNames = { "road""street""houseNo" };  
  22.         Object[] addressPropTypes = { String.class, String.classint.class };  
  23.   
  24.         // Child定義  
  25.         String[] childPropNames = { "name""age" };  
  26.         Object[] childPropTypes = { String.classint.class };  
  27.   
  28.         // Person定義  
  29.         String[] personPropNames = { "name""age""children""phones""address" };  
  30.         Object[] personPropTypes = { String.classint.class"Child[]", Map.class"Address" };  
  31.   
  32.         // 註冊Address到Esper  
  33.         admin.getConfiguration().addEventType("Address", addressPropNames, addressPropTypes);  
  34.         // 註冊Child到Esper  
  35.         admin.getConfiguration().addEventType("Child", childPropNames, childPropTypes);  
  36.         // 註冊Person到Esper  
  37.         admin.getConfiguration().addEventType("Person", personPropNames, personPropTypes);  
  38.   
  39.         // 新增一個gender屬性  
  40.         admin.getConfiguration().updateObjectArrayEventType("Person"new String[] { "gender" }, new Object[] { int.class });  
  41.   
  42.         /** 輸出結果: 
  43.          * Person props: [name, age, children, phones, address, gender] 
  44.          */  
  45.         EventType event = admin.getConfiguration().getEventType("Person");  
  46.         System.out.println("Person props: " + Arrays.asList(event.getPropertyNames()));  
  47.     }  
  48. }  
上面的例子包含了對象數組這種事件格式的所有特性,我就不多加解釋了。

4.XML

很抱歉我沒有實際研究過XML,所以這一節就先不寫了,免得誤導大家就不好了。假以時日我研究之後,一定會把這節補上的。各位請見諒!!


       上面列出的4種事件格式,在實際的應用過程中,對於其對應的事件數據,發送到引擎的方式有點區別。下一篇將會說到這一點,並且有比較新奇的東西哦,你會瞬間感受到Esper的魅力所在。敬請關注

發佈了16 篇原創文章 · 獲贊 8 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章