需求分析

1) 微博内容的浏览,数据库表设计
2) 用户社交体现:关注用户,取关用户
3) 拉取关注的人的微博内容

表结构

代码实现

1) 创建命名空间以及表名的定义
2) 创建微博内容表
3) 创建用户关系表
4) 创建用户微博内容接收邮件表
5) 发布微博内容
6) 添加关注用户
7) 移除(取关)用户
8) 获取关注的人的微博内容
9) 测试

项目结构

pom.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId>
<artifactId>hbase-pro</artifactId>
<version>1.0-SNAPSHOT</version> <properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.10</version>
</dependency> <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency> <dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.3</version>
</dependency> <dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.12</artifactId>
<version>2.4.4</version>
</dependency> <dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency> <dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.70</version>
</dependency> <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency> <dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>1.3.1</version>
</dependency> <dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-server</artifactId>
<version>1.3.1</version>
</dependency>
</dependencies> </project>

1. 常量类 Constants

package deng.com.constants;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration; public class Constants {
// HBase 的配置信息
public static final Configuration CONFIGURATION = HBaseConfiguration.create();
static {
CONFIGURATION.set("hbase.zookeeper.quorum", "192.168.10.102");
CONFIGURATION.set("hbase.zookeeper.property.clientPort", "2181");
}
// 命名空间
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:info";
public static final String INBOX_TABLE_CF="info";
public static final int INBOX_TABLE_VERSIONS=2; }

2. HBaseUtils 类(创建表,判断表是否存在等)

package deng.com.utils;

import deng.com.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; public class HBaseUtils { //创建命名空间
public static void createNameSpace(String nameSpace) throws IOException {
// 1. 获取连接对象
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 = ConnectionFactory.createConnection(Constants.CONFIGURATION);
// 2. 获取admin
Admin admin = connection.getAdmin();
// 3.判读是否存在
boolean b = admin.tableExists(TableName.valueOf(tableName));
// 4. 关闭资源
admin.close();
connection.close();
return b;
} // 3. 创建表
public static void createTable(String tableName, int versions, String... cf) throws IOException {
// 判读是否传入了列族信息
if (cf.length <= 0) {
System.out.println("请传入列族信息");
return;
} // 判断表是否存在
if (isTableExist(tableName)) {
System.out.println(tableName + "表已存在");
return;
} // 1. 获取连接对象
Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);
// Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);
// 2. 获取admin
Admin admin = connection.getAdmin();
// 3. 创建表描述器
HTableDescriptor hTableDescriptor = new HTableDescriptor(TableName.valueOf(tableName));
// 4. 循环添加列族信息
for (String s : cf) {
// 获取列族描述器
HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(s);
// 设置版本
hColumnDescriptor.setMaxVersions(versions);
hTableDescriptor.addFamily(hColumnDescriptor); } // 创建表
admin.createTable(hTableDescriptor);
admin.close();
connection.close();
}
}

3. HbaseDao类(业务操作)

package deng.com.dao;

