Hbase-技术文档-spring-boot整合使用hbase--简单操作增删改查--提供封装高可用的模版类
使用spring-boot项目来整合使用hbase。
引入依赖
<dependency><groupId>org.apache.hbase</groupId><artifactId>hbase-client</artifactId><version>2.4.3</version>
</dependency>
依赖声明表示将把Apache HBase客户端库的2.4.3版本添加到项目中。HBase是一个分布式、可扩展的大数据存储系统,它基于Google的Bigtable模型,并使用了Hadoop分布式文件系统作为底层存储。HBase客户端库是用于与HBase数据库进行交互的工具库,提供了一组API用于执行CRUD(创建、读取、更新、删除)操作以及其他与HBase相关的功能。
通过在项目中添加这个依赖,您将能够使用HBase客户端库的API来与HBase数据库进行通信,执行数据的增删改查操作等。这样,您就可以在Java应用程序中方便地使用HBase的功能了。
封装程度0.5,在下面有一个高可用的封装模版类!需要的向下直接看封装程度max!!!
书写配置文件
application.properties
hbase.config.hbase.zookeeper.quorum=ip地址
hbase.config.hbase.zookeeper.property.clientPort=2181
application.yml
hbase:config:hbase:zookeeper:quorum: ip地址property:clientPort: 2181
配置文件对应java类,书写配置类HbaseProperties.java
import java.util.Map;import org.springframework.boot.context.properties.ConfigurationProperties;@ConfigurationProperties(prefix = "hbase")
public class HbaseProperties {private Map<String,String> config;public void setConfig(Map<String, String> config) {this.config = config;}public Map<String, String> getConfig() {return config;}
}
配置文件HbaseConfig.java
import java.io.IOException;
import java.util.Map;import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
@EnableConfigurationProperties(HbaseProperties.class)
public class HbaseConfig {private final HbaseProperties props;public HbaseConfig(HbaseProperties props) {this.props = props;}@Beanpublic org.apache.hadoop.conf.Configuration configuration(){org.apache.hadoop.conf.Configuration conf = HBaseConfiguration.create();Map<String, String> config = props.getConfig();config.forEach(conf::set);return conf;}@Beanpublic Connection getConnection() throws IOException{return ConnectionFactory.createConnection(configuration());}@Beanpublic HBaseAdmin hBaseAdmin() throws IOException {return (HBaseAdmin) getConnection().getAdmin();}
}
创建一个Hbase的模版类,用于执行与Hbase的交互操作
@Service
public class HBaseTemplate {@Autowiredprivate Configuration configuration;private Connection connection;@PostConstructpublic void init() {connection = ConnectionFactory.createConnection(configuration);}public void putData(Put put) throws IOException {Table table = connection.getTable(TableName.valueOf("table_name"));table.put(put);table.close();}
}
请将table_name替换为您要操作的HBase表的实际名称。
使用封装好的模版类来使用进行操作
@Autowired
private HBaseTemplate hBaseTemplate;public void doSomethingWithHBase() {// 创建Put对象,包含要插入的数据...Put put = new Put(Bytes.toBytes("row_key"));// 设置要插入的列和值...hBaseTemplate.putData(put);
}
这是一个基本的整合示例,可以根据您的具体需求进行调整和扩展。注意,这只是一个基本的示例,您可能还需要处理异常、关闭连接等其他操作。
高度封装!!!max!!!
注意:!!
此方式不需要配置文件,如果需要可以自己去写一个配置类即可,配置类的写法在上面!!!
1、导入依赖
<!-- hbase--><dependency><groupId>org.apache.hbase</groupId><artifactId>hbase-client</artifactId><version>2.4.3</version></dependency>
2、封装模版类
模版类中有很详细的注解和说明
package com.adn.common.util;import lombok.extern.log4j.Log4j2;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.filter.CompareFilter;
import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
import org.apache.hadoop.hbase.filter.SubstringComparator;
import org.apache.hadoop.hbase.util.Bytes;import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Filter;@Component
@Log4j2
public class HBaseTemplate {private Configuration configuration; // Hadoop配置对象,用于创建HBase配置private Connection connection; // HBase连接对象,用于与HBase建立连接/*** 如果需要就可以去写一个时加载的配置类读取配置中的数据* */@PostConstructpublic void init() throws IOException {configuration = HBaseConfiguration.create();configuration.set("hbase.zookeeper.quorum", "部署hbase的ip地址");configuration.setInt("hbase.zookeeper.property.clientPort", 2181);// 等等其他HBase的配置设置connection = ConnectionFactory.createConnection(configuration);}/*** 插入数据* 注意:如果向一个不存在的表中添加数据的时候会直接新建这个表* 所以在向有的表中进行添加数据的时候要确定表名是否存在* */
// public void put(String tableName, String rowKey, String columnFamily, String column, String value) throws IOException {
// // 对指定表执行插入数据操作
// Table table = connection.getTable(TableName.valueOf(tableName)); // 获取指定表的Table对象
// Put put = new Put(Bytes.toBytes(rowKey)); // 创建Put对象,设置行键
// put.addColumn(Bytes.toBytes(columnFamily), Bytes.toBytes(column), Bytes.toBytes(value)); // 设置列族、列和值
// table.put(put); // 执行插入操作
// table.close(); // 关闭表连接
// }public void put(String tableName, String rowKey, String columnFamily, String column, String value) {// 对指定表执行插入数据操作Table table = null; // 获取指定表的Table对象try {table = connection.getTable(TableName.valueOf(tableName));} catch (IOException e) {throw new RuntimeException("连接"+tableName+"表出现异常"+e);}Put put = new Put(Bytes.toBytes(rowKey)); // 创建Put对象,设置行键put.addColumn(Bytes.toBytes(columnFamily), Bytes.toBytes(column), Bytes.toBytes(value)); // 设置列族、列和值try {table.put(put); // 执行插入操作} catch (IOException e) {try {log.info("新建表操作"+tableName);createTableIfNotExists(tableName, columnFamily);this.put(tableName,rowKey,columnFamily,column,value);//使用递归调用方法return;} catch (IOException ex) {throw new RuntimeException(ex);}}try {table.close(); // 关闭表连接} catch (IOException e) {throw new RuntimeException("关闭表连接出现错误"+e);}}/*** 新建表操作* */private void createTableIfNotExists(String tableName, String columnFamily) throws IOException {try (Admin admin = connection.getAdmin()) {TableName hbaseTable = TableName.valueOf(tableName);if (!admin.tableExists(hbaseTable)) {HTableDescriptor tableDescriptor = new HTableDescriptor(hbaseTable);tableDescriptor.addFamily(new HColumnDescriptor(Bytes.toBytes(columnFamily)));admin.createTable(tableDescriptor);}}}/*** 查找获取* */public String get(String tableName, String rowKey, String columnFamily, String column) {// 对指定表执行查找数据操作Table table = null; // 获取指定表的Table对象try {table = connection.getTable(TableName.valueOf(tableName));} catch (IOException e) {throw new RuntimeException("连接表出现异常"+e);}Get get = new Get(Bytes.toBytes(rowKey)); // 创建Get对象,设置行键Result result = null; // 执行查找操作,获取Result对象try {result = table.get(get);} catch (IOException e) {throw new RuntimeException("获取返回值出现异常"+e);}byte[] valueBytes = result.getValue(Bytes.toBytes(columnFamily), Bytes.toBytes(column)); // 获取指定列的值try {table.close(); // 关闭表连接} catch (IOException e) {throw new RuntimeException("关闭连接出现问题"+e);}return Bytes.toString(valueBytes); // 将值转换为字符串并返回}/*** 删除一条数据* */public void delete(String tableName, String rowKey) throws IOException {// 对指定表执行删除数据操作Table table = connection.getTable(TableName.valueOf(tableName)); // 获取指定表的Table对象Delete delete = new Delete(Bytes.toBytes(rowKey)); // 创建Delete对象,设置行键table.delete(delete); // 执行删除操作table.close(); // 关闭表连接}/*** 删除表* */public void deleteTable(String tableName) throws IOException {Admin admin = connection.getAdmin(); // 获取 Admin 对象TableName table = TableName.valueOf(tableName); // 获取表名if (admin.tableExists(table)) { // 检查表是否存在admin.disableTable(table); // 禁用表admin.deleteTable(table); // 删除表System.out.println("成功删除表: " + tableName);} else {System.out.println("表 " + tableName + " 不存在!");}admin.close(); // 关闭 Admin 连接}// 其他操作,如 scan 方法等// 关闭连接的方法public void close() throws IOException {connection.close(); // 关闭HBase连接}/*** 条件查询方法,根据指定的列族、列和值执行查询操作** @param tableName 表名* @param columnFamily 列族名* @param column 列名* @param value 值* @return 匹配的行数据列表* @throws IOException 发生 IO 错误时抛出异常*/public List<String> findbyConditions(String tableName, String columnFamily, String column, String value) throws IOException {List<String> results = new ArrayList<>(); // 创建结果列表Table table = connection.getTable(TableName.valueOf(tableName)); // 获取指定表的 Table 对象Filter filter = (Filter) new SingleColumnValueFilter(Bytes.toBytes(columnFamily), // 创建单列值过滤器Bytes.toBytes(column), CompareFilter.CompareOp.EQUAL, new SubstringComparator(value));Scan scan = new Scan(); // 创建扫描对象scan.setFilter((org.apache.hadoop.hbase.filter.Filter) filter); // 设置扫描过滤器ResultScanner scanner = table.getScanner(scan); // 获取结果扫描器for (Result result : scanner) {StringBuilder row = new StringBuilder(); // 创建字符串构建器row.append(Bytes.toString(result.getRow())).append(": "); // 拼接行键for (Cell cell : result.listCells()) {String family = Bytes.toString(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength()); // 获取列族String qualifier = Bytes.toString(cell.getQualifierArray(), cell.getQualifierOffset(),cell.getQualifierLength()); // 获取列名String cellValue = Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()); // 获取值row.append(family).append(":").append(qualifier).append("=").append(cellValue).append(", "); // 拼接行数据}results.add(row.toString()); // 将行数据添加到结果列表}table.close(); // 关闭表连接return results; // 返回结果列表}/*** 全表查询方法,返回表中所有行的数据列表** @param tableName 表名* @return 所有行的数据列表* @throws IOException 发生 IO 错误时抛出异常*/public List<String> allTheTable(String tableName) throws IOException {List<String> rows = new ArrayList<>(); // 创建行列表Table table = connection.getTable(TableName.valueOf(tableName)); // 获取指定表的 Table 对象Scan scan = new Scan(); // 创建扫描对象ResultScanner scanner = table.getScanner(scan); // 获取结果扫描器for (Result result : scanner) {StringBuilder row = new StringBuilder(); // 创建字符串构建器row.append(Bytes.toString(result.getRow())).append(": "); // 拼接行键for (Cell cell : result.listCells()) {String family = Bytes.toString(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength()); // 获取列族String qualifier = Bytes.toString(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength()); // 获取列名String value = Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()); // 获取值row.append(family).append(":").append(qualifier).append("=").append(value).append(", "); // 拼接行数据}rows.add(row.toString()); // 将行数据添加到行列表}table.close(); // 关闭表连接return rows; // 返回行列表}}
示例service,不知道如何调用的课参考使用
package com.adn.service;import com.adn.common.User;
import com.adn.common.util.HBaseTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.io.IOException;
/*** 示例使用* */
@Component
public class UserHBaseRepository {@Autowiredprivate HBaseTemplate hbaseTemplate;/*** 表名* */private final String TABLE_NAME = "users";/***列族* */private final String COLUMN_FAMILY = "info";public void createUser(String userId, String name, int age, String email) throws IOException {hbaseTemplate.put(TABLE_NAME, userId, COLUMN_FAMILY, "name", name);hbaseTemplate.put(TABLE_NAME, userId, COLUMN_FAMILY, "age", String.valueOf(age));hbaseTemplate.put(TABLE_NAME, userId, COLUMN_FAMILY, "email", email);}public User getUser(String userId) throws IOException {String name = hbaseTemplate.get(TABLE_NAME, userId, COLUMN_FAMILY, "name");String ageStr = hbaseTemplate.get(TABLE_NAME, userId, COLUMN_FAMILY, "age");int age = Integer.parseInt(ageStr);String email = hbaseTemplate.get(TABLE_NAME, userId, COLUMN_FAMILY, "email");// 构造User对象并返回return new User(userId, name, age, email);}public void updateUser(String userId, String name, int age, String email) throws IOException {hbaseTemplate.put(TABLE_NAME, userId, COLUMN_FAMILY, "name", name);hbaseTemplate.put(TABLE_NAME, userId, COLUMN_FAMILY, "age", String.valueOf(age));hbaseTemplate.put(TABLE_NAME, userId, COLUMN_FAMILY, "email", email);}public void deleteUser(String userId) throws IOException {hbaseTemplate.delete(TABLE_NAME, userId);}
}
实例controller
package com.adn.controller;import com.adn.common.User;
import com.adn.service.UserHBaseRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;import java.io.IOException;@RestController
public class UserController {@AutowiredUserHBaseRepository service;/*** 新增数据*String userId, String name, int age, String email*/@GetMapping("new/{userId}/{name}/{age}/{email}")public void newuser(@PathVariable String userId,@PathVariable String name,@PathVariable int age,@PathVariable String email){try {service.createUser(userId,name,age,email);} catch (IOException e) {System.out.println("新增出现异常");throw new RuntimeException(e);}}/*** 查询数据根据id查看数据* */@GetMapping("findById/{userId}")public User findById(@PathVariable String userId){try {return service.getUser(userId);} catch (IOException e) {System.out.println("查询出现异常");throw new RuntimeException(e);}}}
快去尝试一下8!!!!
相关文章:
Hbase-技术文档-spring-boot整合使用hbase--简单操作增删改查--提供封装高可用的模版类
使用spring-boot项目来整合使用hbase。 引入依赖 <dependency><groupId>org.apache.hbase</groupId><artifactId>hbase-client</artifactId><version>2.4.3</version> </dependency> 依赖声明表示将把Apache HBase客户端库…...
基于Pytorch的神经网络部分自定义设计
一、基础概念(学习笔记) (1)训练误差和泛化误差[1] 本质上,优化和深度学习的目标是根本不同的。前者主要关注的是最小化目标,后者则关注在给定有限数据量的情况下寻找合适的模型。训练误差和泛化误差通常不…...
持续更新串联记忆English words
(一)这是一组关于“服装搭配”的单词。通过在记忆中检索,回忆起隐藏的信息吧~ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>今日单词>>&…...
postgresql 内核源码分析 btree索引的增删查代码基本原理流程分析,索引膨胀的原因在这里
B-Tree索引代码流程分析 专栏内容: postgresql内核源码分析手写数据库toadb并发编程 开源贡献: toadb开源库 个人主页:我的主页 管理社区:开源数据库 座右铭:天行健,君子以自强不息;地势坤&…...
详细了解G1、了解G1、G1垃圾收集器详解、G1垃圾回收器简单调优
4.详细了解G1: 4.1.一:什么是垃圾回收 4.2.了解G1 4.3.G1 Yong GC 4.4.G1 Mix GC 4.5.三色标记算法 4.6.调优实践 5.G1垃圾收集器详解 5.1.G1垃圾收集器 5.2.G1的堆内存划分 5.3.G1的运行过程 5.4.三色标记 5.4.1.漏标问题 5.5.记忆集与卡表 5.6.安全点与…...
vue项目中 package.json 详解
在 Vue 项目中,package.json 是一个重要的配置文件,它包含了项目的名称、版本、作者、依赖等信息。下面是一份详细的 Vue 项目 package.json 配置说明: 1.name:项目的名称,用于标识项目,例如:&q…...
为什么要进行管网水位监测,管网水位监测的作用是什么
管网水位监测是城市排水系统管理的重要手段,对于保障城市排水设施安全运行和提升城市管理水平具有重要意义。通过对排水管网的水位进行实时监测和分析,能够及时发现问题并采取措施,提高排水系统的运行效率和管理水平。本文将详细介绍为什么要…...
webpack学习笔记
1. webpack基本概念 webpack: JavaScript 应用程序的静态模块打包器,是目前最为流行的JavaScript打包工具之一。webpack会以一个或多个js文件为入口,递归检查每个js模块的依赖,从而构建一个依赖关系图,然后依据该关系…...
解析代理IP在跨境电商和社媒营销中的关键作用
跨境电商和社媒营销领域的从业者深知,代理IP的价值愈发凸显。在推广营销的过程中,频繁遇到因IP关联而封禁账号的情况,或因使用不安全IP而导致异常问题。 这些问题促使人们开始高度重视代理IP的作用。但实际上,代理IP究竟是何物&a…...
Unity 之 Start 与Update 方法的区别
文章目录 当谈论Unity中的 Start和 Update方法时,我们实际上是在讨论MonoBehaviour类中的两个常用方法,用于编写游戏逻辑。这两个方法在不同的时机被调用,因此您可以根据需要选择在哪个方法中编写特定的代码。 Start 方法: Start…...
Spring Boot中如何编写优雅的单元测试
单元测试是指对软件中的最小可测试单元进行检查和验证。在Java中,单元测试的最小单元是类。通过编写针对类或方法的小段代码,来检验被测代码是否符合预期结果或行为。执行单元测试可以帮助开发者验证代码是否正确实现了功能需求,以及是否能够…...
三星Galaxy S23与iPhone 15的对比分析:谁会胜出?
三星Galaxy S23与iPhone 15的对决将于下个月进入高潮,这将是今年智能手机中最大的一场较量。毕竟,这是两家领先的移动设备制造商的旗舰手机。他们的手机的比较将在很大程度上决定谁能获得最佳手机的称号。 我们已经知道有利于三星Galaxy S23的情况,该产品自春季以来一直在推…...
MySQL索引 事物 存储引擎
一 索引 索引的概念 索引就是一种帮助系统能够更快速的查找信息的结构 索引的作用 索引的副作用 创建索引的规则 MySQL的优化 哪些字段/场景适合创建索引 哪些不适合 小字段唯一性强的字段更新不频繁,但查询率比较高的字段表记录超过 300行主键,外键…...
【谷粒学院】报错记录
无法从Nacos获取动态配置 原先gulimall-common中SpringCloud Alibaba的版本是2.1.0.RELEASE,无法从Nacos中获取配置文件信息 <dependencyManagement><dependencies><dependency><groupId>com.alibaba.cloud</groupId><artifactId&…...
微积分基本概念
微分 函数的微分是指对函数的局部变化的一种线性描述。微分可以近似地描述当函数自变量的取值作足够小的改变时,函数的值是怎样改变的。。对于函数 y f ( x ) y f(x) yf(x) 的微分记作: d y f ′ ( x ) d x d_y f^{}(x)d_x dyf′(x)dx 微分和…...
【业务功能篇78】微服务-前端后端校验- 统一异常处理-JSR-303-validation注解
5. 前端校验 我们在前端提交的表单数据,我们也是需要对提交的数据做相关的校验的 Form 组件提供了表单验证的功能,只需要通过 rules 属性传入约定的验证规则,并将 Form-Item 的 prop 属性设置为需校验的字段名即可 校验的页面效果 前端数据…...
pytorch的用法
...
Qt 设置窗口背景
窗口背景无非两种:背景色、背景图片。Qt中窗口背景如何设置? 一、QPalette设置背景 二、实现paintEvent,使用QPainter来绘制背景 三、使用QSS来设置背景 关于QSS的使用不想多说,一般我不用QSS设置窗口背景,也不建议…...
大模型是什么?泰迪大模型能够解决企业哪些痛点?
什么是大模型? 大模型是指模型具有庞大的参数规模和复杂程度的机器学习模型。在深度学习领域,大模型通常是指具有数百万到数十亿参数的神经网络模型。这些模型需要大量的计算资源和存储空间来训练和存储,并且往往需要进行分布式计算和特殊…...
YOLOv7-tracker 目标追踪 输入视频帧
目录 1 项目安装1.1 环境搭建1.2 项目下载1.3 权重下载1.4 环境安装1.5 上传待检测的视频帧 2 视频帧检测与追踪2.1 检测与追踪2.3 结果 参考项目:https://github.com/JackWoo0831/Yolov7-tracker/tree/master github链接:https://github.com/Whiffe/Yo…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...
elementUI点击浏览table所选行数据查看文档
项目场景: table按照要求特定的数据变成按钮可以点击 解决方案: <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...
Vue ③-生命周期 || 脚手架
生命周期 思考:什么时候可以发送初始化渲染请求?(越早越好) 什么时候可以开始操作dom?(至少dom得渲染出来) Vue生命周期: 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...
通过MicroSip配置自己的freeswitch服务器进行调试记录
之前用docker安装的freeswitch的,启动是正常的, 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...
