这里写自定义目录标题

  • 使用Spring创建接口发布实时日活数据
  • 一、日活数据查询接口相关要求
  • 1.1 访问路径
  • 1.2 要求数据格式
  • 二、搭建SpringWeb发布工程
  • 2.1 创建工程
  • 2.2 配置文件
  • 2.2.1 pom.xml
  • 2.2.2 application.properties
  • 三、 代码实现
  • 3.1 数据层
  • 3.1.1 数据层mapper
  • 3.1.2 封装每小时日活的方法类
  • 3.1.3 数据层 实现配置
  • 3.2 service层
  • 3.2.1 service层接口类
  • 3.2.2 service层实现类
  • 3.3 controller层
  • 3.4 主程序增加扫描包


使用Spring创建接口发布实时日活数据

本文主要针对上一篇文件中的实时日活数据搭建数据接口供前端人员进行实时数据展示使用。

背景前提:使用SparkStreaming计算得出的实时日活数据数据和分时日活数据已经通过Phonix保存到Hbase中的gmall2020_dau表中,现在需要通过数据接口的方式提供给前端人员进行实时数据的展示。

实时数据处理:

一、日活数据查询接口相关要求

springboot根据类名动态给接口加前缀 springboot 动态发布接口_List

1.1 访问路径

springboot根据类名动态给接口加前缀 springboot 动态发布接口_数据_02

1.2 要求数据格式

springboot根据类名动态给接口加前缀 springboot 动态发布接口_实时展示_03

二、搭建SpringWeb发布工程

2.1 创建工程

springboot根据类名动态给接口加前缀 springboot 动态发布接口_数据接口_04


springboot根据类名动态给接口加前缀 springboot 动态发布接口_数据_05


springboot根据类名动态给接口加前缀 springboot 动态发布接口_数据接口_06

此外,还需要在Developer选项中勾选lombok,Web选项中勾选SpringWeb。

2.2 配置文件

2.2.1 pom.xml
<dependency>
    <groupId>org.apache.phoenix</groupId>
    <artifactId>phoenix-core</artifactId>
    <version>5.0.0-HBase-2.0</version>
    <exclusions>
      <exclusion>
        <groupId>org.glassfish</groupId>
        <artifactId>javax.el</artifactId>
      </exclusion>
</exclusions>
</dependency>

<dependency>
       <groupId>com.google.guava</groupId>
       <artifactId>guava</artifactId>
       <version>20.0</version>
</dependency>
2.2.2 application.properties
server.port=8070

logging.level.root=error
 
spring.datasource.driver-class-name=org.apache.phoenix.jdbc.PhoenixDriver
spring.datasource.url=jdbc:phoenix:hadoop102,hadoop103,hadoop104:2181
spring.datasource.data-username=
spring.datasource.data-password=

#mybatis
#mybatis.typeAliasesPackage=com.example.phoenix.entity
mybatis.mapperLocations=classpath:mapper/*.xml
mybatis.configuration.map-underscore-to-camel-case=true

三、 代码实现

springboot根据类名动态给接口加前缀 springboot 动态发布接口_spring_07


springboot根据类名动态给接口加前缀 springboot 动态发布接口_spring_08

3.1 数据层

3.1.1 数据层mapper
package com.atguigu.gmallpublisher.mapper;

import com.atguigu.gmallpublisher.beans.DAUPerHour;
import org.springframework.stereotype.Repository;
import java.util.List;

/**
 * 分析数据接口需要查询什么样的数据
 *      总数: [{"id":"dau","name":"新增日活","value":1200}, {"id":"new_mid","name":"新增设备","value":233}]
 *      分时统计:{"yesterday":{"11":383,"12":123,"17":88,"19":200 },"today":{"12":38,"13":1233,"17":123,"19":688 }}
  *     需要的数据:a:当日日活
 *                 b:当日日活中新增的设备数
 *                 c:某日每个小时的日活数,将每个小时 和 日活数封装为数据模型
 */
@Repository
public interface DauMapper {

    Integer getDAUByData(String date);

    Integer getNewMidCountByDate(String date);

    List<DAUPerHour> getAllDAUPerHour(String date);

}
3.1.2 封装每小时日活的方法类
package com.atguigu.gmallpublisher.beans;

import lombok.*;

@Setter
@Getter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class DAUPerHour {

    private String hour;
    private Integer dauCount;

}
3.1.3 数据层 实现配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 接口式编程:
    namespace: 要绑定的接口的全类名-->
<mapper namespace="com.atguigu.gmallpublisher.mapper.DauMapper">
<!--    id: 必须是绑定的方法名
        resultType: 返回值类型,一般是返回的类型的全类名
        #{xx} :类似于?占位符
               如果当前只有一个参数需要占位符,id可以随便写
               多个占位符,xxx必须和要传入的对象的属性名称一致!
               本质上是调用属性的getter!

-->
    <select id="getDAUByData" resultType="int">
        select count(*) from  GMALL2020_DAU  where LOGDATE = #{LOGDATE}
    </select>

