数据接口工程对接BI可视化大屏(五)数据接口发布

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
简介: 数据接口工程对接BI可视化大屏(五)数据接口发布

第5章 数据接口发布

这里基于MVC开发范式完成数据接口程序的搭建。

5.1 编写Service

可视化大屏共需要8个数据接口,根据数据接口的返回值类型编写Service层的相关方法如下:

public interface DataInterfaceService
{
//查询Mysql中某天分钟级别的下单和退单数
JSONObject queryOrderStatsByDate(String dt);
//从redis中查询各手机的访问量
JSONObject queryVisitStatsTop5();
//从ck中查询各手机当日的销售额
JSONObject querySalesAmountToday();
//从ck统计每个手机品牌在昨日和今日的总销售额
JSONObject querySalesAmount();
//从ES中查询各来源数
JSONObject querySourceData();
//从ES中查询行业信息
JSONObject queryIndustryStats();
//从hbase中查询各省份今日的订单数和销售额
JSONObject queryProvinceStatToday();
//从hbase中查询各省份的目标完成进度
JSONObject queryProviceCompletion(String city);
}

5.2 从MySQL中返回数据

源数据结构:


案例一:查询MySQL中某天分钟级别的下单和退单数。效果图如下:

读取MySQL可以使用JDBC来读取,这里使用Mybatis简化JDBC操作。

5.2.1 封装Bean

@Data
@NoArgsConstructor
@AllArgsConstructor
public class OrderStats
{
private String dt;
private Integer orderCount;
private Integer refundCount;
}

封装日期,下单数和退单数三个字段。

5.2.2 编写Mapper

@DS(“mysql”)
@Mapper
public interface MysqlMapper
{
//查询当天每分钟的退单数和订单数
@Select("SELECT " +
" DATE_FORMAT(dt,‘%H:%I’) dt, " +
" SUM(orderCount) orderCount, " +
" SUM(refundCount) refundCount " +
"FROM di " +
"WHERE DATE(dt)=#{date} " +
"GROUP BY DATE_FORMAT(dt,‘%H:%I’) ")
List queryOrderStatsByDate(@Param(“date”) String dt);
}

使用@DS注解指定Mapper连接的数据源。编写方法,通过日期查询当天的每分钟的下单数和退单数。

使用@Mapper注解标注类可以让Spring容器启动时,使用Mybatis的动态代理技术在容器中为接口创建一个实例。

5.2.3 编写ServiceImpl

根据可视化图表中接口需要返回的数据格式,编写Service的方法实现。

通常{ }格式可以使用Map或JSONObject对象封装。而[ ]格式可以使用List或JSONArray对象封装。

@Service
public class DataInterfaceServiceImpl implements DataInterfaceService
{
@Autowired
private MysqlMapper mysqlMapper;
@Override
public JSONObject queryOrderStatsByDate(String dt) {
 if (null == dt){
 dt = LocalDate.now().toString();
 }
 List data = mysqlMapper.queryOrderStatsByDate(dt);
 System.out.println(data);
 List ocs = data.stream().map(d -> d.getOrderCount()).collect(Collectors.toList());
 List rcs = data.stream().map(d -> d.getRefundCount()).collect(Collectors.toList());
 List dts = data.stream().map(d -> d.getDt()).collect(Collectors.toList());
 JSONObject oJO = new JSONObject();
 oJO.put(“name”,“新增订单数”);
 oJO.put(“data”,ocs);
 JSONObject rJO = new JSONObject();
 rJO.put(“name”,“退单数”);
 rJO.put(“data”,rcs);
 List series = new ArrayList<>(2);
 series.add(oJO);
 series.add(rJO);
 JSONObject dataJO = new JSONObject();
 dataJO.put(“categories”,dts);
 dataJO.put(“series”,series);
 JSONObject result = new JSONObject();
 result.put(“status”,0);
 result.put(“msg”,“”);
 result.put(“data”,dataJO);
 return result ;
}
}

5.2.4 编写Controller

使用@RestController注解可以标识当前类为控制器,并且可以将处理方法的返回值作为数据写入响应体返回。

@RestController
public class DataInterfaceController
{
@Autowired
private DataInterfaceService dIService;
@RequestMapping(value = “/orderStats”)
public Object queryOrderStats(String date){
return dIService.queryOrderStatsByDate(date);
}
}

