有时我们需要在一个Bolt(FirBolt)中将一个对象emit到下一个Bolt(SecBolt)后,将其保存起来,等其它触发条件发生时,修改这个对象的值,然后再将其emit到下一个Bolt,这是我发现如果在上一个对象没有被SecBolt处理的时候,将更新后的这个对象emit给SecBolt的话,第一次emit的值会变得和第二次emit的值一样。不知道这是不是Storm的一个Bug。
我开始以为是因为我的这个类没有重写equals和hashCode的缘故,我将这两个方法重写后发现还是不行,然后我猜测这可能是因为两次emit的都是一个对象导致的,我在BasicLog中重写的clone方法,然后emit的时候都是emti原对象的一个clone。运行,搞定:
下面是BasicLog的代码:
package izp.storm.basic;
import java.io.Serializable;
import java.util.HashMap;
public class BasicLog implements Serializable , Cloneable{
//[start] 字段
private String pushid;
public HashMap<String,String> map = new HashMap<String,String>();
private Boolean push;
private Boolean show;
private Boolean click;
private Boolean mclick;
//[end]
//[start] 属性
public String getPushid() {
return pushid;
}
public void setPushid(String pushid) {
this.pushid = pushid;
}
public Boolean isPush() {
return push;
}
public void setPush(boolean push) {
this.push = push;
}
public Boolean isShow() {
return show;
}
public void setShow(boolean show) {
this.show = show;
}
public Boolean isClick() {
return click;
}
public void setClick(boolean click) {
this.click = click;
}
public Boolean isMclick() {
return mclick;
}
public void setMclick(boolean mclick) {
this.mclick = mclick;
}
//[end]
//[start] 方法
@Override
public BasicLog clone() throws CloneNotSupportedException {
BasicLog other = new BasicLog();
other.setPushid(this.pushid);
other.map = (HashMap<String,String>)this.map.clone();
other.setPush(this.isPush());
other.setShow(this.isShow());
other.setClick(this.isClick());
other.setMclick(this.isMclick());
return other;
}
//[end]
}
提交时的代码:
public void execute(Tuple input, BasicOutputCollector collector) {
BasicLog log = (BasicLog)input.getValueByField("basicLog");
String pushid = log.getPushid();
//对每个push都进行emit 同一个pushid的多次push过滤掉
if(log.isPush()){
if(!map.joinMap.containsKey(pushid)){
map.joinMap.put(pushid, log);
try{
collector.emit(new Values(log.map.get("adid"),log.map.get("adposid"),log.clone()));
System.out.println(new Values(log.map.get("adid"),log.map.get("adposid"),log).toString());
}catch(Exception e){
log(e.toString());
}
}
else{
BasicLog oldLog = map.joinMap.get(pushid);
if(!oldLog.isPush()){
oldLog.setPush(true);
for(String key : log.map.keySet()){
oldLog.map.put(key, log.map.get(key));
}
try{
collector.emit(new Values(oldLog.map.get("adid"),oldLog.map.get("adposid"),oldLog.clone()));
System.out.println(new Values(oldLog.map.get("adid"),oldLog.map.get("adposid"),oldLog).toString());
}catch(Exception e){
log(e.toString());
}
}
}
}
//若show可以关联上 则进行emit ,同一个pushid 多次show 过滤掉
else if(log.isShow()){
if(!map.joinMap.containsKey(pushid)){
map.joinMap.put(pushid, log);
}
else{
BasicLog oldLog = map.joinMap.get(pushid);
if(!oldLog.isShow()){
oldLog.setShow(true);
try{
collector.emit(new Values(oldLog.map.get("adid"),oldLog.map.get("adposid"),oldLog.clone()));
System.out.println(new Values(oldLog.map.get("adid"),oldLog.map.get("adposid"),oldLog).toString());
}catch(Exception e){
log(e.toString());
}
}
}
}
//若click可以关联上 则进行emit, 同一个pushid 若是多次点击 则设置mclick为true
else if(log.isClick()){
if(!map.joinMap.containsKey(pushid)){
map.joinMap.put(pushid, log);
}
else{
BasicLog oldLog = map.joinMap.get(pushid);
if(!oldLog.isClick()){
oldLog.setClick(true);
}
else{
oldLog.setMclick(true);
}
try{
collector.emit(new Values(oldLog.map.get("adid"),oldLog.map.get("adposid"),oldLog.clone()));
System.out.println(new Values(oldLog.map.get("adid"),oldLog.map.get("adposid"),oldLog).toString());
}catch(Exception e){
log(e.toString());
}
}
}
}