一、回顾

1、数据仓库
数据集成的地方,对外来数据进行清洗,分层处理,分析指标得出结论
2、外卖平台思路
MySQL(原始数据) —> (ODS层存储最接近原始数据的层,DIM层维度层一般存储一些维度数据,DW层一般又分为三层【DWS】,将之前的数据合并为一张宽表,为后面的数据统计做准备,通过HQL语句将统计的结果放入DM层) HIve干的事儿 —> MySQL数据中
3、疑问?
为什么不直接在mysql中将四个表进行关联查询呢?
1)MySQL中的数据会越来越大,每次执行的SQL速度会越来越慢,执行一个庞大的SQL语句,会拖累整个mysql服务器。
2)外卖分析平台的数据,也不仅仅来自于我们的mysql
3) 每次统计的结果下一次还要重新做统计,不能重复利用。

二、Java的环境配置(IDEA+JDK+Maven)

Jdk1.8 + IDEA2019.1 + MySQL5.7 + Maven 3.5.2

1、首先安装我们的jdk(直接一直下一步下一步,一般我喜欢将这个软件安装在C盘)

不需要配置环境变量

2、安装我们的 idea

image.png

3、解压maven

  1. 解压到一个没有中文路径的盘符或者文件夹下。<br />我解压到了 E:\apache-maven-3.5.2-bin\apache-maven-3.5.2<br />接着配置mavensettings.xml 配置文件,直接替换老闫的即可。 mavenconf下<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/22131196/1641695423486-2d34fce0-19f6-4c7a-b89c-ffed3f1a6bce.png#clientId=uc0150ab5-0a37-4&from=paste&height=216&id=ud286003d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=216&originWidth=691&originalType=binary&ratio=1&size=19164&status=done&style=none&taskId=uc8ba8b2e-3c23-45f2-80ec-c105de1f43c&width=691)<br />老闫的settings.xml 有啥玄妙的地方?<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/22131196/1641695548942-16dc638b-6545-4b97-83f7-c8127a4563a0.png#clientId=uc0150ab5-0a37-4&from=paste&height=136&id=u37166dc9&margin=%5Bobject%20Object%5D&name=image.png&originHeight=136&originWidth=1049&originalType=binary&ratio=1&size=15428&status=done&style=none&taskId=u5a414601-1925-4e6d-9b55-c5bdd7d7156&width=1049)<br />第二个地方:<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/22131196/1641695630035-ad2b8888-f2b3-4f53-aef2-3e63301b42f8.png#clientId=uc0150ab5-0a37-4&from=paste&height=278&id=uf5e02976&margin=%5Bobject%20Object%5D&name=image.png&originHeight=278&originWidth=1163&originalType=binary&ratio=1&size=33607&status=done&style=none&taskId=u1bc7eb00-782c-4229-af80-3845ee28c82&width=1163)<br />Maven到底是干嘛的? ----> Maven是帮我们下载需要的jar包。

4、IDEA和Maven进行绑定

image.png
image.png
image.png

5、idea关联我们本地的jdk

image.png
image.png
点击确定,不要忘记了

三、开始搞开发(SpringBoot+Mybatis+Echarts)

1、创建项目(SpringBoot项目)

image.png
image.png
image.png
说明项目名字不能用大写。
image.png
选择需要的jar包:
image.png
image.png
一路创建,创建成功后,会进入项目,右下角有滚动的进度条,是在帮助我们下载需要的jar包,等它下载完不动了即可。
image.png
每当你的下载的进度卡到一个点过不去,可以关掉idea,然后重新进入,重新进入之后,选择右侧的maven,点击刷新按钮
image.png
image.png
我删除了一个插件:在pom.xml 中。

<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

如果右下角出现了这个选项,选择图中所示的自动导入:
image.png

2、编写代码第一式—springboot

image.png
编写代码:

