网络推广理论做网站好不好/营销技巧和话术
Code -> GitHub
https://github.com/liufengji/hbase_weibo.git
1、需求分析
1) 微博内容的浏览,数据库表设计
2) 用户社交体现:关注用户,取关用户
3) 拉取关注的人的微博内容
2、代码设计总览
1) 创建命名空间以及表名的定义
2) 创建微博内容表
3) 创建用户关系表
4) 创建用户微博内容接收邮件表
5) 发布微博内容
6) 添加关注用户
7) 移除(取关)用户
8) 获取关注的人的微博内容
9) 测试
3、创建命名空间以及表名的定义
//获取配置conf
private Configuration conf = HBaseConfiguration.create();
//微博内容表的表名
private static final byte[] TABLE_CONTENT = Bytes.toBytes("ns_weibo:content");
//用户关系表的表名
private static final byte[] TABLE_RELATION = Bytes.toBytes("ns_weibo:relation");
//微博收件箱表的表名
private static final byte[] TABLE_INBOX = Bytes.toBytes("ns_weibo:inbox");/*** 初始化命名空间* @param args*/
public void initNamespace(){HBaseAdmin admin = null;try {Connection connection = ConnectionFactory.createConnection(conf);admin = (HBaseAdmin) connection.getAdmin();//命名空间类似于关系型数据库中的schema,可以想象成文件夹NamespaceDescriptor weibo = NamespaceDescriptor.create("ns_weibo").addConfiguration("creator", "Jinji").addConfiguration("create_time", System.currentTimeMillis() + "").build();admin.createNamespace(weibo);} catch (MasterNotRunningException e) {e.printStackTrace();} catch (ZooKeeperConnectionException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally{if(null != admin){try {admin.close();} catch (IOException e) {e.printStackTrace();}}}
}
4、创建微博内容表
表结构
方法名 | creatTableeContent |
---|---|
Table Name | ns_weibo:content |
RowKey | 用户ID_时间戳 |
ColumnFamily | info |
ColumnLabel | 标题,内容,图片 |
Version | 1个版本 |
代码
/*** 创建微博内容表* Table Name:ns_weibo:content* RowKey:用户ID_时间戳* ColumnFamily:info* ColumnLabel:标题,内容,图片URL* Version:1个版本*/
public void createTableContent(){HBaseAdmin admin = null;Connection connection = null;try {connection = ConnectionFactory.createConnection(conf);admin = (HBaseAdmin) connection.getAdmin();//创建表表述HTableDescriptor contentTableDescriptor = new HTableDescriptor(TableName.valueOf(TABLE_CONTENT));//创建列族描述HColumnDescriptor infoColumnDescriptor = new HColumnDescriptor(Bytes.toBytes("info"));//设置块缓存infoColumnDescriptor.setBlockCacheEnabled(true);//设置块缓存大小infoColumnDescriptor.setBlocksize(2097152);//设置压缩方式
// infoColumnDescriptor.setCompressionType(Algorithm.SNAPPY);//设置版本确界infoColumnDescriptor.setMaxVersions(1);infoColumnDescriptor.setMinVersions(1);contentTableDescriptor.addFamily(infoColumnDescriptor);admin.createTable(contentTableDescriptor);} catch (IOException e) {e.printStackTrace();} finally{if(null != admin){try {admin.close();connection.close();} catch (IOException e) {e.printStackTrace();}}}
}
5、创建用户关系表
表结构
方法名 | createTableRelations |
---|---|
Table Name | ns_weibo:relation |
RowKey | 用户ID |
ColumnFamily | attends、fans |
ColumnLabel | 关注用户ID,粉丝用户ID |
ColumnValue | 用户ID |
Version | 1个版本 |
代码
/*** 用户关系表* Table Name:ns_weibo:relation* RowKey:用户ID* ColumnFamily:attends,fans* ColumnLabel:关注用户ID,粉丝用户ID* ColumnValue:用户ID* Version:1个版本*/
public void createTableRelation(){HBaseAdmin admin = null;try {Connection connection = ConnectionFactory.createConnection(conf);admin = (HBaseAdmin) connection.getAdmin();HTableDescriptor relationTableDescriptor = new HTableDescriptor(TableName.valueOf(TABLE_RELATION));//关注的人的列族HColumnDescriptor attendColumnDescriptor = new HColumnDescriptor(Bytes.toBytes("attends"));//设置块缓存attendColumnDescriptor.setBlockCacheEnabled(true);//设置块缓存大小attendColumnDescriptor.setBlocksize(2097152);//设置压缩方式
// attendColumnDescriptor.setCompressionType(Algorithm.SNAPPY);//设置版本确界attendColumnDescriptor.setMaxVersions(1);attendColumnDescriptor.setMinVersions(1);//粉丝列族HColumnDescriptor fansColumnDescriptor = new HColumnDescriptor(Bytes.toBytes("fans"));fansColumnDescriptor.setBlockCacheEnabled(true);fansColumnDescriptor.setBlocksize(2097152);fansColumnDescriptor.setMaxVersions(1);fansColumnDescriptor.setMinVersions(1);relationTableDescriptor.addFamily(attendColumnDescriptor);relationTableDescriptor.addFamily(fansColumnDescriptor);admin.createTable(relationTableDescriptor);} catch (MasterNotRunningException e) {e.printStackTrace();} catch (ZooKeeperConnectionException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally{if(null != admin){try {admin.close();} catch (IOException e) {e.printStackTrace();}}}
}
6、创建微博收件箱表
表结构
方法名 | createTableInbox |
---|---|
Table Name | ns_weibo:inbox |
RowKey | 用户ID |
ColumnFamily | info |
ColumnLabel | 用户ID |
ColumnValue | 取微博内容的RowKey |
Version | 1000 |
代码
/*** 创建微博收件箱表* Table Name: ns_weibo:inbox* RowKey:用户ID* ColumnFamily:info* ColumnLabel:用户ID_发布微博的人的用户ID* ColumnValue:关注的人的微博的RowKey* Version:1000*/
public void createTableInbox(){HBaseAdmin admin = null;try {Connection connection = ConnectionFactory.createConnection(conf);admin = (HBaseAdmin) connection.getAdmin();HTableDescriptor inboxTableDescriptor = new HTableDescriptor(TableName.valueOf(TABLE_INBOX));HColumnDescriptor infoColumnDescriptor = new HColumnDescriptor(Bytes.toBytes("info"));infoColumnDescriptor.setBlockCacheEnabled(true);infoColumnDescriptor.setBlocksize(2097152);infoColumnDescriptor.setMaxVersions(1000);infoColumnDescriptor.setMinVersions(1000);inboxTableDescriptor.addFamily(infoColumnDescriptor);;admin.createTable(inboxTableDescriptor);} catch (MasterNotRunningException e) {e.printStackTrace();} catch (ZooKeeperConnectionException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally{if(null != admin){try {admin.close();} catch (IOException e) {e.printStackTrace();}}}
}
7、发布微博内容
a、微博内容表中添加1条数据
b、微博收件箱表对所有粉丝用户添加数据
代码 Message.java
package com.z.hbase.weibo;public class Message {private String uid;private String timestamp;private String content;public String getUid() {return uid;}public void setUid(String uid) {this.uid = uid;}public String getTimestamp() {return timestamp;}public void setTimestamp(String timestamp) {this.timestamp = timestamp;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}@Overridepublic String toString() {return "Message [uid=" + uid + ", timestamp=" + timestamp + ", content=" + content + "]";}
}
代码
/*** 发布微博* a、微博内容表中数据+1* b、向微博收件箱表中加入微博的Rowkey*/
public void publishContent(String uid, String content){Connection connection = null;try {connection = ConnectionFactory.createConnection(conf);//a、微博内容表中添加1条数据,首先获取微博内容表描述Table contentTable = connection.getTable(TableName.valueOf(TABLE_CONTENT));//组装Rowkeylong timestamp = System.currentTimeMillis();String rowKey = uid + "_" + timestamp;//添加微博内容Put put = new Put(Bytes.toBytes(rowKey));put.addColumn(Bytes.toBytes("info"), Bytes.toBytes("content"), timestamp, Bytes.toBytes(content));contentTable.put(put);//b、向微博收件箱表中加入发布的Rowkey//b.1、查询用户关系表,得到当前用户有哪些粉丝Table relationTable = connection.getTable(TableName.valueOf(TABLE_RELATION));//b.2、取出目标数据Get get = new Get(Bytes.toBytes(uid));get.addFamily(Bytes.toBytes("fans"));Result result = relationTable.get(get);List<byte[]> fans = new ArrayList<byte[]>();//遍历取出当前发布微博的用户的所有粉丝数据for(Cell cell : result.rawCells()){fans.add(CellUtil.cloneQualifier(cell));}//如果该用户没有粉丝,则直接returnif(fans.size() <= 0) return;//开始操作收件箱表Table inboxTable = connection.getTable(TableName.valueOf(TABLE_INBOX));//每一个粉丝,都要向收件箱中添加该微博的内容,所以每一个粉丝都是一个Put对象List<Put> puts = new ArrayList<Put>();for(byte[] fan : fans){Put fansPut = new Put(fan);fansPut.addColumn(Bytes.toBytes("info"), Bytes.toBytes(uid), timestamp, Bytes.toBytes(rowKey));puts.add(fansPut);}inboxTable.put(puts);} catch (IOException e) {e.printStackTrace();}finally{if(null != connection){try {connection.close();} catch (IOException e) {e.printStackTrace();}}}
}
8、添加关注用户
a、在微博用户关系表中,对当前主动操作的用户添加新关注的好友
b、在微博用户关系表中,对被关注的用户添加新的粉丝
c、微博收件箱表中添加所关注的用户发布的微博
代码实现:public void addAttends(String uid, String... attends)
/*** 关注用户逻辑* a、在微博用户关系表中,对当前主动操作的用户添加新的关注的好友* b、在微博用户关系表中,对被关注的用户添加粉丝(当前操作的用户)* c、当前操作用户的微博收件箱添加所关注的用户发布的微博rowkey*/
public void addAttends(String uid, String... attends){//参数过滤if(attends == null || attends.length <= 0 || uid == null || uid.length() <= 0){return;}Connection connection = null;try {connection = ConnectionFactory.createConnection(conf);//用户关系表操作对象(连接到用户关系表)Table relationTable = connection.getTable(TableName.valueOf(TABLE_RELATION));List<Put> puts = new ArrayList<Put>();//a、在微博用户关系表中,添加新关注的好友Put attendPut = new Put(Bytes.toBytes(uid));for(String attend : attends){//为当前用户添加关注的人attendPut.addColumn(Bytes.toBytes("attends"), Bytes.toBytes(attend), Bytes.toBytes(attend));//b、为被关注的人,添加粉丝Put fansPut = new Put(Bytes.toBytes(attend));fansPut.addColumn(Bytes.toBytes("fans"), Bytes.toBytes(uid), Bytes.toBytes(uid));//将所有关注的人一个一个的添加到puts(List)集合中puts.add(fansPut);}puts.add(attendPut);relationTable.put(puts);//c.1、微博收件箱添加关注的用户发布的微博内容(content)的rowkeyTable contentTable = connection.getTable(TableName.valueOf(TABLE_CONTENT));Scan scan = new Scan();//用于存放取出来的关注的人所发布的微博的rowkeyList<byte[]> rowkeys = new ArrayList<byte[]>();for(String attend : attends){//过滤扫描rowkey,即:前置位匹配被关注的人的uid_RowFilter filter = new RowFilter(CompareFilter.CompareOp.EQUAL, new SubstringComparator(attend + "_"));//为扫描对象指定过滤规则scan.setFilter(filter);//通过扫描对象得到scannerResultScanner result = contentTable.getScanner(scan);//迭代器遍历扫描出来的结果集Iterator<Result> iterator = result.iterator();while(iterator.hasNext()){//取出每一个符合扫描结果的那一行数据Result r = iterator.next();for(Cell cell : r.rawCells()){//将得到的rowkey放置于集合容器中rowkeys.add(CellUtil.cloneRow(cell));}}}//c.2、将取出的微博rowkey放置于当前操作的用户的收件箱中if(rowkeys.size() <= 0) return;//得到微博收件箱表的操作对象Table inboxTable = connection.getTable(TableName.valueOf(TABLE_INBOX));//用于存放多个关注的用户的发布的多条微博rowkey信息List<Put> inboxPutList = new ArrayList<Put>();for(byte[] rk : rowkeys){Put put = new Put(Bytes.toBytes(uid));//uid_timestampString rowKey = Bytes.toString(rk);//截取uidString attendUID = rowKey.substring(0, rowKey.indexOf("_"));long timestamp = Long.parseLong(rowKey.substring(rowKey.indexOf("_") + 1));//将微博rowkey添加到指定单元格中put.addColumn(Bytes.toBytes("info"), Bytes.toBytes(attendUID), timestamp, rk);inboxPutList.add(put);}inboxTable.put(inboxPutList);} catch (IOException e) {e.printStackTrace();}finally{if(null != connection){try {connection.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
}
9、移除(取关)用户
a、在微博用户关系表中,对当前主动操作的用户移除取关的好友(attends)
b、在微博用户关系表中,对被取关的用户移除粉丝
c、微博收件箱中删除取关的用户发布的微博
代码
/*** 取消关注(remove)* a、在微博用户关系表中,对当前主动操作的用户删除对应取关的好友* b、在微博用户关系表中,对被取消关注的人删除粉丝(当前操作人)* c、从收件箱中,删除取关的人的微博的rowkey* */
public void removeAttends(String uid, String... attends){//过滤数据if(uid == null || uid.length() <= 0 || attends == null || attends.length <= 0) return;try {Connection connection = ConnectionFactory.createConnection(conf);//a、在微博用户关系表中,删除已关注的好友Table relationTable = connection.getTable(TableName.valueOf(TABLE_RELATION));//待删除的用户关系表中的所有数据List<Delete> deleteList = new ArrayList<Delete>();//当前取关操作者的uid对应的Delete对象Delete attendDelete = new Delete(Bytes.toBytes(uid));//遍历取关,同时每次取关都要将被取关的人的粉丝-1for(String attend : attends){attendDelete.addColumn(Bytes.toBytes("attends"), Bytes.toBytes(attend));//b、在微博用户关系表中,对被取消关注的人删除粉丝(当前操作人)Delete fansDelete = new Delete(Bytes.toBytes(attend));fansDelete.addColumn(Bytes.toBytes("fans"), Bytes.toBytes(uid));deleteList.add(fansDelete);}deleteList.add(attendDelete);relationTable.delete(deleteList);//c、删除取关的人的微博rowkey 从 收件箱表中Table inboxTable = connection.getTable(TableName.valueOf(TABLE_INBOX));Delete inboxDelete = new Delete(Bytes.toBytes(uid));for(String attend : attends){inboxDelete.addColumn(Bytes.toBytes("info"), Bytes.toBytes(attend));}inboxTable.delete(inboxDelete);} catch (IOException e) {e.printStackTrace();}
}
10、获取关注的人的微博内容
a、从微博收件箱中获取所关注的用户的微博RowKey
b、根据获取的RowKey,得到微博内容
代码实现
/*** 获取微博实际内容* a、从微博收件箱中获取所有关注的人的发布的微博的rowkey* b、根据得到的rowkey去微博内容表中得到数据* c、将得到的数据封装到Message对象中*/
public List<Message> getAttendsContent(String uid){Connection connection = null;try {connection = ConnectionFactory.createConnection(conf);Table inboxTable = connection.getTable(TableName.valueOf(TABLE_INBOX));//a、从收件箱中取得微博rowKeyGet get = new Get(Bytes.toBytes(uid));//设置最大版本号get.setMaxVersions(5);List<byte[]> rowkeys = new ArrayList<byte[]>();Result result = inboxTable.get(get);for(Cell cell : result.rawCells()){rowkeys.add(CellUtil.cloneValue(cell));}//b、根据取出的所有rowkey去微博内容表中检索数据Table contentTable = connection.getTable(TableName.valueOf(TABLE_CONTENT));List<Get> gets = new ArrayList<Get>();//根据rowkey取出对应微博的具体内容for(byte[] rk : rowkeys){Get g = new Get(rk);gets.add(g);}//得到所有的微博内容的result对象Result[] results = contentTable.get(gets);//将每一条微博内容都封装为消息对象List<Message> messages = new ArrayList<Message>();for(Result res : results){for(Cell cell : res.rawCells()){Message message = new Message();String rowKey = Bytes.toString(CellUtil.cloneRow(cell));String userid = rowKey.substring(0, rowKey.indexOf("_"));String timestamp = rowKey.substring(rowKey.indexOf("_") + 1);String content = Bytes.toString(CellUtil.cloneValue(cell));message.setContent(content);message.setTimestamp(timestamp);message.setUid(userid);messages.add(message);}}return messages;} catch (IOException e) {e.printStackTrace();}finally{try {connection.close();} catch (IOException e) {e.printStackTrace();}}return null;
}
11、测试
-- 测试发布微博内容
public void testPublishContent(WeiBo wb)
-- 测试添加关注
public void testAddAttend(WeiBo wb)
-- 测试取消关注
public void testRemoveAttend(WeiBo wb)
-- 测试展示内容
public void testShowMessage(WeiBo wb)
代码
/*** 发布微博内容* 添加关注* 取消关注* 展示内容*/
public void testPublishContent(WeiBo wb){wb.publishContent("0001", "今天买了一包空气,送了点薯片,非常开心!!");wb.publishContent("0001", "今天天气不错。");
}public void testAddAttend(WeiBo wb){wb.publishContent("0008", "准备下课!");wb.publishContent("0009", "准备关机!");wb.addAttends("0001", "0008", "0009");
}public void testRemoveAttend(WeiBo wb){wb.removeAttends("0001", "0008");
}public void testShowMessage(WeiBo wb){List<Message> messages = wb.getAttendsContent("0001");for(Message message : messages){System.out.println(message);}
}public static void main(String[] args) {WeiBo weibo = new WeiBo();weibo.initTable(); weibo.testPublishContent(weibo);weibo.testAddAttend(weibo);weibo.testShowMessage(weibo);weibo.testRemoveAttend(weibo);weibo.testShowMessage(weibo);
}