HBase项目案例之微博

HBase项目案例之微博

笔者配置

Hadoop3.1.3+HBase2.2.2
IDEA本地运行
没有写运行配置,我是在resorces里添加文件,可以看另一篇文章的步骤一
HBase整合MR本地IDEA运行

思路

三张表用来存储数据
微博内容表:CONTENT_TABLE
用户关系表:RELATION_TABLE
收件箱表:INBOX_TABLE

微博内容表:content

用来存储用户发布的内容

    //微博内容表
    public static final String CONTENT_TABLE = "weibo:content";
    public static final String CONTENT_TABLE_CF = "info";
    public static final int CONTENT_TABLE_VERSION = 1;

用户关系表:relation

用来存储用户的关注和粉丝,分为两个列族,列名和值是一样的

    //用户关系表
    public static final String RELATION_TABLE = "weibo:relation";
    public static final String RELATION_TABLE_CF1 = "attends";
    public static final String RELATION_TABLE_CF2 = "fans";
    public static final int RELATION_TABLE_VERSIONS = 1;

收件箱表:inbox

用来存储用户的关注的人的微博,rowkey是用户,info:name,name是指关注的人,value是关注的人的最新微博,根据name去查找content表,找最新的内容的rowkey,然后放进inbox表的value值里。
INBOX_TABLE_VERSIONS是设置保存的版本数,所以即使覆盖了,还是可以看同一个用户的两条微博。

    //收件箱表
    public static final String INBOX_TABLE = "weibo:inbox";
    public static final String INBOX_TABLE_CF = "info";
    public static final int INBOX_TABLE_VERSIONS = 2;

代码结构

在这里插入图片描述

Constants.java

package com.lmr.constants;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;

public class Constants {

    //HBase的配置信息
    public static final Configuration CONFIGURATION = HBaseConfiguration.create();

    //命名空间
    public static final String NAMESPACE = "weibo1";

    //微博内容表
    public static final String CONTENT_TABLE = "weibo1:content";
    public static final String CONTENT_TABLE_CF = "info";
    public static final int CONTENT_TABLE_VERSION = 1;

    //用户关系表
    public static final String RELATION_TABLE = "weibo1:relation";
    public static final String RELATION_TABLE_CF1 = "attends";
    public static final String RELATION_TABLE_CF2 = "fans";
    public static final int RELATION_TABLE_VERSIONS = 1;

    //收件箱表
    public static final String INBOX_TABLE = "weibo1:inbox";
    public static final String INBOX_TABLE_CF = "info";
    public static final int INBOX_TABLE_VERSIONS = 2;

}

HBaseUtil.java

package com.lmr.utils;

import com.lmr.constants.Constants;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.NamespaceDescriptor;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;

import java.io.IOException;

/**
 * 1.创建命名空间
 * 2.判断表是否存在
 * 3.创建表(三张表)
 */
public class HBaseUtil {

    public static void createNameSpace(String nameSpace) throws IOException {

        //1.获取Connection对象
        Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);

        //2.获取Admin对象
        Admin admin = connection.getAdmin();

        //3.构建命名空间描述器
        NamespaceDescriptor namespaceDescriptor = NamespaceDescriptor.create(nameSpace).build();

        //4.创建命名空间
        admin.createNamespace(namespaceDescriptor);