package com.yxh.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class OrderShowController {

    @RequestMapping("/hello")
    public String hello(){
        // sout 直接回车就出现打印的语句
        System.out.println("Hello SpringBoot!!!!");
        return "Hello SpringBoot";
    }
}

启动项目测试是否成功!
image.png
image.png
启动报错:原因是导入了mysql的相关的jar包,却没有指定数据库连接地址,所以报错!!!!!
在resources 文件夹的配置文件中 application.properties中,编写数据库连接数据

spring.datasource.url=jdbc:mysql://192.168.32.135:3306/el_report
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root

image.png

3、编写java代码第二式—学习一个Echarts

网址:https://echarts.apache.org/zh/index.html
是由百度公司推出的非常有名的一个图形化的报表工具。
入门案例:
image.png
折线图:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <!-- 引入刚刚下载的 ECharts 文件 -->
    <script src="echarts.min.js"></script>
  </head>

  <body>
     <!-- 为 ECharts 准备一个定义了宽高的 DOM -->
     <div id="main" style="width: 600px;height:400px;"></div>
     <script type="text/javascript">
      // 基于准备好的dom,初始化echarts实例
      var myChart = echarts.init(document.getElementById('main'));

      // 指定图表的配置项和数据
      var option = {
        title: {
          text: 'ECharts 入门示例'
        },
        tooltip: {},
        legend: {
          data: ['销量']
        },
        xAxis: {
          data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
        },
        yAxis: {},
        series: [
          {
            name: '销量',
            type: 'bar',
            data: [5, 20, 36, 10, 10, 20]
          }
        ]
      };

      // 使用刚指定的配置项和数据显示图表。
      myChart.setOption(option);
    </script>
   </body>
</html>

饼状图:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <!-- 引入刚刚下载的 ECharts 文件 -->
    <script src="echarts.min.js"></script>
  </head>

  <body>
     <!-- 为 ECharts 准备一个定义了宽高的 DOM -->
     <div id="main" style="width: 600px;height:400px;"></div>
     <script type="text/javascript">
      // 基于准备好的dom,初始化echarts实例
      var myChart = echarts.init(document.getElementById('main'));

      // 指定图表的配置项和数据
      var option = {
          series: [
            {
              type: 'pie',
              data: [
                {
                  value: 335,
                  name: '直接访问'
                },
                {
                  value: 234,
                  name: '联盟广告'
                },
                {
                  value: 1548,
                  name: '搜索引擎'
                }
              ],
              radius: '50%'
            }
          ]
        };

      // 使用刚指定的配置项和数据显示图表。
      myChart.setOption(option);
    </script>
   </body>
</html>

一般的图形,我们只需要替换option这一部分即可,找到合适的图标,修改上面的文字和数据即可变为你自己的图标。

项目中的页面:
image.png
重新启动你的java项目:
image.png
如果你的页面粘贴进去之后,重启发现访问不了页面,不是跨域的问题,而是页面没有编译,需要先清理一下编译的内容,然后重启即可。
image.png
什么是跨域?就是两个项目,域名不同,但是需要通信,这个时候叫跨域。

4、编写代码

统计的是订单在家里,公司以及学校的情况。
1)编写一个mapper ,用于查询数据,将查询的结果存放在一个实体中。
创建了一个mapper 包,存放mapper里面的接口

package com.yxh.mapper;

import com.yxh.entry.OrderLocatHourDist;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

/**
 * 此接口,是用来查询数据库的
 */
@Mapper
public interface OrderMapper {

    @Select("select * from order_locat_hour_dist")
    public OrderLocatHourDist selectOrderLocalHour();

}

