今天这篇主要讲讲一些基础知识以便领大家入门,具体的语法下篇会有详细说明。
1. Pattern Atoms and Pattern operators
Pattern是通过原子事件和操作符组合在一起构成模板。原子事件有3类,操作符有4类,具体如下:
原子事件:
1). 普通事件:包括POJO,Map,Array,XML
2). 时间事件:包括间隔n个时间单位、crontab
3). 自定义插件:用于观察特定事件的发生
操作符:
1). 重复操作符:every, every-distinct, [num] and until
2). 逻辑操作符:and, or, not
3). 顺序操作符:->(Followed by)
4). 事件生命周期操作符:timer:within, timer:withinmax, while-expression, 自定义插件
关于操作符,自然会有优先级,具体如下:
Precedence | Operator | Description | Example |
---|---|---|---|
1 |
guard postfix | where timer:within and while (expression) (incl. withinmax and plug-in pattern guard) |
MyEvent where timer:within(1 sec) |
2 |
unary | every, not every, distinct |
every MyEvent |
3 | repeat | [num], until |
[5] MyEvent [1..3] MyEvent until MyOtherEvent |
4 | and | and | every (MyEvent and MyOtherEvent) |
5 | or | or | every (MyEvent or MyOtherEvent) |
6 | followed by | -> | every (MyEvent -> MyOtherEvent) |
上面的内容各位可以先有个印象,方便理解之后的详解。
2. Pattern Filter Expression
Pattern的Filter表达式和普通的表达式没有区别,我就不展开讲解了,各位看看下面几个例子就好,除了Filter之外的东西暂时不用关心是什么意思。
1). every e1=RfidEvent -> e2=RfidEvent(assetId=e1.assetId)
2). every e1=RfidEvent -> e2=RfidEvent(MyLib.isInRadius(e1.x, e1.y, x, y) and zone in (1, e1.zone))
3). every (RfidEvent(zone > 1) and RfidEvent(zone < 10))
3. Controlling Event Consumption
上面说到了Filter,因为Pattern可以由多个原子事件组成,那么Filter自然也会有多个,正常情况下,所有的Filter都会对进入引擎的事件进行判定,但是我们也有只需要判定一次的时候,只要满足了某个Filter,那么其他的Filter就不用管这个事件了。Esper考虑到了这个需求,我们只需要在Filter表达式后面加个@consume注解即可,此注解可以跟随数字,表示过滤的优先级。默认优先级为1,数值越大优先级越高。
为了结合上面几节的知识,我给了个完整的实例:
package example;
import com.espertech.esper.client.EPAdministrator;
import com.espertech.esper.client.EPRuntime;
import com.espertech.esper.client.EPServiceProvider;
import com.espertech.esper.client.EPServiceProviderManager;
import com.espertech.esper.client.EPStatement;
import com.espertech.esper.client.EventBean;
import com.espertech.esper.client.UpdateListener;
/**
* Created by Luonanqin on 8/11/14.
*/
class ConsumeEvent {
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "ConsumeEvent{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}';
}
}
class PatternConsumeListener1 implements UpdateListener {
public void update(EventBean[] newEvents, EventBean[] oldEvents) {
if (newEvents != null) {
for (int i = 0; i < newEvents.length; i++) {
System.out.println("a: " + newEvents[i].get("a"));
System.out.println("b: " + newEvents[i].get("b"));
}
}
}
}
class PatternConsumeListener2 implements UpdateListener {
public void update(EventBean[] newEvents, EventBean[] oldEvents) {
if (newEvents != null) {
for (int i = 0; i < newEvents.length; i++) {
System.out.println("a: " + newEvents[i].get("a"));
System.out.println("b: " + newEvents[i].get("b"));
System.out.println("c: " + newEvents[i].get("c"));
}
}
}
}
public class PatternConsumeTest {
public static void main(String[] args) {
EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider();
EPAdministrator admin = epService.getEPAdministrator();
EPRuntime runtime = epService.getEPRuntime();
String consume = ConsumeEvent.class.getName();
String epl1 = "every (a=" + consume + "(id = 1)@consume and b=" + consume + "(name = 'luonq'))";
System.out.println("EPL1: " + epl1 + "\n");
EPStatement stat1 = admin.createPattern(epl1);
stat1.addListener(new PatternConsumeListener1());
ConsumeEvent ce1 = new ConsumeEvent();
ce1.setId(1);
ce1.setName("luonq");
System.out.println("Send Event: " + ce1);
runtime.sendEvent(ce1);
System.out.println();
ConsumeEvent ce2 = new ConsumeEvent();
ce2.setId(2);
ce2.setName("luonq");
System.out.println("Send Event: " + ce2);
runtime.sendEvent(ce2);
stat1.destroy();
System.out.println();
String epl2 = "every (a=" + consume + "(id = 1)@consume(2) or b=" + consume + "(name = 'luonq')@consume(3) or c=" + consume + "(age > 2))";
System.out.println("EPL2: " + epl2 + "\n");
EPStatement stat2 = admin.createPattern(epl2);
stat2.addListener(new PatternConsumeListener2());
ConsumeEvent ce3 = new ConsumeEvent();
ce3.setId(1);
ce3.setName("luonq");
ce3.setAge(3);
System.out.println("Send Event: " + ce3);
runtime.sendEvent(ce3);
ConsumeEvent ce4 = new ConsumeEvent();
ce4.setId(1);
ce4.setName("luonqin");
ce4.setAge(1);
System.out.println("Send Event: " + ce4);
runtime.sendEvent(ce4);
ConsumeEvent ce5 = new ConsumeEvent();
ce5.setId(3);
ce5.setName("luonqin");
ce5.setAge(5);
System.out.println("Send Event: " + ce5);
runtime.sendEvent(ce5);
}
}
执行结果:
EPL1: every (a=example.ConsumeEvent(id = 1)@consume and b=example.ConsumeEvent(name = 'luonq'))
Send Event: ConsumeEvent{id=1, name='luonq', age=0}
Send Event: ConsumeEvent{id=2, name='luonq', age=0}
a: ConsumeEvent{id=1, name='luonq', age=0}
b: ConsumeEvent{id=2, name='luonq', age=0}
EPL2: every (a=example.ConsumeEvent(id = 1)@consume(2) or b=example.ConsumeEvent(name = 'luonq')@consume(3) or c=example.ConsumeEvent(age > 2))
Send Event: ConsumeEvent{id=1, name='luonq', age=3}
a: null
b: ConsumeEvent{id=1, name='luonq', age=3}
c: null
Send Event: ConsumeEvent{id=1, name='luonqin', age=1}
a: ConsumeEvent{id=1, name='luonqin', age=1}
b: null
c: null
Send Event: ConsumeEvent{id=3, name='luonqin', age=5}
a: null
b: null
c: ConsumeEvent{id=3, name='luonqin', age=5}
这里先简单说明下,every关键字表示引擎把每个事件都进行Pattern的匹配,而不管上一个匹配是否完成。or和and就是或和且的意思,表示满足某个以及满足所有。
去掉consume的执行结果:
EPL1: every (a=example.ConsumeEvent(id = 1) and b=example.ConsumeEvent(name = 'luonq'))
Send Event: ConsumeEvent{id=1, name='luonq', age=0}
a: ConsumeEvent{id=1, name='luonq', age=0}
b: ConsumeEvent{id=1, name='luonq', age=0}
Send Event: ConsumeEvent{id=2, name='luonq', age=0}
EPL2: every (a=example.ConsumeEvent(id = 1) or b=example.ConsumeEvent(name = 'luonq') or c=example.ConsumeEvent(age > 2))
Send Event: ConsumeEvent{id=1, name='luonq', age=3}
a: ConsumeEvent{id=1, name='luonq', age=3}
b: null
c: null
Send Event: ConsumeEvent{id=1, name='luonqin', age=1}
a: ConsumeEvent{id=1, name='luonqin', age=1}
b: null
c: null
Send Event: ConsumeEvent{id=3, name='luonqin', age=5}
a: null
b: null
c: ConsumeEvent{id=3, name='luonqin', age=5}
上面的例子可能看得不是很懂,不过没关系,等到后面讲操作符进行详解后再来回顾就很简单了。
本篇内容较少,主要是将一些必备的基础知识跟各位说说,下一篇会对围绕操作符展开,如果篇幅过长,可能会分成两篇为大家献上。敬请期待……