        //5.关闭资源
        admin.close();
        connection.close();
    }

    //2.判断表是否存在
    private static boolean isTableExist(String tableName) throws IOException {

        //1.获取Connection对象
        Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);

        //2.获取Admin对象
        Admin admin = connection.getAdmin();

        //3.判断表是否存在
        boolean exists = admin.tableExists(TableName.valueOf(tableName));

        //4.关闭资源
        admin.close();
        connection.close();

        //返回结果
        return exists;
    }

    //3.创建表
    public static void createTable(String tableName, int versions, String... cfs ) throws IOException {

        //1.判断是否传入了列族信息
        if (cfs.length <= 0){
            System.out.println("请设置列族信息!!!");
            return;
        }

        //2.判断表是否存在
        if (isTableExist(tableName)){
            System.out.println(tableName + "表已存在");
            return;
        }

        //3.获取Connection对象
        Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);

        //4.获取Admin对象
        Admin admin = connection.getAdmin();

        //5.创建表描述器
        HTableDescriptor hTableDescriptor = new HTableDescriptor(TableName.valueOf(tableName));

        //6.添加列族信息
        for (String cf : cfs) {

            HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(cf);

            //7.设置版本
            hColumnDescriptor.setMaxVersions(versions);

            hTableDescriptor.addFamily(hColumnDescriptor);
        }

        //8.创建表操作
        admin.createTable(hTableDescriptor);

        //9.关闭资源
        admin.close();
        connection.close();

    }
}

HBaseDao.java

package com.lmr.dao;

import com.lmr.constants.Constants;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.filter.CompareFilter;
import org.apache.hadoop.hbase.filter.RowFilter;
import org.apache.hadoop.hbase.filter.SubstringComparator;
import org.apache.hadoop.hbase.util.Bytes;

import java.io.IOException;
import java.util.ArrayList;

/**
 * 1.发布微博
 * 2.删除微博
 * 3.关注用户
 * 4.取关用户
 * 5.获取用户的初始化页面
 * 6.获取用户微博详情
 */
public class HBaseDao {

    //1.发布微博
    public static void publishWeiBo(String uid, String content) throws IOException {

        //获取Connection对象
        Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);

        //第一部分:操作微博内容表
        //1.获取微博内容表对象
        Table contTable = connection.getTable(TableName.valueOf(Constants.CONTENT_TABLE));

        //2.获取当前时间戳
        long ts = System.currentTimeMillis();

        //3.获取RowKey
        String rowKey = uid + "_" + ts;

        //4.创建Put对象
        Put contPut = new Put(Bytes.toBytes(rowKey));

        //5.给Put对象赋值
        contPut.addColumn(Bytes.toBytes(Constants.CONTENT_TABLE_CF), Bytes.toBytes("content"), Bytes.toBytes(content));

        //6.执行插入数据操作
        contTable.put(contPut);


        //第二部分:操作微博收件箱表
        //1.获取用户关系表对象
        Table relaTable = connection.getTable(TableName.valueOf(Constants.RELATION_TABLE));

        //2.获取当前发布微博人的fans列族数据
        Get get = new Get(Bytes.toBytes(uid));
        get.addFamily(Bytes.toBytes(Constants.RELATION_TABLE_CF2));
        Result result = relaTable.get(get);

        //3.创建一个集合,用于存放微博内容表的Put对象
        ArrayList<Put> inboxPuts = new ArrayList<>();

        //4.遍历粉丝
        for (Cell cell : result.rawCells()) {

            //5.构建微博收件箱表的Put对象
            Put inboxPut = new Put(CellUtil.cloneQualifier(cell));

            //6.给收件箱表的Put对象赋值
            inboxPut.addColumn(Bytes.toBytes(Constants.INBOX_TABLE_CF), Bytes.toBytes(uid), Bytes.toBytes(rowKey));

            //7.将收件箱表的Put对象存入集合
            inboxPuts.add(inboxPut);
        }

        //8.判断是否有粉丝
        if (inboxPuts.size() > 0){

            //获取收件箱对象
            Table inboxTable = connection.getTable(TableName.valueOf(Constants.INBOX_TABLE));

            //执行收件箱表数据插入操作
            inboxTable.put(inboxPuts);

            //关闭收件箱表
            inboxTable.close();
        }