2)在Controller 中,将数据封装成我们页面需要的数据格式

    @Autowired
    OrderMapper orderMapper;

    /**
     * 出结果了,但是我们的页面需要的是这样类型的数据
     *  {data:[100,234,345]}
     *
     *  alt + enter 导入某个包
     * @return
     */
    @RequestMapping("/listOrders")
    public Map<String,List<Integer>> listOrders(){
        /*
           在此处查询数据库,然后将结果返回给页面
         */
        OrderLocatHourDist orderLocatHourDist = orderMapper.selectOrderLocalHour();
        ArrayList<Integer> list = new ArrayList<>();
        list.add(orderLocatHourDist.getSchool_orders());
        list.add(orderLocatHourDist.getCompany_orders());
        list.add(orderLocatHourDist.getHome_orders());

        Map<String, List<Integer>> map = new HashMap<>();
        map.put("data",list);
        return map;

    }

需要有一个实体,接收我们从数据库查询数据

package com.yxh.entry;

public class OrderLocatHourDist {

    private String dt;
    private int school_orders;
    private int company_orders;
    private int home_orders;
    private int orders_0_5;
    private int orders_6_12;
    private int orders_13_15;
    private int orders_16_20;
    private int orders_21_24;

    public String getDt() {
        return dt;
    }

    public void setDt(String dt) {
        this.dt = dt;
    }

    public int getSchool_orders() {
        return school_orders;
    }

    public void setSchool_orders(int school_orders) {
        this.school_orders = school_orders;
    }

    public int getCompany_orders() {
        return company_orders;
    }

    public void setCompany_orders(int company_orders) {
        this.company_orders = company_orders;
    }

    public int getHome_orders() {
        return home_orders;
    }

    public void setHome_orders(int home_orders) {
        this.home_orders = home_orders;
    }

    public int getOrders_0_5() {
        return orders_0_5;
    }

    public void setOrders_0_5(int orders_0_5) {
        this.orders_0_5 = orders_0_5;
    }

    public int getOrders_6_12() {
        return orders_6_12;
    }

    public void setOrders_6_12(int orders_6_12) {
        this.orders_6_12 = orders_6_12;
    }

    public int getOrders_13_15() {
        return orders_13_15;
    }

    public void setOrders_13_15(int orders_13_15) {
        this.orders_13_15 = orders_13_15;
    }

    public int getOrders_16_20() {
        return orders_16_20;
    }

    public void setOrders_16_20(int orders_16_20) {
        this.orders_16_20 = orders_16_20;
    }

    public int getOrders_21_24() {
        return orders_21_24;
    }

    public void setOrders_21_24(int orders_21_24) {
        this.orders_21_24 = orders_21_24;
    }
}

页面的请求也做了一个修改:
image.png
显示效果:
image.png
第二个指标:

@RequestMapping("/listTimeOrders")
    public Map<String,List<Map<String,String>>> listTimeOrders(){
        OrderLocatHourDist orderLocatHourDist = orderMapper.selectOrderLocalHour();
        HashMap<String, String> map1 = new HashMap<>();
        HashMap<String, String> map2 = new HashMap<>();
        HashMap<String, String> map3 = new HashMap<>();
        HashMap<String, String> map4 = new HashMap<>();
        HashMap<String, String> map5 = new HashMap<>();
        map1.put("name","0~5点");
        map1.put("value",orderLocatHourDist.getOrders_0_5()+"");
        map2.put("name","6~12点");
        map2.put("value",orderLocatHourDist.getOrders_6_12()+"");
        map3.put("name","13~15点");
        map3.put("value",orderLocatHourDist.getOrders_13_15()+"");
        map4.put("name","16~20点");
        map4.put("value",orderLocatHourDist.getOrders_16_20()+"");
        map5.put("name","21~23点");
        map5.put("value",orderLocatHourDist.getOrders_21_24()+"");

        ArrayList<Map<String, String>> list = new ArrayList<>();
        list.add(map1);
        list.add(map2);
        list.add(map3);
        list.add(map4);
        list.add(map5);

        HashMap<String, List<Map<String, String>>> hashMap = new HashMap<>();
        hashMap.put("data",list);
        return hashMap;
    }

