Apache HBase 是 Java 语言编写的一款 Apache 开源的 NoSQL 型数据库,不支持 SQL,不支持事务,不支持 Join 操作,没有表关系。Apache HBase 构建在 Apache Hadoop 和 Apache Zookeeper 之上。
Apache HBase: https://hbase.apache.org/
HBase 的安装配置,请参考 “Springboot 系列 (24) - Springboot+HBase 大数据存储(二)| 安装配置 Apache HBase 和 Apache Zookeeper”。
本文将创建一个 SpringBoot 项目,演示通过 RestTemplate 访问 “Springboot 系列 (27) - Springboot+HBase 大数据存储(五)| HBase REST 服务” 里通过 curl 命令测试过的 HBase REST 服务。
1. 系统环境
操作系统:Ubuntu 20.04
Hadoop 版本:3.2.2
Zookeeper 版本:3.6.3
HBase 版本:2.4.4
HBase 所在路径:~/apps/hbase-2.4.4/
本文使用的 HBase 部署在伪分布式 Hadoop 架构上(主机名:hadoop-master-vm),在 HBase + Zookeeper (独立的) 模式下运行,Zookeeper 使用端口 2182,HBase REST 服务使用端口 8888。
2. 创建 Spring Boot 基础项目
项目实例名称:SpringbootExample22
Spring Boot 版本:2.6.6
创建步骤:
(1) 创建 Maven 项目实例 SpringbootExample22;
(2) Spring Boot Web 配置;
(3) 导入 Thymeleaf 依赖包;
(4) 配置 jQuery;
具体操作请参考 “Springboot 系列 (2) - 在 Spring Boot 项目里使用 Thymeleaf、JQuery+Bootstrap 和国际化” 里的项目实例 SpringbootExample02,文末包含如何使用 spring-boot-maven-plugin 插件运行打包的内容。
SpringbootExample22 和 SpringbootExample02 相比,SpringbootExample22 不配置 Bootstrap、模版文件(templates/*.html)和国际化。
3. 配置 RestTemplate
RestTemplate 默认配置是使用了 JDK 自带的 HttpURLConnection 作为底层 HTTP 客户端实现。可以通过 setRequestFactory 属性来切换使用不同的 HTTP 库,如 Apache HttpComponents、OkHttp、Netty 等。
如何切换 RestTemplate 的底层库,可以参考 “Springboot 系列 (18) - 在 Spring Boot 项目里使用 RestTemplate 访问 REST 服务”。
1) 使用默认配置
创建 src/main/java/com/example/config/RestTemplateConfig.java 文件
package com.example.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@ConditionalOnMissingBean(RestTemplate.class)
@Bean
public RestTemplate restTemplate(){
RestTemplate restTemplate = new RestTemplate();
return restTemplate;
}
}
2) 修改 src/main/resources/application.properties 文件,内容如下
spring.main.banner-mode=off
# Web server
server.display-name=SpringbootExample22
server.address=localhost
server.port=9090
# HBase Rest Server
hbase.rest.url=http://hadoop-master-vm:8888
注:这里 hbase.rest.url 使用了 REST 服务器所在的主机名 hadoop-master-vm,可以替换成 REST 服务器所在主机的 IP 地址。
3) 运行
Edit Configurations
Click "+" add new configuration -> Select "Maven"
Command line: clean spring-boot:run
Name: SpringbootExample22 [clean,spring-boot:run]
-> Apply / OK
Click Run "SpringbootExample22 [clean,spring-boot:run]"
...
Spring boot example project
访问 http://localhost:9090/test
Test Page
注:打包可以将 Command line 改成 clean package spring-boot:repackage
4. 测试实例 (Web 模式)
创建的一个 demo 表,demo 表包含 cf1,cf2 两个列族 (Column Family) ,我们将向 demo 表添加如下数据:
id | name | age | job |
row1 | Tom | 12 | Student |
row2 | Jerry | 9 | Engineer |
row3 | Jerry | 10 | Engineer |
REST 接口在操作数据时,会对 key、column、value 等值进行 Base64 编解码,可以运行如下命令编解码:
$ echo -ne "Tom" | base64 # 编码
VG9t
$ echo -ne "VG9t" | base64 -d # 解码
Tom
注:echo 的 -n 表示不换行输出,-e 表示处理特殊字符。
以下是操作数据时使用到的 Base64 编码列表:
原值 | 编码后 |
cf1:name | Y2YxOm5hbWU= |
cf1:age | Y2YxOmFnZQ== |
cf2:job | Y2YyOmpvYg== |
row1 | cm93MQ== |
row2 | cm93Mg== |
row3 | cm93Mw== |
Tom | VG9t |
Jerry | SmVycnk= |
12 | MTI= |
9 | OQ== |
10 | MTA= |
Student | U3R1ZGVudA== |
Engineer | RW5naW5lZXI= |
1) 创建 src/main/resources/templates/client.html 文件
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title th:text="${var}">Client</title>
<script language="javascript" th:src="@{/lib/jquery/jquery-3.6.0.min.js}"></script>
</head>
<body>
<h4>HBase REST API - Client</h4>
<p> </p>
<p>
<label><strong>REST API:</strong></label><br>
<select id="otype" style="width: 50%;">
<option value=""></option>
<option value="hbase_info">1. HBase 信息</option>
<option value="table_operation">2. Table 操作</option>
<option value="data_add">3. 添加数据</option>
<option value="data_query_get">4. 查询数据 -> GET 操作</option>
<option value="data_query_scanner">5. 查询数据 -> 无状态 Scanner</option>
<option value="data_delete">6. 删除数据</option>
<option value="namespace_operation">7. Namespace 操作</option>
</select><br><br>
<button type="button" id="btn_exec" class="btn btn-default btn-sm">Execute</button>
</p>
<p> </p>
<div id="result_area" style="padding: 15px; width: 80%; font-size: 12px; min-height: 120px;">
</div>
<script type="text/javascript">
$(document).ready(function() {
$("#otype").change(function(e) {
$('#result_area').html("");
});
$("#btn_exec").click(function(e) {
var otype = $("#otype").val();
if (otype == '') {
alert("Please select REST API");
$("#otype").focus();
return;
}
var url = "";
switch(otype) {
case "hbase_info":
url = "/hbase"
break;
case "table_operation":
url = "/table"
break;
case "data_add":
url = "/data/add"
break;
case "data_query_get":
url = "/data/query/get"
break;
case "data_query_scanner":
url = "/data/query/scanner"
break;
case "data_delete":
url = "/data/delete"
break;
case "namespace_operation":
url = "/namespace"
break;
default:
break;
}
$('#result_area').append("Executing ...<br><br>");
$('#btn_exec').prop('disabled', true);
$.ajax({
type: 'GET',
url: url,
timeout: 10000,
success: function(response) {
//console.log(response);
$('#result_area').append(response + "<br>");
//$('#result_area').append(JSON.stringify(response + "<br>"));
$('#btn_exec').prop('disabled', false);
},
error: function(err) {
console.log(err);
$('#result_area').append('AJAX Error: ' + err.statusText + " " + err.status);
$('#btn_exec').prop('disabled', false);
}
});
});
});
</script>
</body>
</html>
2) 修改 src/main/java/com/example/controller/IndexController.java 文件
package com.example.controller;
import java.util.ArrayList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Controller;
//import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;
@Controller
public class IndexController {
@Autowired
private RestTemplate restTemplate;
@Value("${hbase.rest.url}")
private String hbaseRestUrl;
@ResponseBody
@RequestMapping("/test")
public String test() {
return "Test Page";
}
@RequestMapping("/client")
public String client() {
return "client";
}
@ResponseBody
@RequestMapping("/hbase")
public String hbase() {
// 显示 HBase 版本
String url = hbaseRestUrl + "/version/cluster";
System.out.println("url = " + url);
ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);
String str = "显示 HBase 版本 -> " + url + "<br>";
str += "Status Code: " + responseEntity.getStatusCode() + "<br>";
str += "Result: " + responseEntity.getBody() + "<br><br>";
// 显示 HBase 群集状态
url = hbaseRestUrl + "/status/cluster";
responseEntity = restTemplate.getForEntity(url, String.class);
str += "显示 HBase 群集状态 -> " + url + "<br>";
str += "Status Code: " + responseEntity.getStatusCode() + "<br>";
str += "Result: " + responseEntity.getBody() + "<br>";
return str;
}
@ResponseBody
@RequestMapping("/table")
public String table() {
// 头部信息
//MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
//headers.add("Accept", "application/json");
//headers.add("Content-Type", "application/json");
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
ArrayList<MediaType> acceptList = new ArrayList<>();
acceptList.add(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(acceptList);
// 参数信息
//MultiValueMap<String, String> mapParams = new LinkedMultiValueMap<>();
//HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<>(mapParams, headers);
// 查看所有表
HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<>(null, httpHeaders);
ResponseEntity<String> responseEntity = restTemplate.exchange(hbaseRestUrl, HttpMethod.GET, httpEntity, String.class);
String str = "查看所有表 -> " + hbaseRestUrl + "<br>";
str += "Status Code: " + responseEntity.getStatusCode() + "<br>";
str += "Result: " + responseEntity.getBody() + "<br><br>";
// 创建 demo 表 (1 个列族 cf1)
String url = hbaseRestUrl + "/demo/schema";
String jsonParams = "{\"name\":\"demo\",\"ColumnSchema\":[{\"name\":\"cf1\"}]}";
HttpEntity<String> httpEntity2 = new HttpEntity<>(jsonParams, httpHeaders);
responseEntity = restTemplate.exchange(url, HttpMethod.PUT, httpEntity2, String.class);
str += "创建 demo 表 (1 个列族 cf1) -> " + url + "<br>";
str += "Request Entity: " + jsonParams + "<br>";
str += "Status Code: " + responseEntity.getStatusCode() + "<br>";
str += "Result: " + responseEntity.getBody() + "<br><br>";
// 添加 2 个列族 cf2 和 cf3
jsonParams = "{\"name\":\"demo\",\"ColumnSchema\":[{\"name\":\"cf2\"},{\"name\":\"cf3\"}]}";
HttpEntity<String> httpEntity3 = new HttpEntity<>(jsonParams, httpHeaders);
responseEntity = restTemplate.exchange(url, HttpMethod.POST, httpEntity3, String.class);
str += "添加 2 个列族 cf2 和 cf3 -> " + url + "<br>";
str += "Request Entity: " + jsonParams + "<br>";
str += "Status Code: " + responseEntity.getStatusCode() + "<br>";
str += "Result: " + responseEntity.getBody() + "<br><br>";
// 删除 cf3 列族,不是使用 POST,应该使用 PUT 替换表结构
jsonParams = "{\"name\":\"demo\",\"ColumnSchema\":[{\"name\":\"cf1\"},{\"name\":\"cf2\"}]}";
HttpEntity<String> httpEntity4 = new HttpEntity<>(jsonParams, httpHeaders);
responseEntity = restTemplate.exchange(url, HttpMethod.PUT, httpEntity4, String.class);
str += "删除 cf3 列族 -> " + url + "<br>";
str += "Request Entity: " + jsonParams + "<br>";
str += "Status Code: " + responseEntity.getStatusCode() + "<br>";
str += "Result: " + responseEntity.getBody() + "<br><br>";
// 修改 cf1 列族的 VERSIONS 为 2,默认是 1 (即只保留最后一个版本)
jsonParams = "{\"name\":\"demo\",\"ColumnSchema\":[{\"name\":\"cf1\",\"VERSIONS\":\"2\"}]}";
HttpEntity<String> httpEntity5 = new HttpEntity<>(jsonParams, httpHeaders);
responseEntity = restTemplate.exchange(url, HttpMethod.POST, httpEntity5, String.class);
str += "修改 cf1 列族的 VERSIONS 为 2,默认是 1 (即只保留最后一个版本) -> " + url + "<br>";
str += "Request Entity: " + jsonParams + "<br>";
str += "Status Code: " + responseEntity.getStatusCode() + "<br>";
str += "Result: " + responseEntity.getBody() + "<br><br>";
// 显示 demo 表结构信息
responseEntity = restTemplate.getForEntity(url, String.class);
str += "显示 demo 表结构信息 -> " + url + "<br>";
str += "Status Code: " + responseEntity.getStatusCode() + "<br>";
str += "Result: " + responseEntity.getBody() + "<br><br>";
// 显示 demo 表分区
String url2 = hbaseRestUrl + "/demo/regions";
responseEntity = restTemplate.getForEntity(url2, String.class);
str += "显示 demo 表分区 -> " + url + "<br>";
str += "Status Code: " + responseEntity.getStatusCode() + "<br>";
str += "Result: " + responseEntity.getBody() + "<br><br>";
return str;
}
@ResponseBody
@RequestMapping("/data/add")
public String dataAdd() {
// 查看 demo 表是否存在
String url = hbaseRestUrl + "/demo/exists";
String str = "查看 demo 表是否存在 -> " + url + "<br>";
try {
ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);
str += "Status Code: " + responseEntity.getStatusCode() + "<br>";
str += "Result: " + responseEntity.getBody() + "<br><br>";
} catch (Exception e) {
str += "Error: " + e.getMessage();
return str;
}
// 头部信息
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
ArrayList<MediaType> acceptList = new ArrayList<>();
acceptList.add(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(acceptList);
// 添加 row1 的 name、age 数据
url = hbaseRestUrl + "/demo/row1";
String jsonParams = "{\"Row\":[{\"key\":\"cm93MQ==\",\"Cell\":[{\"column\":\"Y2YxOm5hbWU=\",\"$\":\"VG9t\"},{\"column\":\"Y2YxOmFnZQ==\",\"$\":\"MTI=\"}]}]}";
HttpEntity<String> httpEntity = new HttpEntity<>(jsonParams, httpHeaders);
ResponseEntity<String> responseEntity2 = restTemplate.exchange(url, HttpMethod.PUT, httpEntity, String.class);
str += "添加 row1 的 name、age 数据 -> " + url + "<br>";
str += "Request Entity: " + jsonParams + "<br>";
str += "Status Code: " + responseEntity2.getStatusCode() + "<br>";
str += "Result: " + responseEntity2.getBody() + "<br><br>";
// 添加 row1 的 job 数据
jsonParams = "{\"Row\":[{\"key\":\"cm93MQ==\",\"Cell\":[{\"column\":\"Y2YyOmpvYg==\",\"$\":\"U3R1ZGVudA==\"}]}]}";
httpEntity = new HttpEntity<>(jsonParams, httpHeaders);
responseEntity2 = restTemplate.exchange(url, HttpMethod.PUT, httpEntity, String.class);
str += "添加 row1 的 job 数据 -> " + url + "<br>";
str += "Request Entity: " + jsonParams + "<br>";
str += "Status Code: " + responseEntity2.getStatusCode() + "<br>";
str += "Result: " + responseEntity2.getBody() + "<br><br>";
// 添加 row2 的 name、age 和 job 数据
url = hbaseRestUrl + "/demo/row2";
jsonParams = "{\"Row\":[{\"key\":\"cm93Mg==\",\"Cell\":[{\"column\":\"Y2YxOm5hbWU=\",\"$\":\"SmVycnk=\"},{\"column\":\"Y2YxOmFnZQ==\",\"$\":\"OQ==\"},{\"column\":\"Y2YyOmpvYg==\",\"$\":\"RW5naW5lZXI=\"}]}]}";
httpEntity = new HttpEntity<>(jsonParams, httpHeaders);
responseEntity2 = restTemplate.exchange(url, HttpMethod.PUT, httpEntity, String.class);
str += "添加 row2 的 name、age 和 job 数据 -> " + url + "<br>";
str += "Request Entity: " + jsonParams + "<br>";
str += "Status Code: " + responseEntity2.getStatusCode() + "<br>";
str += "Result: " + responseEntity2.getBody() + "<br><br>";
// 再次添加 row2 的 age 数据, 值为 10 (Cell 支持 2 个版本,这里不会替换原版本 9,以时间戳为区分,生成一个新版本)
jsonParams = "{\"Row\":[{\"key\":\"cm93Mg==\",\"Cell\":[{\"column\":\"Y2YxOmFnZQ==\",\"$\":\"MTA=\"}]}]}";
httpEntity = new HttpEntity<>(jsonParams, httpHeaders);
responseEntity2 = restTemplate.exchange(url, HttpMethod.PUT, httpEntity, String.class);
str += "再次添加 row2 的 age 数据, 值为 10 -> " + url + "<br>";
str += "Request Entity: " + jsonParams + "<br>";
str += "Status Code: " + responseEntity2.getStatusCode() + "<br>";
str += "Result: " + responseEntity2.getBody() + "<br><br>";
// 添加 row3 的 name、age 和 job 数据
url = hbaseRestUrl + "/demo/row3";
jsonParams = "{\"Row\":[{\"key\":\"cm93Mw==\",\"Cell\":[{\"column\":\"Y2YxOm5hbWU=\",\"$\":\"SmVycnk=\"},{\"column\":\"Y2YxOmFnZQ==\",\"$\":\"MTA=\"},{\"column\":\"Y2YyOmpvYg==\",\"$\":\"RW5naW5lZXI=\"}]}]}";
httpEntity = new HttpEntity<>(jsonParams, httpHeaders);
responseEntity2 = restTemplate.exchange(url, HttpMethod.PUT, httpEntity, String.class);
str += "添加 row3 的 name、age 和 job 数据 -> " + url + "<br>";
str += "Request Entity: " + jsonParams + "<br>";
str += "Status Code: " + responseEntity2.getStatusCode() + "<br>";
str += "Result: " + responseEntity2.getBody() + "<br><br>";
// 查看 row3 数据
httpEntity = new HttpEntity<>(null, httpHeaders);
responseEntity2 = restTemplate.exchange(url, HttpMethod.GET, httpEntity, String.class);
str += "查看 row3 数据 -> " + url + "<br>";
str += "Status Code: " + responseEntity2.getStatusCode() + "<br>";
str += "Result: " + responseEntity2.getBody() + "<br><br>";
return str;
}
@ResponseBody
@RequestMapping("/data/query/get")
public String dataQueryGet() {
// 查看 demo 表是否存在
String url = hbaseRestUrl + "/demo/exists";
String str = "查看 demo 表是否存在 -> " + url + "<br>";
try {
ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);
str += "Status Code: " + responseEntity.getStatusCode() + "<br>";
str += "Result: " + responseEntity.getBody() + "<br><br>";
} catch (Exception e) {
str += "Error: " + e.getMessage();
return str;
}
// 获取 row2 的全部数据
url = hbaseRestUrl + "/demo/row2";
ResponseEntity<String> responseEntity2 = restTemplate.getForEntity(url, String.class);
str += "获取 row2 的全部数据 -> " + url + "<br>";
str += "Status Code: " + responseEntity2.getStatusCode() + "<br>";
str += "Result: " + responseEntity2.getBody() + "<br><br>";
// 获取 row2 的 cf1 列族的全部数据
url = hbaseRestUrl + "/demo/row2/cf1";
responseEntity2 = restTemplate.getForEntity(url, String.class);
str += "获取 row2 的 cf1 列族的全部数据 -> " + url + "<br>";
str += "Status Code: " + responseEntity2.getStatusCode() + "<br>";
str += "Result: " + responseEntity2.getBody() + "<br><br>";
// 获取 row2 的 cf1 列族的 age 数据
url = hbaseRestUrl + "/demo/row2/cf1:age";
responseEntity2 = restTemplate.getForEntity(url, String.class);
str += "获取 row2 的 cf1 列族的 age 数据 -> " + url + "<br>";
str += "Status Code: " + responseEntity2.getStatusCode() + "<br>";
str += "Result: " + responseEntity2.getBody() + "<br><br>";
// 获取 row2 的 age、job 数据 (多列)
url = hbaseRestUrl + "/demo/row2/cf1:age,cf2:job";
responseEntity2 = restTemplate.getForEntity(url, String.class);
str += "获取 row2 的 age、job 数据 (多列) -> " + url + "<br>";
str += "Status Code: " + responseEntity2.getStatusCode() + "<br>";
str += "Result: " + responseEntity2.getBody() + "<br><br>";
// 获取 row2 的 age 数据的最新 2 个版本
url = hbaseRestUrl + "/demo/row2/cf1:age?v=2";
responseEntity2 = restTemplate.getForEntity(url, String.class);
str += "获取 row2 的 age 数据的最新 2 个版本 -> " + url + "<br>";
str += "Status Code: " + responseEntity2.getStatusCode() + "<br>";
str += "Result: " + responseEntity2.getBody() + "<br><br>";
return str;
}
@ResponseBody
@RequestMapping("/data/query/scanner")
public String dataQueryScanner() {
// 查看 demo 表是否存在
String url = hbaseRestUrl + "/demo/exists";
String str = "查看 demo 表是否存在 -> " + url + "<br>";
try {
ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);
str += "Status Code: " + responseEntity.getStatusCode() + "<br>";
str += "Result: " + responseEntity.getBody() + "<br><br>";
} catch (Exception e) {
str += "Error: " + e.getMessage();
return str;
}
// 扫描整个 demo 表
url = hbaseRestUrl + "/demo/*";
ResponseEntity<String> responseEntity2 = restTemplate.getForEntity(url, String.class);
str += "扫描整个 demo 表 -> " + url + "<br>";
str += "Status Code: " + responseEntity2.getStatusCode() + "<br>";
str += "Result: " + responseEntity2.getBody() + "<br><br>";
// 扫描 cf2 列簇
url = hbaseRestUrl + "/demo/*/cf2";
responseEntity2 = restTemplate.getForEntity(url, String.class);
str += "扫描 cf2 列簇 -> " + url + "<br>";
str += "Status Code: " + responseEntity2.getStatusCode() + "<br>";
str += "Result: " + responseEntity2.getBody() + "<br><br>";
// 扫描 cf1 和 cf2 列簇
url = hbaseRestUrl + "/demo/*/cf1,cf2";
responseEntity2 = restTemplate.getForEntity(url, String.class);
str += "扫描 cf1 和 cf2 列簇 -> " + url + "<br>";
str += "Status Code: " + responseEntity2.getStatusCode() + "<br>";
str += "Result: " + responseEntity2.getBody() + "<br><br>";
// 扫描 cf1 列簇的 age,显示最后两个版本
url = hbaseRestUrl + "/demo/*/cf1:age?v=2";
responseEntity2 = restTemplate.getForEntity(url, String.class);
str += "扫描 cf1 列簇的 age,显示最后两个版本 -> " + url + "<br>";
str += "Status Code: " + responseEntity2.getStatusCode() + "<br>";
str += "Result: " + responseEntity2.getBody() + "<br><br>";
// 扫描整个 demo 表,限定返回行数
url = hbaseRestUrl + "/demo/*?limit=1";
responseEntity2 = restTemplate.getForEntity(url, String.class);
str += "扫描整个 demo 表,限定返回行数 -> " + url + "<br>";
str += "Status Code: " + responseEntity2.getStatusCode() + "<br>";
str += "Result: " + responseEntity2.getBody() + "<br><br>";
// 扫描整个 demo 表,从指定行(包括该行)开始向后扫描
url = hbaseRestUrl + "/demo/*?startrow=row2";
responseEntity2 = restTemplate.getForEntity(url, String.class);
str += "扫描整个 demo 表,从指定行(包括该行)开始向后扫描 -> " + url + "<br>";
str += "Status Code: " + responseEntity2.getStatusCode() + "<br>";
str += "Result: " + responseEntity2.getBody() + "<br><br>";
// 扫描整个 demo 表,扫描到指定行(不包括该行)
url = hbaseRestUrl + "/demo/*?endrow=row2";
responseEntity2 = restTemplate.getForEntity(url, String.class);
str += "扫描整个 demo 表,扫描到指定行(不包括该行) -> " + url + "<br>";
str += "Status Code: " + responseEntity2.getStatusCode() + "<br>";
str += "Result: " + responseEntity2.getBody() + "<br><br>";
// 扫描整个 demo 表,复合条件
url = hbaseRestUrl + "/demo/*/cf1:age?v=2&limit=1&startrow=row2";
responseEntity2 = restTemplate.getForEntity(url, String.class);
str += "扫描整个 demo 表,复合条件 -> " + url + "<br>";
str += "Status Code: " + responseEntity2.getStatusCode() + "<br>";
str += "Result: " + responseEntity2.getBody() + "<br><br>";
return str;
}
@ResponseBody
@RequestMapping("/data/delete")
public String dataDelete() {
// 查看 demo 表是否存在
String url = hbaseRestUrl + "/demo/exists";
String str = "查看 demo 表是否存在 -> " + url + "<br>";
try {
ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);
str += "Status Code: " + responseEntity.getStatusCode() + "<br>";
str += "Result: " + responseEntity.getBody() + "<br><br>";
} catch (Exception e) {
str += "Error: " + e.getMessage();
return str;
}
// 头部信息
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
ArrayList<MediaType> acceptList = new ArrayList<>();
acceptList.add(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(acceptList);
// 删除 row3 的 cf2 列族的 job 数据
url = hbaseRestUrl + "/demo/row3/cf2:job/?check=delete";
HttpEntity<String> httpEntity = new HttpEntity<>(null, httpHeaders);
ResponseEntity<String> responseEntity2 = restTemplate.exchange(url, HttpMethod.DELETE, httpEntity, String.class);
str += "删除 row3 的 cf2 列族的 job 数据 -> " + url + "<br>";
str += "Status Code: " + responseEntity2.getStatusCode() + "<br>";
str += "Result: " + responseEntity2.getBody() + "<br><br>";
// 删除 row3 整行数据
url = hbaseRestUrl + "/demo/row3/?check=delete";
httpEntity = new HttpEntity<>(null, httpHeaders);
responseEntity2 = restTemplate.exchange(url, HttpMethod.DELETE, httpEntity, String.class);
str += "删除 row3 整行数据 -> " + url + "<br>";
str += "Status Code: " + responseEntity2.getStatusCode() + "<br>";
str += "Result: " + responseEntity2.getBody() + "<br><br>";
// 删除 demo 表
url = hbaseRestUrl + "/demo/schema";
httpEntity = new HttpEntity<>(null, httpHeaders);
responseEntity2 = restTemplate.exchange(url, HttpMethod.DELETE, httpEntity, String.class);
str += "删除 demo 表 -> " + url + "<br>";
str += "Status Code: " + responseEntity2.getStatusCode() + "<br>";
str += "Result: " + responseEntity2.getBody() + "<br><br>";
return str;
}
@ResponseBody
@RequestMapping("/namespace")
public String namespace() {
// 头部信息
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
ArrayList<MediaType> acceptList = new ArrayList<>();
acceptList.add(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(acceptList);
// 查看所有 Namespace
String url = hbaseRestUrl + "/namespaces";
HttpEntity<String> httpEntity = new HttpEntity<>(null, httpHeaders);
ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, httpEntity, String.class);
String str = "查看所有 Namespace -> " + url + "<br>";
str += "Status Code: " + responseEntity.getStatusCode() + "<br>";
str += "Result: " + responseEntity.getBody() + "<br><br>";
// 创建 'ns_test' Namespace
url = hbaseRestUrl + "/namespaces/ns_test";
httpEntity = new HttpEntity<>(null, httpHeaders);
responseEntity = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);
str += "创建 'ns_test' Namespace -> " + url + "<br>";
str += "Status Code: " + responseEntity.getStatusCode() + "<br>";
str += "Result: " + responseEntity.getBody() + "<br><br>";
// 在 ns_test 下创建 tbl_01 表 (1 个列族 cf1)
url = hbaseRestUrl + "/ns_test:tbl_01/schema";
String jsonParams = "{\"name\":\"ns_test:tbl_01\",\"ColumnSchema\":[{\"name\":\"cf1\"}]}";
httpEntity = new HttpEntity<>(jsonParams, httpHeaders);
responseEntity = restTemplate.exchange(url, HttpMethod.PUT, httpEntity, String.class);
str += "在 ns_test 下创建 tbl_01 表 (1 个列族 cf1) -> " + url + "<br>";
str += "Request Entity: " + jsonParams + "<br>";
str += "Status Code: " + responseEntity.getStatusCode() + "<br>";
str += "Result: " + responseEntity.getBody() + "<br><br>";
// 查看 ns_test 下的表
url = hbaseRestUrl + "/namespaces/ns_test/tables";
httpEntity = new HttpEntity<>(null, httpHeaders);
responseEntity = restTemplate.exchange(url, HttpMethod.GET, httpEntity, String.class);
str += "查看 ns_test 下的表 -> " + url + "<br>";
str += "Status Code: " + responseEntity.getStatusCode() + "<br>";
str += "Result: " + responseEntity.getBody() + "<br><br>";
// 删除 ns_test 下的 tbl_01 表
url = hbaseRestUrl + "/ns_test:tbl_01/schema";
httpEntity = new HttpEntity<>(null, httpHeaders);
responseEntity = restTemplate.exchange(url, HttpMethod.DELETE, httpEntity, String.class);
str += "删除 ns_test 下的 tbl_01 表 -> " + url + "<br>";
str += "Status Code: " + responseEntity.getStatusCode() + "<br>";
str += "Result: " + responseEntity.getBody() + "<br><br>";
// 删除 ns_test
url = hbaseRestUrl + "/namespaces/ns_test";
httpEntity = new HttpEntity<>(null, httpHeaders);
responseEntity = restTemplate.exchange(url, HttpMethod.DELETE, httpEntity, String.class);
str += "删除 ns_test -> " + url + "<br>";
str += "Status Code: " + responseEntity.getStatusCode() + "<br>";
str += "Result: " + responseEntity.getBody() + "<br><br>";
return str;
}
}
3) 测试页面
运行 SpringbootExample22,访问 http://localhost:9090/client。