原数据是一个字符串数组,将数组中的元素一个一个向下发送
SimpleSpout
package com.xnmzdx.spout;
import java.util.Map;
import backtype.storm.spout.SpoutOutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.topology.base.BaseRichSpout;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Values;
public class SimpleSpout extends BaseRichSpout {
private static final long serialVersionUID = 2732069924540458266L;
private SpoutOutputCollector collector;
private int index = 0;
//向下发送的原数据(字符串数组)
private String[] setnences = {
"my dog has fieas",
"i like cold beverages",
"the dog ate my homeword",
"don't have a cow man",
"i don't think i like fleas"
};
@Override
public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
this.collector = collector;
}
@Override
public void nextTuple() {
if(index <= setnences.length-1){
collector.emit(new Values(setnences[index]));
index++;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
//声明发送数据的字段名称
declarer.declare(new Fields("sentence"));
}
}
将收到的每个字符串按空格分割,然后以str 1的格式存入redis数据库中(只是做最简单的分割单词,并没有计算单词的个数,相当于找出有多少个不同的单词),使用的是自己封装的redis操作工具类。
这个类的构造方法需要传入redis端口号和所在的主机ip,后续用于redis操作工具类的创建(主要是为了连接redis)
SaveRedisBolt
package com.xnmzdx.bolt;
import com.xnmzdx.utis.RedisOperations;
import backtype.storm.topology.BasicOutputCollector;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.topology.base.BaseBasicBolt;
import backtype.storm.tuple.Tuple;
public class SaveRedisBolt extends BaseBasicBolt {
private static final long serialVersionUID = -562386704327430015L;
String host; //redis所在的主机ip
int port; //redis的端口号
//构造方法
public SaveRedisBolt(String host, int port){
this.host = host;
this.port = port;
}
@Override
public void execute(Tuple input, BasicOutputCollector collector) {
String line = input.getStringByField("sentence");
String[] strs = line.split(" "); //按空格分割单词
for(String str : strs){ //可以对这部分做修改,使其变成做单词个数的统计
//str 1
RedisOperations redisoper = new RedisOperations(this.host,this.port); //redis操作的工具类
redisoper.insert(str, 1+""); //向redis中插入数据
}
}
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
}
}
redis操作的工具类,采用的是单机连接redis的方法,并简单封装了向redis插入数据的方法
RedisOperations
package com.xnmzdx.utis;
import redis.clients.jedis.Jedis;
/**
* 用于操作redis的工具类
* @author Administrator
*
*/
public class RedisOperations {
private Jedis jedis;
public RedisOperations(String host, int port){
//单机连接的方式
jedis = new Jedis(host,port);
jedis.auth("123456");
}
//插入数据的方法
public void insert(String word,String num){
jedis.set(word, num);
}
}
new SaveRedisBolt("storm02", 6379):“storm02”在windows操作系统上有IP映射的,也可直接写ip地址
RedisTopology
package com.xnmzdx.topology;
import com.xnmzdx.bolt.SaveRedisBolt;
import com.xnmzdx.spout.SimpleSpout;
import backtype.storm.Config;
import backtype.storm.LocalCluster;
import backtype.storm.topology.TopologyBuilder;
/**
* 将storm的计算结果存入redis中
* @author zyt
*
*/
public class RedisTopology {
public static void main(String[] args) {
//创建拓扑对象
TopologyBuilder builder = new TopologyBuilder();
builder.setSpout("simpleSpout", new SimpleSpout());
builder.setBolt("saveRedisBolt", new SaveRedisBolt("storm02", 6379)).shuffleGrouping("simpleSpout");
//创建配置
Config config = new Config();
//本地模式
LocalCluster cluster = new LocalCluster();
//提交拓扑
cluster.submitTopology("StromRedisTopology", config, builder.createTopology());
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
cluster.killTopology("StromRedisTopology");
cluster.shutdown();
}
}