第三个指标:

package com.yxh.mapper;

import com.yxh.entry.OrderAgeDistribute;
import com.yxh.entry.OrderLocatHourDist;
import com.yxh.entry.OrderMapDistribute;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

/**
 * 此接口,是用来查询数据库的
 */
@Mapper
public interface OrderMapper {

    @Select("select * from order_locat_hour_dist")
     OrderLocatHourDist selectOrderLocalHour();

    @Select("select * from order_paytype_age_dist")
    OrderAgeDistribute selectOrderPayTypeAge();

    @Select("select * from order_map_dist")
    List<OrderMapDistribute> selectOrderMapDist();

}

响应的数据:

@RequestMapping("/listAgeOrders")
    public Map<String, List<Double>> listAgeOrders(){

        OrderAgeDistribute orderAgeDistribute = orderMapper.selectOrderPayTypeAge();
        ArrayList<Double> list = new ArrayList<>();
        list.add(orderAgeDistribute.getOrders_price_0_16());
        list.add(orderAgeDistribute.getOrders_price_17_25());
        list.add(orderAgeDistribute.getOrders_price_26_35());
        list.add(orderAgeDistribute.getOrders_price_36_60());
        list.add(orderAgeDistribute.getOrders_price_61_80());
        list.add(orderAgeDistribute.getOrders_price_81_pluss());
        Map<String, List<Double>> map = new HashMap<>();
        map.put("data",list);
        return map;
    }

第四个Map:
页面展示

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
    <title></title>
    <!-- Bootstrap Styles-->
    <link href="assets/css/bootstrap.css" rel="stylesheet" />
     <!-- FontAwesome Styles-->
    <link href="assets/css/font-awesome.css" rel="stylesheet" />
        <!-- Custom Styles-->
    <link href="assets/css/custom-styles.css" rel="stylesheet" />
     <!-- Google Fonts-->
   <link href='https://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css' />
    <script src="assets/js/echarts.min.js"></script>
    <script src="assets/js/china.js"></script>
    <script src="assets/js/jquery-3.3.1.min.js"></script>
    <style>
        *{margin:0;padding:0}
        html,body{
            width:100%;
            height:100%;
        }
        #main{
              width:600px;
              height:450px;
              margin: 150px auto;
              border:1px solid #ddd;
          }
        /*默认长宽比0.75*/
    </style>
