HBase 项目

微博系统

1.需求分析

    1) 微博内容的浏览,数据库表设计

    2) 用户社交体现:关注用户,取关用户

    3) 拉取关注的人的微博内容

 

2.代码实现( 代码设计总览)

    1) 创建命名空间以及表名的定义

    2) 创建微博内容表

    3) 创建用户关系表

    4) 创建用户微博内容接收邮件表

    5) 发布微博内容

    6) 添加关注用户

    7) 移除(取关)用户

    8) 获取关注的人的微博内容

    9) 测试

 

3.具体代码实现

1) 创建命名空间以及表名的定义

//获取配置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();

                     }

              }

       }

}

 

2) 创建微博内容表

    表结构:

方法名

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();

                     }

              }

       }

}

 

3) 创建用户关系表

    表结构:

方法名

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();

                     }

              }

       }

}

 

4) 创建微博收件箱表

    表结构:

方法名

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();

                     }

              }

       }

}

 

5) 发布微博内容

    a、微博内容表中添加1条数据

    b、微博收件箱表对所有粉丝用户添加数据

    代码:Message.java

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;

       }

       @Override

       public String toString() {

              return "Message [uid=" + uid + ", timestamp=" + timestamp + ", content=" + content + "]";

       }

}

    代码:public void publishContent(String uid, String 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));

              //组装Rowkey

              long 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));

              }

              //如果该用户没有粉丝,则直接return

              if(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();

                     }

              }

       }

}

6) 添加关注用户

    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)的rowkey

              Table contentTable = connection.getTable(TableName.valueOf(TABLE_CONTENT));

              Scan scan = new Scan();

              //用于存放取出来的关注的人所发布的微博的rowkey

              List<byte[]> rowkeys = new ArrayList<byte[]>();

             

              for(String attend : attends){

                     //过滤扫描rowkey,即:前置位匹配被关注的人的uid_

                     RowFilter filter = new RowFilter(CompareFilter.CompareOp.EQUAL, new SubstringComparator(attend + "_"));

                     //为扫描对象指定过滤规则

                     scan.setFilter(filter);

                     //通过扫描对象得到scanner

                     ResultScanner 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_timestamp

                     String rowKey = Bytes.toString(rk);

                     //截取uid

                     String 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 block

                            e.printStackTrace();

                     }

              }

       }

}

 

7) 移除(取关)用户

    a、在微博用户关系表中,对当前主动操作的用户移除取关的好友(attends)

    b、在微博用户关系表中,对被取关的用户移除粉丝

    c、微博收件箱中删除取关的用户发布的微博

    代码:public void removeAttends(String uid, String... attends)

/**

 * 取消关注(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));

              //遍历取关,同时每次取关都要将被取关的人的粉丝-1

              for(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();

       }

}

 

 8) 获取关注的人的微博内容

        a、从微博收件箱中获取所关注的用户的微博RowKey

        b、根据获取的RowKey,得到微博内容

        代码实现:public List<Message> getAttendsContent(String uid)

/**

 * 获取微博实际内容

 * 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、从收件箱中取得微博rowKey

              Get 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;

}

 

9) 测试

/**

 * 发布微博内容

 * 添加关注

 * 取消关注

 * 展示内容

 */

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);

}

 

4.源码下载地址:https://github.com/luomingkui/hbase

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员学习圈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值