/*
* 1.发布微博
* 2. 删除微博
* 3. 关注用户
* 4. 取关用户
* 5.获取用户微博详情
* 6.获取用户的初始页面
*/ import com.sun.xml.internal.bind.v2.runtime.reflect.opt.Const;
import deng.com.constants.Constants;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.HConstants;
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.Filter;
import org.apache.hadoop.hbase.filter.RowFilter;
import org.apache.hadoop.hbase.filter.SubstringComparator;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.yarn.webapp.hamlet.HamletSpec; import java.io.IOException;
import java.util.ArrayList; public class HBaseDao {
// 1. 发布微博
public static void publishWeiBo(String uuid, String content) throws IOException {
// 获取Connection 对象
Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);
// 第一部分 操作微博内容表 // 获取微博内容表对象
Table conTable = connection.getTable(TableName.valueOf(Constants.CONTENT_TABLE));
// content 表的rowkey 是用户id+时间戳
// 获取当前时间
long ts = System.currentTimeMillis();
// 拼接rowKey
String rowKey = uuid + "_" + ts;
// 创建Put 对象
Put conPut = new Put(Bytes.toBytes(rowKey));
// 给put 对象赋值
conPut.addColumn(Bytes.toBytes(Constants.CONTENT_TABLE_CF), Bytes.toBytes("content"), Bytes.toBytes(content)); // 插入数据
conTable.put(conPut); // 第二部分 操作微博收件箱表
// 1. 获取用户关系表对象
Table relationTable = connection.getTable(TableName.valueOf(Constants.RELATION_TABLE));
// 2. 获取当前发布微博人的fans列族数据
Get get = new Get(Bytes.toBytes(uuid));
get.addFamily(Bytes.toBytes(Constants.RELATION_TABLE_CF2)); // 指定fans 那个列族
Result result = relationTable.get(get);
// 创建一个集合用于存放微博内容表Put对象
ArrayList<Put> inboxPuts = new ArrayList<>();
Cell[] cells = result.rawCells();
// 遍历粉丝
for (Cell cell : cells) {
// 构建微博收件箱表的put对象
Put inboxPut = new Put(CellUtil.cloneQualifier(cell));
// 给收件箱的putd对象赋值
inboxPut.addColumn(Bytes.toBytes(Constants.INBOX_TABLE_CF), Bytes.toBytes(uuid), Bytes.toBytes(rowKey));
// 收件箱表的put对象存入表中
inboxPuts.add(inboxPut); }
// 判断是否有粉丝
if (inboxPuts.size() > 0) {
// 获取收件箱表对象
Table inboxTable = connection.getTable(TableName.valueOf(Constants.INBOX_TABLE));
//执行收件箱表数据插入
inboxTable.put(inboxPuts);
// 关闭收件箱表
inboxTable.close();
}
// 关闭资源
relationTable.close();
conTable.close();
connection.close(); } public static void addAttends(String uuid, String... attends) throws IOException {
// 校验
if (attends.length <= 0) {
System.out.println("请选择关注的人!");
return;
}
// 第一部分:操作用户关系表
//1. 获取用户关系表对象
Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);
Table relaTable = connection.getTable(TableName.valueOf(Constants.RELATION_TABLE)); //2. 创建一个集合用于存放用户关系表对象
ArrayList<Put> relaPuts = new ArrayList<>();
//3. 创建操作者的Put对象
Put uuidPut = new Put(Bytes.toBytes(uuid));
//4. 循环创建被关注者的put 对象
for (String attend : attends) { //5. 给操作者put 对象赋值
uuidPut.addColumn(Bytes.toBytes(Constants.RELATION_TABLE_CF1), Bytes.toBytes(attend), Bytes.toBytes(attend));
//6. 创建被关注者的put对象
Put attendPut = new Put(Bytes.toBytes(attend));
//7. 给被关注者对象赋值
attendPut.addColumn(Bytes.toBytes(Constants.RELATION_TABLE_CF2), Bytes.toBytes(uuid), Bytes.toBytes(uuid));
//8. 将被关注者对象放入集合
relaPuts.add(attendPut);
} //9 .将操作者的put对象添加至集合
relaPuts.add(uuidPut); //10. 执行用户关系表的插入操作
relaTable.put(relaPuts); // 第二部分:收件箱表
// 1. 获取微博内容表对象
Table conTable = connection.getTable(TableName.valueOf(Constants.CONTENT_TABLE));
// 2. 创建收件箱表的put对象
Put inboxPut = new Put(Bytes.toBytes(uuid));
// 3. 循环attends 获取每个被关注者近期发布的微博内容
for (String attend : attends) {
// 4. 获取当前被关注近期发布的微博内容
Scan scan = new Scan(Bytes.toBytes(attend + "_"), Bytes.toBytes(attend + "|"));// startrow ,endrow
ResultScanner resultScanner = conTable.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();
}
// 关闭资源
conTable.close();
relaTable.close();
connection.close(); }
} // 取关
public static void delAttends(String uid, String... dels) throws IOException {
if(dels.length<=0){
System.out.println("请添加取关用户!");
return;
}
//获取连接对象
Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);
// 第一部分:操作用户关系表
// 1. 获取用户关系表对象
Table relTable = connection.getTable(TableName.valueOf(Constants.RELATION_TABLE));
// 2. 创建一个集合,用户存放用户关系表的delete对象
ArrayList<Delete> relDeletes = new ArrayList<>();
// 3. 创建操作delete对象
Delete uidDelete = new Delete(Bytes.toBytes(uid));
// 4. 循环创建被取关的delete对象
for (String del : dels) {
// 5. 给操作者delete对象赋值
uidDelete.addColumns(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(uid));
// 8. 将被取关者delete对象添加至集合
relDeletes.add(delDelete); }
// 9. 将操作者的Delete对象添加至集合
relDeletes.add(uidDelete);
// 10.执行删除操作
relTable.delete(relDeletes); // 第二部分:操作收件箱表
// 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); // 5. 关闭资源
inboxTable.close();
relTable.close();
connection.close();
}
// 获取某人的初始化页面数据
public static void getInt(String uid) throws IOException {
//获取connection 对象
Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);
// 1. 收件箱表对象
Table inboxTable = connection.getTable(TableName.valueOf(Constants.INBOX_TABLE)); // 2. 获取内容表对象
Table conTable = connection.getTable(TableName.valueOf(Constants.CONTENT_TABLE));
// 3. 创建收件箱表的Get对象,并获取数据(set最大版本获取)
Get inboxGet = new Get(Bytes.toBytes(uid));
inboxGet.setMaxVersions();
// 4. 获取该get对象的内容
Result result = inboxTable.get(inboxGet);
// 5. 遍历获取到数据
for (Cell cell : result.rawCells()) {
// 6. 构建微博内容表get对象
Get conGet = new Get(CellUtil.cloneValue(cell));
// 7. 获取该get对象的内容
Result result1 = conTable.get(conGet);
// 8. 解析并打印
for (Cell rawCell : result1.rawCells()) {
System.out.println(
"RK:"+Bytes.toString(CellUtil.cloneRow(rawCell))+","+
"CF:"+Bytes.toString(CellUtil.cloneFamily(rawCell))+","+
"cn:"+Bytes.toString(CellUtil.cloneQualifier(rawCell))+","+
"value:"+Bytes.toString(CellUtil.cloneValue(rawCell))
);
} }
//6. 关闭资源
inboxTable.close();
conTable.close();
connection.close(); }
// 获取某人的所有微博详情
public static void getWeiBo(String uid) throws IOException {
// 获取连接对象
Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);
// 1. 获取内容表 Table conTable = connection.getTable(TableName.valueOf(Constants.CONTENT_TABLE));
// 2. 构建scan 对象
Scan scan = new Scan();
// 构建过滤器
Filter rowFilter = new RowFilter(CompareFilter.CompareOp.EQUAL,new SubstringComparator(uid+"_"));
scan.setFilter(rowFilter); // 3. 获取数据
ResultScanner scanner = conTable.getScanner(scan);
// 4. 解析数据并打印
for (Result result : scanner) {
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))
);
}
}
// 5. 关闭资源
conTable.close();
connection.close(); }
}