        //关闭资源
        relaTable.close();
        contTable.close();
        connection.close();

    }

    //2.关注用户
    public static void addAttends(String uid, String... attends) throws IOException {

        //校验是否添加了待关注的人
        if (attends.length <= 0){
            System.out.println("请选择待关注的人!!!");
            return;
        }

        //获取Connection对象
        Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);

        //第一部分:操作用户关系表
        //1.获取用户关系表对象
        Table relaTable = connection.getTable(TableName.valueOf(Constants.RELATION_TABLE));

        //2.创建一个集合,用于存放用户关系表的Put对象
        ArrayList<Put> relaPuts = new ArrayList<>();

        //3.创建操作者的Put对象
        Put uidPut = new Put(Bytes.toBytes(uid));

        //4.循环创建被关注者的Put对象
        for (String attend : attends) {

            //5.给操作者的Put对象赋值
            uidPut.addColumn(Bytes.toBytes(Constants.RELATION_TABLE_CF1), Bytes.toBytes(attend), Bytes.toBytes(attend));

            //6.创建被关注着的Put对象
            Put attendPut = new Put(Bytes.toBytes(attend));

            //7.给被关注者的Put对象赋值
            attendPut.addColumn(Bytes.toBytes(Constants.RELATION_TABLE_CF2), Bytes.toBytes(uid), Bytes.toBytes(uid));

            //8.将被关注者的Put对象放入集合
            relaPuts.add(attendPut);

        }

        //9.将操作者的Put对象添加至集合
        relaPuts.add(uidPut);

        //10.执行用户关系表的插入数据操作
        relaTable.put(relaPuts);


        //第二部分:操作收件箱表
        //1.获取微博内容表对象
        Table contTable = connection.getTable(TableName.valueOf(Constants.CONTENT_TABLE));

        //2.创建收件箱表的Put对象
        Put inboxPut = new Put(Bytes.toBytes(uid));

        //3.循环attends,获取每个被关注者的近期发布的微博
        for (String attend : attends) {

            //4.获取当前被关注者的近期发布的微博(scan)-> 集合ResultScanner
            Scan scan = new Scan(Bytes.toBytes(attend + "_"), Bytes.toBytes(attend + "|"));
            ResultScanner resultScanner = contTable.getScanner(scan);

            //定义一个时间戳
            long ts = System.currentTimeMillis();

            //5.对获取的值进行遍历
            for (Result result : resultScanner) {

                //6.给收件箱表的Put对象赋值
                inboxPut.addColumn(Bytes.toBytes(Constants.INBOX_TABLE_CF), Bytes.toBytes(attend), ts++,  result.getRow());

            }


        }


        //7.判断当前的Put对象是否为空
        if (!inboxPut.isEmpty()){

            //获取收件箱表的对象
            Table inboxTable = connection.getTable(TableName.valueOf(Constants.INBOX_TABLE));

            //插入数据
            inboxTable.put(inboxPut);

            //关闭收件箱表连接
            inboxTable.close();

        }

        //关闭资源
        relaTable.close();
        contTable.close();
        connection.close();

    }


    //3.取关
    public static void deleteAttends(String uid, String... dels) throws IOException {

        if (dels.length <= 0){
            System.out.println("请添加待取关的用户!!!");
            return;
        }

        //获取Connection对象
        Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);

        //第一部分
        //1.获取用户关系表对象
        Table relaTable = connection.getTable(TableName.valueOf(Constants.RELATION_TABLE));

        //2.创建一个集合,用于存放用户关系表的Delete对象
        ArrayList<Delete> relaDeletes = new ArrayList<>();

        //3.创建操作者的Delete对象
        Delete uidDelete = new Delete(Bytes.toBytes(uid));

        //4.循环创建被取关者的Delete对象

        for (String del : dels) {

            //5.给操作者的Delete对象赋值
            uidDelete.addColumn(Bytes.toBytes(Constants.RELATION_TABLE_CF1), Bytes.toBytes(del));

            //6.创建被取关者的Delete对象
            Delete delDelete = new Delete(Bytes.toBytes(del));

            //7.给被取关者的Delete对象赋值
            delDelete.addColumns(Bytes.toBytes(Constants.RELATION_TABLE_CF2), Bytes.toBytes(del));

            //8.将被取关者的Delete对象添加至集合
            relaDeletes.add(delDelete);
        }

        //9.将操作者的Delete对象添加至集合
        relaDeletes.add(uidDelete);

        //10.执行用户关系表的删除操作
        relaTable.delete(relaDeletes);

        //第二部分:操作收件箱表
        //1.获取收件箱表对象
        Table inboxTable = connection.getTable(TableName.valueOf(Constants.INBOX_TABLE));

        //2.创建操作者的Delete对象
        Delete inboxDelete = new Delete(Bytes.toBytes(uid));

        //3.给操作者的Delete对象赋值
        for (String del : dels) {
            inboxDelete.addColumns(Bytes.toBytes(Constants.INBOX_TABLE_CF), Bytes.toBytes(del));
        }

        //4.执行收件箱表的删除操作
        inboxTable.delete(inboxDelete);

        //关闭资源
        relaTable.close();
        inboxTable.close();
        connection.close();

    }


    //4.获取某个人的初始化页面数据
    public static void getInit(String uid) throws IOException {

        //1.获取Connection对象
        Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);

        //2.获取收件箱表对象
        Table inboxTable = connection.getTable(TableName.valueOf(Constants.INBOX_TABLE));

        //3.获取微博内容表对象
        Table contTable = connection.getTable(TableName.valueOf(Constants.CONTENT_TABLE));

        //4.创建收件箱表Get对象,并获取数据(设置最大版本)
        Get inboxGet = new Get(Bytes.toBytes(uid));
        inboxGet.setMaxVersions();
        Result result = inboxTable.get(inboxGet);

        //5.遍历获取的数据
        for (Cell cell : result.rawCells()) {


            //6.构建微博内容表Get对象
            Get contGet = new Get(CellUtil.cloneValue(cell));   //获取关注的人的微博内容的值

            //7.获取该Get对象的数据内容
            Result contResult = contTable.get(contGet);   //再把关注的人微博内容的值的数据内容

            //8.解析内容并打印
            for (Cell contCell : contResult.rawCells()) {


                System.out.println("RK:" + Bytes.toString(CellUtil.cloneRow(contCell)) +
                        ",CF:" + Bytes.toString(CellUtil.cloneFamily(contCell)) +
                        ",CN:" + Bytes.toString(CellUtil.cloneQualifier(contCell)) +
                        ",Value:" + Bytes.toString(CellUtil.cloneValue(contCell)));

            }
        }

        //9.关闭资源
        inboxTable.close();
        contTable.close();
        connection.close();

    }


    //5.获取某个人的所有微博详情
    public static void getWeiBo(String uid) throws IOException {

        //1.获取Connection对象
        Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);

        //2.获取微博内容对象
        Table table = connection.getTable(TableName.valueOf(Constants.CONTENT_TABLE));

        //3.构建Scan对象
        Scan scan = new Scan();

        //构建过滤器
        RowFilter rowFilter = new RowFilter(CompareFilter.CompareOp.EQUAL, new SubstringComparator(uid + "_"));

        scan.setFilter(rowFilter);

        //4.获取数据
        ResultScanner resultScanner = table.getScanner(scan);

        //5.解析数据并打印
        for (Result result : resultScanner) {
            for (Cell cell : result.rawCells()) {
                System.out.println("RK:" + Bytes.toString(CellUtil.cloneRow(cell)) +
                        ",CF:" + Bytes.toString(CellUtil.cloneFamily(cell)) +
                        ",CN:" + Bytes.toString(CellUtil.cloneQualifier(cell)) +
                        ",Value:" + Bytes.toString(CellUtil.cloneValue(cell)));
            }
        }

        //6.关闭资源
        table.close();
        connection.close();
    }
}

