zoukankan      html  css  js  c++  java
  • HBase案例-谷粒微博(尚硅谷)

    1 需求分析

    模拟微博运行过程,可以实现发布微博、关注/取关用户、查看用户微博内容等功能。

    2 数据表设计

    共设计3张表,分别是微博内容表、用户关系表、微博收件箱表。

    2.1 微博内容表

    设计一个列族info,包含一个列Content,用于存放发布的微博内容。行键设计为用户id+时间戳,每行数据表示某个用户在某一时刻发布的微博内容。所有用户发布的所有微博内容均存储在一张表中。

    2.2 用户关系表

    设计两个列族attends、fans,表示当前用户的关注者和粉丝。每个列族可以有很多列,每个列表示一个具体的用户,列的值与列名保持相同,仅起到标识用户的作用。行键设计为用户id。如果某个用户没有关注任何其他用户,则该行数据的attends列族为空;同样地,如果没有粉丝,则fans列族为空。

    2.3 微博收件箱表(初始化页面表)

    设计为一个列族info,可以包括多个列,分别表示当前用户关注的其他用户。行键设计为用户id,每行数据表示当前用户关注的其他用户所发布的微博内容,每列的值设置3个版本,内容为关注者所发布的微博内容的行键(uid+ts)。即列的值是第一张表(微博内容表)的外键。

    数据表示例如下:

    3 项目架构

    创建Maven工程,在pom.xml文件中添加项目所需要的依赖。

        <dependencies>
            <dependency>
                <groupId>org.apache.hbase</groupId>
                <artifactId>hbase-server</artifactId>
                <version>1.3.1</version>
            </dependency>
            <dependency>
                <groupId>org.apache.hbase</groupId>
                <artifactId>hbase-client</artifactId>
                <version>1.3.1</version>
            </dependency>
        </dependencies>

    在src/main/resources文件夹下添加配置文件hbase-site.xml,其中包含项目要连接的集群信息,这样就不用在代码里再设置了。

    在src/main/java下创建4个Java包:constants、utils、dao、test,分别表示常量、工具类、数据操作、测试。

    4 定义常量

    在constants包下创建Constants类,存放项目需要用到的常量。包括HBase配置信息、命名空间、微博内容表及其列族信息、用户关系表及其列族信息、收件箱表及其列族信息。

    public class Constants {
    
        // HBase配置信息
        public static final Configuration CONFIGURATION = HBaseConfiguration.create();
    
        // 命名空间
        public static final String NAMESPACE = "weibo";
    
        // 微博内容表
        public static final String CONTENT_TABLE = "weibo:content";
        public static final String CONTENT_TABLE_CF = "info";
        public static final int CONTENT_TABLE_VERSIONs = 1;
    
        // 用户关系表
        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;
    
        // 收件箱表
        public static final String INBOX_TABLE = "weibo:inbox";
        public static final String INBOX_TABLE_CF = "info";
        public static final int INBOX_TABLE_VERSIONS = 2;
    }

    5 HBaseUtil封装

    在utils包下创建HBaseUtil类,提供项目通用的功能,包括创建命名空间、判断表是否存在、创建表。

    public class HBaseUtil {
    
        // 1 创建命名空间
        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();
            // 5 返回结果
            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();
        }
    }

    6 HBaseDao封装

    在dao包下创建HBaseDao类,实现与业务相关的数据操作功能。

    6.1 发布微博

        // 1 发布微博
        public static void publishWeiBo(String uid, String content) throws IOException {
            Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);
    
            // 第一部分:操作微博内容表
            Table contTable = connection.getTable(TableName.valueOf(Constants.CONTENT_TABLE));
            long ts = System.currentTimeMillis();
            String rowKey = uid + "_" + ts;
            Put contPut = new Put(Bytes.toBytes(rowKey));
            contPut.addColumn(Bytes.toBytes(Constants.CONTENT_TABLE_CF), Bytes.toBytes("content"), Bytes.toBytes(content));
            contTable.put(contPut);
    
            // 第二部分:操作微博收件箱表
            Table relaTable = connection.getTable(TableName.valueOf(Constants.RELATION_TABLE));
            Get relaGet = new Get(Bytes.toBytes(uid));
            relaGet.addFamily(Bytes.toBytes(Constants.RELATION_TABLE_CF2));
            Result result = relaTable.get(relaGet);
    
            ArrayList<Put> inboxPuts = new ArrayList<>();
    
            for (Cell cell : result.rawCells()) {
                Put inboxPut = new Put(CellUtil.cloneQualifier(cell));
                inboxPut.addColumn(Bytes.toBytes(Constants.INBOX_TABLE_CF), Bytes.toBytes(uid), Bytes.toBytes(rowKey));
                inboxPuts.add(inboxPut);
            }
            // 判断当前uid是否有粉丝
            if (inboxPuts.size() > 0){
                Table inboxTable = connection.getTable(TableName.valueOf(Constants.INBOX_TABLE));
                inboxTable.put(inboxPuts);
                inboxTable.close();
            }
    
            // 关闭资源
            relaTable.close();
            contTable.close();
            connection.close();
        }

    难点是要同时操作3张表,要处理3张表之间的联系。某个uid用户发布了一条微博,系统做了这些事情:在微博内容表中,添加一条数据;在用户关系表中,查找uid的fans用户;在微博收件箱表中,为所有fans用户更新当前uid用户的微博发布信息。

    微博内容表中,行键设计为uid+时间戳。

            Table contTable = connection.getTable(TableName.valueOf(Constants.CONTENT_TABLE));
            long ts = System.currentTimeMillis();
            String rowKey = uid + "_" + ts;
            Put contPut = new Put(Bytes.toBytes(rowKey));
            contPut.addColumn(Bytes.toBytes(Constants.CONTENT_TABLE_CF), Bytes.toBytes("content"), Bytes.toBytes(content));
            contTable.put(contPut);

    在用户关系表中,查找当前uid的fans信息。遍历每一个粉丝,在微博收件箱表中为每个粉丝更新uid用户的微博发布信息。构建Get对象,行键为uid,列族为fans,传入用户关系表中,返回一个result对象,其中包含uid的所有粉丝信息。

            Table relaTable = connection.getTable(TableName.valueOf(Constants.RELATION_TABLE));
            Get relaGet = new Get(Bytes.toBytes(uid));
            relaGet.addFamily(Bytes.toBytes(Constants.RELATION_TABLE_CF2));
            Result result = relaTable.get(relaGet);

    解析result对象,获取每一个cell对象,每个cell对象包含列族fans中的各列的列名及列的值。将获取到的粉丝信息作为新的行键,构建微博收件箱表的Put对象,列族为info,列名为当前用户的uid,值是当前新添加微博的行键(uid+时间戳)。每一个Put对象存放在创建的ArrayList列表中。循环遍历每一个粉丝,进行如上操作。

            ArrayList<Put> inboxPuts = new ArrayList<>();
    
            for (Cell cell : result.rawCells()) {
                Put inboxPut = new Put(CellUtil.cloneQualifier(cell));
                inboxPut.addColumn(Bytes.toBytes(Constants.INBOX_TABLE_CF), Bytes.toBytes(uid), Bytes.toBytes(rowKey));
                inboxPuts.add(inboxPut);
            }

    如果当前uid用户没有粉丝(ArrayList列表为空),则不对微博收件箱表做任何操作。否则,获取微博收件箱表对象,并将ArrayList列表中的Put对象传入到微博收件箱表中。

            // 判断当前uid是否有粉丝
            if (inboxPuts.size() > 0){
                Table inboxTable = connection.getTable(TableName.valueOf(Constants.INBOX_TABLE));
                inboxTable.put(inboxPuts);
                inboxTable.close();
            }

    最后,关闭资源。

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

    6.2 关注用户

        // 2 关注用户
        public static void addAttends(String uid, String... attends) throws IOException {
            if (attends.length <= 0) {
                System.out.println("请传入要关注的人");
                return;
            }
    
            Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);
    
            // 添加uid用户的关注人,且同步更新关注人的粉丝信息
            Table relaTable = connection.getTable(TableName.valueOf(Constants.RELATION_TABLE));
            Put attendPut = new Put(Bytes.toBytes(uid));
            ArrayList<Put> relaPuts = new ArrayList<>();
            for (String attend : attends) {  // 对于每一个attend对象,要同时做两件事情
                attendPut.addColumn(Bytes.toBytes(Constants.RELATION_TABLE_CF1), Bytes.toBytes(attend), Bytes.toBytes(attend));
    
                Put fanPut = new Put(Bytes.toBytes(attend));
                fanPut.addColumn(Bytes.toBytes(Constants.RELATION_TABLE_CF2), Bytes.toBytes(uid), Bytes.toBytes(uid));
                relaPuts.add(fanPut);
            }
            relaPuts.add(attendPut);  // 对于同一行数据,可以一次添加多个列
            relaTable.put(relaPuts);
    
            // 更新微博收件箱表信息
            Table contTable = connection.getTable(TableName.valueOf(Constants.CONTENT_TABLE));
            Put inboxPut = new Put(Bytes.toBytes(uid));
            for (String attend : attends) {
                Scan scan = new Scan(Bytes.toBytes(attend + "_"), Bytes.toBytes(attend + "|"));
                ResultScanner resultScanner = contTable.getScanner(scan);
    
                // 定义一个时间戳,以解决多条数据同一时间戳的问题
                long ts = System.currentTimeMillis();
    
                for (Result result : resultScanner) {
                    inboxPut.addColumn(Bytes.toBytes(Constants.INBOX_TABLE_CF), Bytes.toBytes(attend), ts++, result.getRow());
                }
            }
            // 判断uid所关注的人是否有发过微博
            if (!inboxPut.isEmpty()) {
                Table inboxTable = connection.getTable(TableName.valueOf(Constants.INBOX_TABLE));
                inboxTable.put(inboxPut);
                inboxTable.close();
            }
    
            // 关闭资源
            relaTable.close();
            contTable.close();
            connection.close();
        }

    关注用户同样需要操作3张表。在用户关系表中,当前uid用户在attends列族中添加若干个用户,同时这些用户在fans列族中添加当前uid用户。此外,在微博收件箱表中,以当前uid用户为行键,在列族info中添加若干个列,每列表示一个关注人,每列的值存放此关注人发布的微博的行键(版本存放2条)。

    循环遍历传入的attends参数,在每一次遍历中要同时做两件事情。一是为uid添加关注人,二是为关注人添加粉丝(uid)。这个地方要注意,对于同一行数据,Put对象可以分步骤添加多个列。而对于不同行数据,需要分别创建Put对象并添加到ArrayList<Put>列表中,之后再传入至用户关系表对象中。

            // 添加uid用户的关注人,且同步更新关注人的粉丝信息
            Table relaTable = connection.getTable(TableName.valueOf(Constants.RELATION_TABLE));
            Put attendPut = new Put(Bytes.toBytes(uid));
            ArrayList<Put> relaPuts = new ArrayList<>();
            for (String attend : attends) {  // 对于每一个attend对象,要同时做两件事情
                attendPut.addColumn(Bytes.toBytes(Constants.RELATION_TABLE_CF1), Bytes.toBytes(attend), Bytes.toBytes(attend));
    
                Put fanPut = new Put(Bytes.toBytes(attend));
                fanPut.addColumn(Bytes.toBytes(Constants.RELATION_TABLE_CF2), Bytes.toBytes(uid), Bytes.toBytes(uid));
                relaPuts.add(fanPut);
            }
            relaPuts.add(attendPut);  // 对于同一行数据,可以一次添加多个列
            relaTable.put(relaPuts);

    在微博收件箱表中,对于当前uid用户,为其添加新关注的人,并更新这些人发布的微博信息。这两个信息分别由列名和列值承载,所以可以通过一个Put对象同时添加。新关注人发布的微博信息通过Scan对象获取,指定起始和终止的行键,根据字典序的排序规则以及微博内容表中“uid+时间戳”的行键设计规则,设计起始行键为“attend_”,终止行键为“attend|”,其中attend是要关注的人。这样设计可以获取到某个用户所发布的全部微博的行键(字典序,有比没有大,而且字符|大于字符_)。微博内容表的getScanner()方法返回ResultScanner对象,其中包含若干个Result对象。每一个Result对象表示一行数据,包含所需要的行键信息。手动定义一个时间戳,以解决多条数据同一时间戳的问题。最后,如果当前uid用户新关注的人都没有发布过微博,则不用对微博收件箱表做任何操作;当至少有一条微博时,才进行后续操作。

            // 更新微博收件箱表信息
            Table contTable = connection.getTable(TableName.valueOf(Constants.CONTENT_TABLE));
            Put inboxPut = new Put(Bytes.toBytes(uid));
            for (String attend : attends) {
                Scan scan = new Scan(Bytes.toBytes(attend + "_"), Bytes.toBytes(attend + "|"));
                ResultScanner resultScanner = contTable.getScanner(scan);
    
                // 定义一个时间戳,以解决多条数据同一时间戳的问题
                long ts = System.currentTimeMillis();
    
                for (Result result : resultScanner) {
                    inboxPut.addColumn(Bytes.toBytes(Constants.INBOX_TABLE_CF), Bytes.toBytes(attend), ts++, result.getRow());
                }
            }
            // 判断uid新关注的人是否有发过微博
            if (!inboxPut.isEmpty()) {
                Table inboxTable = connection.getTable(TableName.valueOf(Constants.INBOX_TABLE));
                inboxTable.put(inboxPut);
                inboxTable.close();
            }
    
            // 关闭资源
            relaTable.close();
            contTable.close();
            connection.close();

    6.3 取关用户

        // 3 取关用户
        public static void deleteAttends(String uid, String... dels) throws IOException {
            if (dels.length <= 0) {
                System.out.println("请传入要取关的用户");
                return;
            }
    
            Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);
    
            // 更新用户关系表
            Table relaTable = connection.getTable(TableName.valueOf(Constants.RELATION_TABLE));
            Delete uidDelete = new Delete(Bytes.toBytes(uid));
    
            ArrayList<Delete> attendDeletes = new ArrayList<>();
    
            for (String del : dels) {
                uidDelete.addColumns(Bytes.toBytes(Constants.RELATION_TABLE_CF1), Bytes.toBytes(del));
    
                Delete attendDelete = new Delete(Bytes.toBytes(del));
                attendDelete.addColumns(Bytes.toBytes(Constants.RELATION_TABLE_CF2), Bytes.toBytes(uid));
                attendDeletes.add(attendDelete);
            }
            relaTable.delete(uidDelete);
            relaTable.delete(attendDeletes);
    
            // 更新微博收件箱表
            Table inboxTable = connection.getTable(TableName.valueOf(Constants.INBOX_TABLE));
            Delete inboxDelete = new Delete(Bytes.toBytes(uid));
            for (String del : dels) {
                inboxDelete.addColumns(Bytes.toBytes(Constants.INBOX_TABLE_CF), Bytes.toBytes(del));
            }
            inboxTable.delete(inboxDelete);
    
            // 关闭资源
            inboxTable.close();
            relaTable.close();
            connection.close();
        }

    与关注用户逻辑类似,但更简单些,因为只涉及到用户关系表和微博收件箱表两张表。其中,调用了Delete对象的addColumns()方法而不是addColumn()方法,addColumns()方法可以同时删掉多个版本。

    6.4 获取某个人的初始化页面数据

        // 4 获取某个人的初始化页面数据
        public static void getInit(String uid) throws IOException {
            Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);
    
            Table contTable = connection.getTable(TableName.valueOf(Constants.CONTENT_TABLE));
            Table inboxTable = connection.getTable(TableName.valueOf(Constants.INBOX_TABLE));
            Get inboxGet = new Get(Bytes.toBytes(uid));
            inboxGet.setMaxVersions();  // 为Get对象设置最大版本
            Result result = inboxTable.get(inboxGet);
    
            for (Cell cell : result.rawCells()) {
                Get contGet = new Get(CellUtil.cloneValue(cell));
                Result contResult = contTable.get(contGet);
                for (Cell contCell : contResult.rawCells()) {
                    System.out.println("RK:" + Bytes.toString(CellUtil.cloneRow(contCell))+
                            ", ColumnFamily:" + Bytes.toString(CellUtil.cloneFamily(contCell)) +
                            ", ColumnName:" + Bytes.toString(CellUtil.cloneQualifier(contCell)) +
                            ", value:" + Bytes.toString(CellUtil.cloneValue(contCell)));
                }
            }
    
            // 关闭资源
            inboxTable.close();
            contTable.close();
            connection.close();
        }

    根据当前uid用户遍历微博收件箱表,找到其关注的所有人,打印出这些人发布的若干条微博数据(由版本数控制)。

    创建Get对象,传入uid作为行键,并设置最大版本。传入收件箱表对象,返回一个Result对象,其中包含uid所关注的所有用户的若干条微博的行键。

            Table contTable = connection.getTable(TableName.valueOf(Constants.CONTENT_TABLE));
            Table inboxTable = connection.getTable(TableName.valueOf(Constants.INBOX_TABLE));
            Get inboxGet = new Get(Bytes.toBytes(uid));
            inboxGet.setMaxVersions();  // 为Get对象设置最大版本
            Result result = inboxTable.get(inboxGet);

    获取result对象的所有Cell对象,每一个Cell对象包含一条微博数据的一个行键。遍历所有Cell对象,获取微博数据的行键,之后再微博内容表中根据行键找到相应微博数据,此时返回一个Result对象。这个Result对象只包含一个Cell对象(Cell是HBase中的概念,是由列族、列名、时间戳唯一确定的单元),获取这个Cell对象,进一步地获取行键、列族、列名、值的信息。这里的难点在于对Result和Cell的理解。

            for (Cell cell : result.rawCells()) {
                Get contGet = new Get(CellUtil.cloneValue(cell));
                Result contResult = contTable.get(contGet);
                for (Cell contCell : contResult.rawCells()) {
                    System.out.println("RK:" + Bytes.toString(CellUtil.cloneRow(contCell))+
                            ", ColumnFamily:" + Bytes.toString(CellUtil.cloneFamily(contCell)) +
                            ", ColumnName:" + Bytes.toString(CellUtil.cloneQualifier(contCell)) +
                            ", value:" + Bytes.toString(CellUtil.cloneValue(contCell)));
                }
            }
    
            // 关闭资源
            inboxTable.close();
            contTable.close();
            connection.close();

    6.5 获取某个人的所有微博详情

        // 5 获取某个人的所有微博详情
        public static void getWeiBo(String uid) throws IOException {
            Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);
    
            Table contTable = connection.getTable(TableName.valueOf(Constants.CONTENT_TABLE));
    
            // 使用Scan起始终止行键的方法
            // Scan scan = new Scan(Bytes.toBytes(uid + "_"), Bytes.toBytes(uid + "|"));
            Scan scan = new Scan();
            // 构建过滤器
            RowFilter rowFilter = new RowFilter(CompareFilter.CompareOp.EQUAL, new SubstringComparator(uid + "_"));
            scan.setFilter(rowFilter);
            ResultScanner resultScanner = contTable.getScanner(scan);
    
            for (Result result : resultScanner) {
                for (Cell contCell : result.rawCells()) {
                    System.out.println("RK:" + Bytes.toString(CellUtil.cloneRow(contCell))+
                            ", ColumnFamily:" + Bytes.toString(CellUtil.cloneFamily(contCell)) +
                            ", ColumnName:" + Bytes.toString(CellUtil.cloneQualifier(contCell)) +
                            ", Value:" + Bytes.toString(CellUtil.cloneValue(contCell)));
                }
            }
    
            // 关闭资源
            contTable.close();
            connection.close();
        }

    可以使用Scan起始终止行键的方法,也可以使用过滤器的方法。这里创建一个行键过滤器RowFilter,第一个参数传入比较符,第二个参数传入要比较的对象。之后通过setFilter()方法为Scan对象添加过滤器。

            Scan scan = new Scan();
            // 构建过滤器
            RowFilter rowFilter = new RowFilter(CompareFilter.CompareOp.EQUAL, new SubstringComparator(uid + "_"));
            scan.setFilter(rowFilter);
            ResultScanner resultScanner = contTable.getScanner(scan);

    7 测试代码

    在test包下新建TestWeiBo类,存放程序主函数。

    public class TestWeiBo {
        public static void init() {
            try {
                // 创建命名空间
                HBaseUtil.createNamespace(Constants.NAMESPACE);
                // 创建微博内容表
                HBaseUtil.createTable(Constants.CONTENT_TABLE, Constants.CONTENT_TABLE_VERSIONS, 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条微博
            Thread.sleep(10);
            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的第三条微博");
            // 获取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");
            System.out.println("------------555------------");
            // 获取1003微博详情
            HBaseDao.getWeiBo("1003");
        }
    }

    程序运行结果如下:(结果有点不对,还没有解决这个问题..


    参考:尚硅谷HBase教程(hbase框架快速入门)

  • 相关阅读:
    2018年3月20日java
    2018年3月19日Java
    浏览器执行js代码的机制--对于我们深入了解js有很大的帮助,同时面试时候也都能用得到。
    如果用css的border属性画一个三角形
    js事件(event)的运行原理
    如何通过源生js获取一个元素的具体样式值 /* getCss:获取指定元素的具体样式的属性值 curElement:[dom对象] attr:[string] */
    js创建对象的高级模式
    查看release的SHA1
    集成百度地图定位和导航功能时出现包冲突
    【十次方基础教程(后台)】MongoDB相关
  • 原文地址:https://www.cnblogs.com/wangmengdx/p/15140498.html
Copyright © 2011-2022 走看看