4. 测试类TestWeiBo

package deng.com.test;

import deng.com.constants.Constants;
import deng.com.utils.HBaseUtils; import java.io.IOException; import static deng.com.dao.HBaseDao.*; public class TestWeiBO {
public static void init() throws IOException {
// 创建命名空间
// HBaseUtils.createNameSpace(Constants.NAMESPACE);
// 创建微博内容表
HBaseUtils.createTable(Constants.CONTENT_TABLE,Constants.CONTENT_TABLE_VERSIONS,Constants.CONTENT_TABLE_CF); // 创建用户关系表
HBaseUtils.createTable(Constants.RELATION_TABLE,Constants.RELATION_TABLE_VERSIONS,Constants.RELATION_TABLE_CF1,Constants.RELATION_TABLE_CF2); // 创建收件箱表
HBaseUtils.createTable(Constants.INBOX_TABLE,Constants.INBOX_TABLE_VERSIONS,Constants.INBOX_TABLE_CF);
} public static void main(String[] args) throws IOException {
// 初始化
init();
// 1001 发布微博
publishWeiBo("1001","快来上课"); // 1002 关注1001和1003
// addAttends("1002","1001","1003"); // 获取1002 初始化页面
getInt("1002");
System.out.println("================1111================");
// getWeiBo("1001"); // 1003 发布3条微博 。同时1001 发布两条微博v哦
publishWeiBo("1003","我是1003 : 今天天气真好");
publishWeiBo("1003","我是1003 : 一起去海边玩吧");
publishWeiBo("1003","我是1003 : 走,开车去");
publishWeiBo("1001","我是1001:我才不去");
publishWeiBo("1001","我是1001:要去你自己去");
// 获取1002 初始化页面
getInt("1002");
System.out.println("================2222================"); // 1002 取关1003
delAttends("1002","1003"); // 获取1002 初始化页面
getInt("1002");
System.out.println("================3333================");
// 1002 再次关注1003
addAttends("1002","1003");
System.out.println("================4444===============");
// 获取1001 详情
getWeiBo("1001"); }
}