TestWeiBo

package com.lmr.test;

import com.lmr.constants.Constants;
import com.lmr.dao.HBaseDao;
import com.lmr.utils.HBaseUtil;

import java.io.IOException;

public class TestWeiBo {

    public static void init(){


        try {
            //创建命名空间
            HBaseUtil.createNameSpace(Constants.NAMESPACE);

            //创建微博内容表
            HBaseUtil.createTable(Constants.CONTENT_TABLE, Constants.CONTENT_TABLE_VERSION, Constants.CONTENT_TABLE_CF);

            //创建用户关系表
            HBaseUtil.createTable(Constants.RELATION_TABLE, Constants.RELATION_TABLE_VERSIONS, Constants.RELATION_TABLE_CF1, Constants.RELATION_TABLE_CF2);

            //创建收件箱表
            HBaseUtil.createTable(Constants.INBOX_TABLE, Constants.INBOX_TABLE_VERSIONS, Constants.INBOX_TABLE_CF);


        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws IOException, InterruptedException {

//        初始化
        init();

//        1001发布微博
        HBaseDao.publishWeiBo("1001", "1001第一的微博!!!");

//        1002关注1001和1003
        HBaseDao.addAttends("1002", "1001", "1003");

        //获取1002初始化页面
        HBaseDao.getInit("1002");

        System.out.println("*******************111*******************");

        //1003发布3条微博,同时1001发布2条微博
        HBaseDao.publishWeiBo("1003", "1003第一的微博!!!");
        Thread.sleep(10);

        HBaseDao.publishWeiBo("1001", "1001第二的微博!!!");
        Thread.sleep(10);

        HBaseDao.publishWeiBo("1003", "1003第二的微博!!!");
        Thread.sleep(10);

        HBaseDao.publishWeiBo("1001", "1001第三的微博!!!");
        Thread.sleep(10);

        HBaseDao.publishWeiBo("1003", "1003第三的微博!!!");
        Thread.sleep(10);

        //获取1002初始化页面
        HBaseDao.getInit("1002");

        System.out.println("*******************222*******************");

        //1002取关1003
        HBaseDao.deleteAttends("1002", "1003");

        //获取1002初始化页面
        HBaseDao.getInit("1002");
        System.out.println("*******************333*******************");

        //1002再次关注1003
        HBaseDao.addAttends("1002", "1003");

        //获取1002初始化页面
        HBaseDao.getInit("1002");
        System.out.println("*******************444*******************");

        //获取1001微博详情
        HBaseDao.getWeiBo("1001");

    }
}

代码结果

RK:1001_1642943474683,CF:info,CN:content,Value:1001第一的微博!!!
*******************111*******************
RK:1001_1642943484562,CF:info,CN:content,Value:1001第三的微博!!!
RK:1001_1642943478157,CF:info,CN:content,Value:1001第二的微博!!!
RK:1003_1642943487776,CF:info,CN:content,Value:1003第三的微博!!!
RK:1003_1642943481379,CF:info,CN:content,Value:1003第二的微博!!!
*******************222*******************
RK:1001_1642943484562,CF:info,CN:content,Value:1001第三的微博!!!
RK:1001_1642943478157,CF:info,CN:content,Value:1001第二的微博!!!
*******************333*******************
RK:1001_1642943484562,CF:info,CN:content,Value:1001第三的微博!!!
RK:1001_1642943478157,CF:info,CN:content,Value:1001第二的微博!!!
RK:1003_1642943487776,CF:info,CN:content,Value:1003第三的微博!!!
RK:1003_1642943481379,CF:info,CN:content,Value:1003第二的微博!!!
*******************444*******************
RK:1001_1642943474683,CF:info,CN:content,Value:1001第一的微博!!!
RK:1001_1642943478157,CF:info,CN:content,Value:1001第二的微博!!!
RK:1001_1642943484562,CF:info,CN:content,Value:1001第三的微博!!!
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值