</head>
<body>
    <div id="wrapper">
        <nav class="navbar navbar-default top-navbar" role="navigation">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".sidebar-collapse">
                    <span class="sr-only">好程序员</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="index.html"><i class="fa fa-gear"></i> <strong>好程序员</strong></a>
            </div>
        </nav>
        <!--/. NAV TOP  -->
        <nav class="navbar-default navbar-side" role="navigation">
            <div class="sidebar-collapse">
                <ul class="nav" id="main-menu">
                    <li>
                        <a href="index.html">
                        <i class="fa fa-dashboard"></i> 网站订单分析</a>
                    </li>
                    <li>
                        <a href="chart.html" >
                        <i class="fa fa-bar-chart-o"></i> 网站用户分析</a>
                    </li>
                    <li>
                        <a href="map.html" class="active-menu">
                        <i class="fa fa-qrcode"></i>地域分析 </a>
                    </li>
                </ul>
            </div>
        </nav>

        <div id="page-wrapper">
            <div id="page-inner">

            </div>
        </div>

        <!--订单分布地图==========-->
        <script type="text/javascript">
        var dataList=[
            {name:"南海诸岛",value:0},
            {name: '北京', value: randomValue()},
            {name: '天津', value: randomValue()},
            {name: '上海', value: randomValue()}
        ]
        var myChart = echarts.init(document.getElementById('page-inner'));
        function randomValue() {
            return Math.round(Math.random()*1000);
        }
        option = {
            tooltip: {
                    formatter:function(params,ticket, callback){
                        return params.seriesName+'<br />'+params.name+':'+params.value
                    }//数据格式化
                },
            visualMap: {
                min: 0,
                max: 50,
                left: 'left',
                top: 'bottom',
                text: ['高','低'],//取值范围的文字
                inRange: {
                    color: ['#e0ffff', '#dd1d17']//取值范围的颜色
                },
                show:true//图注
            },
            geo: {
                map: 'china',
                roam: false,//不开启缩放和平移
                zoom:1.23,//视角缩放比例
                label: {
                    normal: {
                        show: true,
                        fontSize:'10',
                        color: 'rgba(0,0,0,0.7)'
                    }
                },
                itemStyle: {
                    normal:{
                        borderColor: 'rgba(0, 0, 0, 0.2)'
                    },
                    emphasis:{
                        areaColor: '#4df335',//鼠标选择区域颜色
                        shadowOffsetX: 0,
                        shadowOffsetY: 0,
                        shadowBlur: 20,
                        borderWidth: 0,
                        shadowColor: 'rgba(0, 0, 0, 0.5)'
                    }
                }
            },
            series : [
                {
                    name: '订单量',
                    type: 'map',
                    geoIndex: 0,
                    data:[]

                }
            ]
        };
        var url='/mapOrders'
        // 异步加载json格式数据
       $.getJSON(url,function(data){
        myChart.setOption({
            /*xAxis: {
                data: data.categories
            },*/
            series: [{
                // 根据名字对应到相应的系列
                //name: '订单数',
                data: data.data
            }]
        });
    });
        myChart.setOption(option);
        myChart.on('click', function (params) {
            alert(params.name);
        });

      /*  setTimeout(function () {
            myChart.setOption({
                series : [
                    {
                        name: '信息量',
                        type: 'map',
                        geoIndex: 0,
                        data:dataList
                    }
                ]
            });
        },1000)*/
    </script>

</body>

初始化地图:

//首先需要对地图进行初始化
    /**
     * 初始化map
     * @return
     */
    public static List<Map<String,String>> initMap(){
        List<Map<String,String>> maps = new ArrayList<>();
        String[] arr = {"北京","天津","上海","重庆","河北","山西","辽宁","吉林","黑龙江",
                "江苏","浙江","安徽","福建","江西","山东","河南","湖北","湖南","广东",
                "海南","四川","贵州","云南","陕西","甘肃","青海","台湾","内蒙古","广西",
                "西藏","宁夏","新疆","香港","澳门"};
        for (int i=0;i < 34;i++){
            Map<String,String> map = new HashMap<>();
            map.put("name",arr[i]);
            map.put("value","0");
            maps.add(map);
        }
        return maps;
    }

地图上的数据展示:

@RequestMapping("/mapOrders")
    public Map<String, List<Map<String,String>>> mapOrders(){
        List<OrderMapDistribute> mapDistribute = orderMapper.selectOrderMapDist();

        List<Map<String,String>> res1 =initMap();
        // 外面一层是初始化的数据
        for (Map<String,String> m : res1){
            // 数据库中的数据
            for(OrderMapDistribute om : mapDistribute){
                String province = om.getProvince();
                if(province.contains("省")){
                    province = province.replace("省", "");
                }else if(province.contains("市")){
                    province = province.replace("市", "");
                }else if(province.contains("内蒙古")){
                    province = province.substring(0,3);
                }else if(province.contains("自治区")){
                    province = province.substring(0,2);
                }else if(province.contains("特别行政区")){
                    province = province.substring(0,2);
                }

                //判断
                if(province.equals(m.get("name"))){
                    m.put("value",om.order_cnt+"");
                    break;
                }

            }
        }

        Map<String, List<Map<String,String>>> map = new HashMap<>();
        map.put("data",res1);
        return map;
    }

还有两个实体,详见代码。
效果图:
image.png
image.png
image.png