Hbase 项目的更多相关文章

  1. hbase项目

    四.HBase 项目4.1.涉及概念梳理:命名空间4.1.1.命名空间的结构 1) Table:表,所有的表都是命名空间的成员,即表必属于某个命名空间,如果没有指定, 则在 default 默认的命名 ...

  2. 【HBase学习】Apache HBase项目简介

    原创声明:转载请注明作者和原始链接 http://www.cnblogs.com/zhangningbo/p/4068957.html       英文原版:http://hbase.apache.o ...

  3. Hadoo生态中pHive HBase 项目的区别

    http://jenmhdn.iteye.com/blog/1678789 导读:Apache Hive是一个构建于Hadoop(分布式系统基础架构)顶层的数据仓库,Apache HBase是运行于H ...

  4. Hbase项目(完整版)

    涉及概念梳理:命名空间 4.1.1.命名空间的结构 1) Table:表,所有的表都是命名空间的成员,即表必属于某个命名空间,如果没有指定,则在default默认的命名空间中. 2) RegionSe ...

  5. 【Hadoop学习】Apache HBase项目简介

    正在撰写,稍后来访……

  6. HBase笔记:对HBase原理的简单理解

    早些时候学习hadoop的技术,我一直对里面两项技术倍感困惑,一个是zookeeper,一个就是Hbase了.现在有机会专职做大数据相关的项目,终于看到了HBase实战的项目,也因此有机会搞懂Hbas ...

  7. HBase应用开发回顾与总结系列之一:概述HBase设计规范

      概述 笔者本人接触研究HBase也有半年之久了,虽说不上深入和系统,但至少算是比较沉迷.作为部门里大数据技术的探路者,笔者还要承担起技术传播的职责,所以在摸索研究的过程中总是不断地进行总结和测试, ...

  8. HBase学习(十四)LINUX下用Eclipse构建HBase开发环境

    Eclipse,HBase版本号眼下没有发现须要特别指定 1:从HBase集群中复制一份Hbase部署文件,放置在开发端某一文件夹下(如在/app/hadoop/hbase096文件夹下). 2:在e ...

  9. Phoenix(sql on hbase)简单介绍

    Phoenix(sql on hbase)简单介绍 介绍: Phoenix is a SQL skin over HBase delivered as a client-embedded JDBC d ...

随机推荐

  1. 自我学习与理解:keras框架下的深度学习(三)回归问题

    本文主要是使用keras对其有的波士顿房价数据集做一个回归预测,其代码架构与之前一样(都只是使用多层感知机):数据的预处理.搭建网络框架.编译.循环训练以及测试训练的网络模型.其中除了数据预处理与之前 ...

  2. 手把手一步一步教你使用Java开发一个大型街机动作闯关类游戏01游戏窗口

    项目源码 项目源码 游戏配置信息类 Config.java 没什么解释的. package config; public class Config { public final static Stri ...

  3. 【LeetCode】剑指 Offer 04. 二维数组中的查找

    二维数组查找:线性查找法 有二维数组: [  [1,   4,  7, 11, 15],  [2,   5,  8, 12, 19],  [3,   6,  9, 16, 22],  [10, 13, ...

  4. Mind the Box: $\ell_1$-APGD for Sparse Adversarial Attacks on Image Classifiers

    目录 概 主要内容 Croce F. and Hein M. Mind the box: \(\ell_1\)-APGD for sparse adversarial attacks on image ...

  5. 在ABP VNext框架中对HttpApi模块的控制器进行基类封装

    在ABP VNext框架中,HttpApi项目是我们作为Restful格式的控制器对象的封装项目,但往往很多案例都是简单的继承基类控制器AbpControllerBase,而需要在每个控制器里面重写很 ...

  6. 贪心学院计算机视觉CV训练营

    贪心学院计算机视觉CV训练营 任务 Notes 其他 任务1:机器学习.深度学习简介 Note1 任务2:深度学习的发展历史 Note2 任务3:现代深度学习的典型例子 Note3 任务4:深度学习在 ...

  7. HAproxy开启日志记录

    1.说明 HAproxy在默认情况不会记录日志, 不仅要在haproxy.conf中配置日志输出, 还需要修改系统日志的配置文件. 2.修改haproxy.conf 在haproxy.conf文件中增 ...

  8. [数据结构]FHQ-Treap

    前言(个人评价FHQ-Treap) 这是一个巨佬(名叫范浩强)在冬令营交流的时候提出的数据结构(FHQ:\(\text{你干嘛非要旋转呢?Think Functional!}\))(可以看出FHQ大佬 ...

  9. 在git上下载的源码项目,运行时报错AssertionError [ERR_ASSERTION] [ERR_ASSERTION]: Task function must be specified

    原因是gulp3 和gulp4的运行方式不一样, 解决方法: 1.修改package.json文件中gulp的版本为最新版本 2.删除node_modules文件夹和package-lock.json ...

  10. Nginx日志配置及日志分析脚本案例

    https://blog.csdn.net/bbwangj/article/details/82186162 nginx的log日志分为access log 和 error log 其中access ...