5.2.5 测试

5.3 从Redis中返回数据

源数据结构: key=hotphone, valueType=zset。member为手机品牌,score为热度值。

案例二:在Redis中查询实时访问量前5的热点手机品牌。效果图:

5.3.1 封装Bean

此案例需要的数据字段个数较少,可以不封装Bean。

5.3.2 编写Mapper

Redis为NoSQL数据库,可以使用Spring提供的RedisTemplate客户端进行操作,因此也无需封装Mapper。

5.3.3 编写ServiceImpl

根据可视化图表中接口需要返回的数据格式,编写Service的方法实现。

@Service
public class DataInterfaceServiceImpl implements DataInterfaceService
{
@Autowired
private RedisTemplate redisTemplate;
@Override
public JSONObject queryVisitStatsTop5() {
 Set typedTuples = redisTemplate.opsForZSet().reverseRangeWithScores(redisDataKey, 0, 4);
 List scores = new ArrayList<>();
 List brands = new ArrayList<>();
 List series = new ArrayList<>(1);
 for (ZSetOperations.TypedTuple t : typedTuples) {
 scores.add(t.getScore());
 brands.add(t.getValue());
 }
 JSONObject result = getJsonObject(scores, brands, series);
 return result;
}
}

5.3.4 编写Controller

使用@RestController注解可以标识当前类为控制器,并且可以将处理方法的返回值作为数据写入响应体返回。

@RestController
public class DataInterfaceController
{
@Autowired
private DataInterfaceService dIService;
@RequestMapping(value = “/phoneVistTop5”)
public Object queryPhoneVistTop5(){
 return dIService.queryVisitStatsTop5();
}
}

5.3.5 测试

5.4 从Clickhouse中返回数据

源数据结构:

案例三:从ck中查询各手机当日的销售额。效果图:

案例四:从ck中计算每个手机品牌昨天和今天的总销售额。效果图:

读取Clickhouse可以使用JDBC来读取,这里使用Mybatis简化JDBC操作。

5.4.1 封装Bean

//案例三

@Data
@NoArgsConstructor
@AllArgsConstructor
public class PhoneSales
{
private String brand;
private Double salesAmount;
}
//案例四
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PhoneSalesCompare
{
private String brand;
private Double todaySalesAmount;
private Double yestodaySalesAmount;
}

5.4.2 编写Mapper