<!--    在xml中,<,>都会被解析为标签,需要将这些符号转移
                < : <
                > : >
-->
    <select id="getNewMidCountByDate" resultType="int">
        select  count(*)
        from
            (select mid from GMALL2020_DAU  where  LOGDATE = #{LOGDATE} ) t1
            left join
             (select mid from GMALL2020_DAU  where  LOGDATE < #{LOGDATE} ) t2
             on t1.mid = t2.mid
             where t2.mid is null
    </select>

<!--    将查询结果的列封装为bean的属性时,需要让列名和属性名一样-->
    <select id="getAllDAUPerHour" resultType="com.atguigu.gmallpublisher.beans.DAUPerHour">
        select
            LOGHOUR hour ,count(*) dauCount
        from GMALL2020_DAU  where  LOGDATE = #{LOGDATE}
        group by LOGHOUR
    </select>
    
</mapper>

3.2 service层

3.2.1 service层接口类
package com.atguigu.gmallpublisher.service;

import com.atguigu.gmallpublisher.beans.DAUPerHour;

import java.util.List;

public interface PublisherService {

    Integer getDAUByData(String date);

    Integer getNewMidCountByDate(String date);

    List<DAUPerHour> getAllDAUPerHour(String date);

}
3.2.2 service层实现类
package com.atguigu.gmallpublisher.service;

import com.atguigu.gmallpublisher.beans.DAUPerHour;
import com.atguigu.gmallpublisher.mapper.DauMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class PublisherServiceImpl implements PublisherService{

    @Autowired
    private DauMapper mapper;

    @Override
    public Integer getDAUByData(String date) {
        return mapper.getDAUByData(date);
    }

    @Override
    public Integer getNewMidCountByDate(String date) {
        return mapper.getNewMidCountByDate(date);
    }

    @Override
    public List<DAUPerHour> getAllDAUPerHour(String date) {
        return mapper.getAllDAUPerHour(date);
    }
}

3.3 controller层

package com.atguigu.gmallpublisher.controller;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmallpublisher.beans.DAUPerHour;
import com.atguigu.gmallpublisher.service.PublisherService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/*
      http://localhost:8070/realtime-total?date=2020-08-15
        [{"id":"dau","name":"新增日活","value":1200},
           {"id":"new_mid","name":"新增设备","value":233}]


      http://localhost:8070/realtime-hours?id=dau&date=2020-08-15
        {"yesterday":{"11":383,"12":123,"17":88,"19":200 },
           "today":{"12":38,"13":1233,"17":123,"19":688 }}

 */
@RestController
public class PublisherController {

    @Autowired
    private PublisherService service;


    public JSONObject handleDAUPerHour(List<DAUPerHour> datas){
        JSONObject jsonObject = new JSONObject();

        for (DAUPerHour data : datas) {
            jsonObject.put(data.getHour(),data.getDauCount());
        }

        return jsonObject;

    }

    @RequestMapping("/realtime-hours")
    public JSONObject handle2(String date){

        //查询昨日的数据
        String yesterDate = LocalDate.parse(date).minusDays(1).toString();
        List<DAUPerHour> yesDAUPerHour = service.getAllDAUPerHour(yesterDate);

        //查询今日的数据
        List<DAUPerHour> todayDAUPerHour = service.getAllDAUPerHour(date);

        JSONObject yesJSON = handleDAUPerHour(yesDAUPerHour);
        JSONObject todayJSON = handleDAUPerHour(todayDAUPerHour);

        //封装结果
        JSONObject result = new JSONObject();
        //写入jsonobject
        result.put("yesterday",yesJSON);
        result.put("today",todayJSON);

        //让jackson生成json,不要将fastjson生成的字符串直接写回,会产生转义字符
        return result;

    }


    /*
        springboot 内置了jackson(json的解析框架)
        如果方法声明了@Responsebody,自动将返回值转换成JSON,再放入响应体,相应客户端
     */
    @RequestMapping("/realtime-total")
    public List handle1(String date){
        //准备返回值的数据容器
        ArrayList result = new ArrayList();

        HashMap<String, Object> data1 = new HashMap<>();
        HashMap<String, Object> data2 = new HashMap<>();

        //查询当日日活
        Integer dauByData = service.getDAUByData(date);
            data1.put("id","dau");
            data1.put("name","新增日活");
            data1.put("value", dauByData);

        Integer newMidCountByDate = service.getNewMidCountByDate(date);
            data2.put("id","new_mid");
            data2.put("name","新增设备");
            data2.put("value",newMidCountByDate);

         result.add(data1);
         result.add(data2);

         return result;
    }

}

3.4 主程序增加扫描包

package com.atguigu.gmallpublisher;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
//通知容器使用代理的方式为Mapper创建对象
@MapperScan(basePackages = "com.atguigu.gmallpublisher.mapper")
public class GmallPublisherApplication {

    public static void main(String[] args) {
        SpringApplication.run(GmallPublisherApplication.class, args);
    }

}