@Mapper
@DS(“ck”)
public interface CKMapper
{
//案例三
@Select(“select brand,sum(saleAmount) salesAmount from di where dt = #{dt} group by brand”)
List queryPhoneSalesToday(String dt);
//案例四
@Select("select " +
 " ifNull(t1.brand,t2.brand) brand, " +
 " ifNull(todayAmount,0.0) todaySalesAmount, " +
 " ifNull(yestodayAmount,0.0) yestodaySalesAmount " +
 "from " +
 "(select brand,sum(saleAmount) todayAmount from di where toDate(dt) = today() group by brand) t1 " +
 "full join " +
 "(select brand,sum(saleAmount) yestodayAmount from di where toDate(dt) = yesterday() group by brand) t2 " +
 "on t1.brand = t2.brand ")
List queryPhoneSales();
}

5.4.3 编写ServiceImpl

根据可视化图表中接口需要返回的数据格式,编写Service的方法实现。

@Service
public class DataInterfaceServiceImpl implements DataInterfaceService
{
@Autowired
private CKMapper ckMapper;
//案例三
@Override
public JSONObject querySalesAmountToday() {
 List datas = ckMapper.queryPhoneSalesToday(LocalDate.now().toString());
 List scores = new ArrayList<>();
 List brands = new ArrayList<>();
 List series = new ArrayList<>(1);
 for (PhoneSales data : datas) {
 scores.add(data.getSalesAmount());
 brands.add(data.getBrand());
 }
 JSONObject result = getJsonObject(scores, brands, series);
 return result;
}

//案例四

@Override
public JSONObject querySalesAmount() {
 List data = ckMapper.queryPhoneSales();
 List today = new ArrayList<>();
 List yesterday = new ArrayList<>();
 List brands = new ArrayList<>();
 List series = new ArrayList<>(2);
 for (PhoneSalesCompare d : data) {
 today.add(d.getTodaySalesAmount());
 yesterday.add(d.getYestodaySalesAmount());
 brands.add(d.getBrand());
 }
 JSONObject todayJO = new JSONObject();
 JSONObject yesterdayJO = new JSONObject();
 JSONObject result = new JSONObject();
 JSONObject dataJO = new JSONObject();
 todayJO.put(“name”,“今天”);
 todayJO.put(“data”,today);
 yesterdayJO.put(“name”,“昨天”);
 yesterdayJO.put(“data”,yesterday);
 series.add(todayJO);
 series.add(yesterdayJO);
 dataJO.put(“categories”,brands);
 dataJO.put(“series”,series);
 result.put(“status”,0);
 result.put(“msg”,“”);
 result.put(“data”,dataJO);
 return result;
}
}

5.4.4 编写Controller

@RestController
public class DataInterfaceController
{
@Autowired
private DataInterfaceService dIService;
//案例三
@RequestMapping(value = “/phoneSalesAmount”)
public Object queryPhoneSalesAmountToday(){
 return dIService.querySalesAmountToday();
}
//案例四
@RequestMapping(value = “/phoneSalesAmountCompare”)
public Object queryPhoneSalesAmount(){
 return dIService.querySalesAmount();
}
}

5.4.5 测试

案例三:

案例四:

5.5 从ES中返回数据

源数据结构:

{ “mappings”:
{ “_doc”:
{ “properties”:
{
“_class”:
{ “type”: “keyword”, “index”: false, “doc_values”: false },
“id”: { “type”: “long” },
“name”: { “type”: “keyword” },
“profession”: { “type”: “keyword” },
“sex”: { “type”: “keyword” },
“source”: { “type”: “keyword” }
}
}
}
}

案例五:查询ES中手机购买用户的访问渠道统计信息。效果图:

案例六:查询ES中手机购买用户的行业背景及性别比例。效果图:

ES是NoSql数据库,这里使用SpringData中提供的ElasticsearchRestTemplate客户端访问数据库。

5.5.1 封装Bean

封装Bean映射ES目标index中的数据模型。

@Data
@NoArgsConstructor
@AllArgsConstructor
@Document(indexName = “di”)
public class Customer
{
@Id
private Integer id;
@Field(type = FieldType.Keyword)
private String name;
@Field(type = FieldType.Keyword)
private String sex;
@Field(type = FieldType.Keyword)
private String source;
@Field(type = FieldType.Keyword)
private String profession;
}

5.5.2 编写Dao及Impl

public interface ESDao
{
SearchHits queryFromES(AbstractAggregationBuilder aggregationBuilder,Class t);
}
在ESDao中编写通用的聚合查询方法。并提供实现如下:
@Repository
public class ESDaoImpl implements ESDao
{
@Autowired
private ElasticsearchRestTemplate et;
@Override
public SearchHits queryFromES(AbstractAggregationBuilder aggregationBuilder, Class t) {
Query query = new NativeSearchQueryBuilder()
.addAggregation(aggregationBuilder)
.build();
 SearchHits searchHits = et.search(query, t);
 return searchHits;
}
}

5.5.3 编写ServiceImpl

根据可视化图表中接口需要返回的数据格式,编写Service的方法实现。

@Service
public class DataInterfaceServiceImpl implements DataInterfaceService
{
@Autowired
private ESDao esDao;
//案例五
@Override
public JSONObject querySourceData() {
 TermsAggregationBuilder aggregation = AggregationBuilders.terms(“sc”)
 .field(“source”);
 SearchHits searchHits = esDao.queryFromES(aggregation, Customer.class);
 Aggregations aggregations = searchHits.getAggregations();
 Terms tagg= aggregations.get(“sc”);
 List elasticBucket = tagg.getBuckets();
 List data = new ArrayList<>();
 elasticBucket.forEach(el -> {
 data.add(new SourceInfo(el.getKeyAsString(),el.getDocCount()));
 });
 JSONObject jsonObject = new JSONObject();
 jsonObject.put(“status”,0);
 jsonObject.put(“msg”,“”);
 jsonObject.put(“data”,data);
 return jsonObject;
}
//案例六
@Override
public JSONObject queryIndustryStats() {
 TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders
 .terms(“pc”).field(“profession”).size(10)
 .subAggregation(AggregationBuilders.terms(“sc”).field(“sex”).size(2));
 SearchHits searchHits = esDao.queryFromES(termsAggregationBuilder, Customer.class);
 Aggregations aggregations = searchHits.getAggregations();
 List categeryList = new ArrayList<>();
 List maleList = new ArrayList<>();
 List femaleList = new ArrayList<>();
 Terms byCompanyAggregation = aggregations.get(“pc”);
 List elasticBucket = byCompanyAggregation.getBuckets();
 elasticBucket.forEach(el -> {
 categeryList.add(el.getKeyAsString());
 Terms sexAggregation = el.getAggregations().get(“sc”);
 List buckets = sexAggregation.getBuckets();
 buckets.forEach(d -> {
 if (“男”.equals(d.getKeyAsString())) {
 double malePercent = d.getDocCount() * 100 / el.getDocCount() ;
 maleList.add((int)malePercent);
 femaleList.add(100 - (int)malePercent);
 }
 });
 });
 List series = Arrays.asList(
 new IndustryInfo(“男”, “%”, maleList),
 new IndustryInfo(“女”, “%”, femaleList)
 );
 JSONObject dataJO = new JSONObject();
 dataJO.put(“categories”,categeryList);
 dataJO.put(“series”,series);
 dataJO.put(“yUnit”,“%”);
 JSONObject resultJO = new JSONObject();
 resultJO.put(“status”,0);
 resultJO.put(“msg”,“”);
 resultJO.put(“data”,dataJO);
 return resultJO;
}
}

5.5.4 编写Controller

@RestController
public class DataInterfaceController
{
@Autowired
private DataInterfaceService dIService;
//案例五
@RequestMapping(value = “/sourceInfo”)
public Object querySourceInfo(){
 return dIService.querySourceData();
}
//案例六
@RequestMapping(value = “/sexcompare”)
public Object querySexcompare(){
 return dIService.queryIndustryStats();
}
}

5.5.5 测试

案例五:

案例六:

5.6 从HBase中返回数据

源数据结构:

案例七:查询各省份今日的订单数和销售额。效果图:

案例八:查询各省份今日的千万销售额目标完成进度。效果图:

HBase是一个NoSQL数据库,这里使用Phoenix编写SQL查询HBase。Phoenix支持JDBC操作,这里使用Mybatis简化JDBC操作。

5.6.1 封装Bean

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ProvinceStat
{
private String name;
private Double value;
private Integer sizeValue;
private String url = “sugar.baidu.com”;
}

5.6.2 编写Mapper

@Mapper
@DS(“hbase”)
public interface HBaseMapper
{
//案例七
@Select("select province name , sum(ordercount) sizeValue , sum(saleamount) “value” " +
 " from di " +
 " where substr(to_char(saletime),1,10) = #{date} " +
 " group by province")
List queryProvinceStatToday(String date);
//案例八
@Select("select sum(saleamount) " +
 " from di " +
 " where substr(to_char(saletime),1,10) = #{date}" +
 " and province = #{name}")
Double queryCompletionByProvinceName(@Param(“name”) String name,@Param(“date”) String date);
}

5.6.3 编写ServiceImpl

根据可视化图表中接口需要返回的数据格式,编写Service的方法实现。

@Service
public class DataInterfaceServiceImpl implements DataInterfaceService
{
@Autowired
private HBaseMapper hBaseMapper;
//案例七
@Override
public JSONObject queryProvinceStatToday() {
 List mapData = hBaseMapper.queryProvinceStatToday(LocalDate.now().toString());
 JSONObject dataJO = new JSONObject();
 dataJO.put(“mapData”,mapData);
 dataJO.put(“valueName”,“销售额”);
 dataJO.put(“sizeValueName”,“下单数”);
 JSONObject result = new JSONObject();
 result.put(“status”,0);
 result.put(“msg”,“”);
 result.put(“data”,dataJO);
 return result;
}
//案例八
@Override
public JSONObject queryProviceCompletion(String city) {
 Double amount = hBaseMapper.queryCompletionByProvinceName(city, LocalDate.now().toString());
 double completion = 0;
 if (amount==null){
 completion = 0;
 }else if (amount >= 1000000){
 completion = 100;
 }else{
 completion = amount / 10000000 * 100;
 }
 JSONObject result = new JSONObject();
 result.put(“status”,0);
 result.put(“msg”,“”);
 result.put(“data”,completion);
 return result;
}
}

5.6.4 编写Controller

@RestController
public class DataInterfaceController
{
@Autowired
private DataInterfaceService dIService;
//案例七
@RequestMapping(value = “/provinceStatsToday”)
public Object queryProvinceStatsToday(){
 return dIService.queryProvinceStatToday();
}
//案例八
@RequestMapping(value = “/provinceCompletionToday”)
public Object queryProviceCompletion(String city){
 return dIService.queryProviceCompletion(city);
}
}

5.6.5 测试

案例七:

案例八:

5.7 发布数据接口

将程序打包后部署到拥有公网IP的机器,或者也可以在window本地启动应用程序。

之后使用内网穿透工具,将项目的访问端口暴露到公网。

5.8 对接SugarBI

在SugarBI管理界面中点击编辑按钮:

点击对应图例,在后侧菜单栏中进行编辑,选择数据接收方式为API拉取,并填写之前控制器中对应方法绑定的API,调整数据刷新时间。

点击调试按钮,可以对数据格式是否符合要求进行验证:

之后点击保存后可以将BI看板分享或者发布。

目录
相关文章
|
7月前
|
数据采集 数据可视化 数据挖掘
数据分析案例-BI工程师招聘岗位信息可视化分析
数据分析案例-BI工程师招聘岗位信息可视化分析
147 0
|
2月前
|
缓存 数据可视化 BI
帆软BI 模仿一个可视化护理软件大屏 (三百六十行 行行fine BI)
帆软BI 模仿一个可视化护理软件大屏 (三百六十行 行行fine BI)
37 0
|
4月前
|
数据可视化 BI Windows
这两个BI可视化软件如何选择?亲测推荐
这两个BI可视化软件如何选择?亲测推荐
|
5月前
|
缓存 DataWorks 数据可视化
DataWorks 数据服务 + BI 可视化分析报表 (搭建战报)
DataWorks 数据服务提供强大的数据 API 能力,并能与多种业界流行的 BI 报表 (DataV、QuickBI、PowerBI和Grafana) 结合,使用 API 数据源的好处是统一数据接口、统一权限管理、统一数据交换以及数据服务提供强大的各式各样的插件能力 (如缓存插件、流量控制插件、日志脱敏插件、断路器插件、IP访问控制插件、三方鉴权插件等),下文介绍各热门 BI 工具接入 DataWorks 数据服务的操作方式。
201 0
DataWorks 数据服务 + BI 可视化分析报表 (搭建战报)
|
7月前
|
数据可视化 Linux Apache
CentOS部署Apache Superset大数据可视化BI分析工具并实现无公网IP远程访问
CentOS部署Apache Superset大数据可视化BI分析工具并实现无公网IP远程访问
|
7月前
|
传感器 数据可视化 搜索推荐
瓴羊Quick BI助力深圳光明环境水务公司举办水务数据应用大会暨第二届“光环杯”BI应用大赛
瓴羊Quick BI助力深圳光明环境水务公司举办水务数据应用大会暨第二届“光环杯”BI应用大赛
140 0
|
7月前
|
BI
Quick BI V5.0发布:一键解锁智能小Q等全新智能商业分析能力
Quick BI V5.0发布:一键解锁智能小Q等全新智能商业分析能力
253 0
|
5月前
|
数据可视化 安全 搜索推荐
干货|FESCO Adecco外企德科:Quick BI打造战略管理“观数台”(2)
干货|FESCO Adecco外企德科:Quick BI打造战略管理“观数台”
135 4
|
5月前
|
监控 数据可视化 数据挖掘
干货|FESCO Adecco外企德科:Quick BI打造战略管理“观数台”(1)
干货|FESCO Adecco外企德科:Quick BI打造战略管理“观数台”
113 4
|
7月前
|
分布式计算 大数据 BI
MaxCompute产品使用合集之MaxCompute项目的数据是否可以被接入到阿里云的Quick BI中
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。

热门文章

最新文章