Hadoop (11) of big data technology - website traffic log data analysis system

Table of contents

material:

1. Module development - data preprocessing

1. Analyze preprocessed data

2. Realize data preprocessing

(1) Create a Maven project and add related dependencies

(2) Create a JavaBean object and encapsulate logging

(3) Create a MapReduce program and perform data preprocessing

 2. Module development - data warehouse development

1. Upload files

2. Realize the data warehouse

3. Module development - data analysis

 4. Module development - data export

5. Module development - log analysis system report display

1. Build a log analysis system

(1) Create a project and add related dependencies

(2) Write configuration files

2. Realize the report function display

(1) Create a persistent class

(2) Realize the DAO layer

(3) Realize the Service layer

(4) Realize the Controller layer

(5) Implement page functions

3. Display of system function modules

​edit

Reference books:


material:

http://link: https://pan.baidu.com/s/1aNxbVjNq1z1A-oOIYy_E4Q?pwd=gjpt Extraction code: gjpt icon-default.png?t=MBR7http://link: https://pan.baidu.com/s/1aNxbVjNq1z1A-oOIYy_E4Q ?pwd=gjpt extraction code: gjpt

1. Module development - data preprocessing

1. Analyze preprocessed data

        In the collected log files, under normal circumstances, the log files cannot be directly analyzed for data, because there are many illegal data in the log files (for example, the log data is lost during network transmission).

        In the data preprocessing stage, the main purpose is to clean and filter the collected raw data, so it can be easily realized by using MapReduce technology. In actual development, the data preprocessing process usually does not directly delete illegal data, but adds an identification field to each piece of data, so as to avoid data loss when used by other businesses.

        In addition, this data preprocessing is only to clean and filter illegal data information. It will read each line of log file data and finally output a piece of data, and will not perform other operations. Therefore, in the process of processing using MapReduce technology, it will only involve The Map phase does not involve the Reduce phase. By default, the ReduceTask value is 1, so in the main running function, Job.setNumReduceTasks(0) needs to be set.

2. Realize data preprocessing

(1) Create a Maven project and add related dependencies

The pom.xml file is configured as follows:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.itcast</groupId>
    <artifactId>HadoopDataReport</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>2.10.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>2.10.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs</artifactId>
            <version>2.10.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-mapreduce-client-core</artifactId>
            <version>2.10.1</version>
        </dependency>

    </dependencies>


</project>

(2) Create a JavaBean object and encapsulate logging

        In the collected log data, each line represents a log record and contains multiple field information separated by spaces. To facilitate subsequent data processing, a JavaBean object is created to encapsulate each piece of data.

WebLogBean.java

package cn.itcast.weblog.bean;

import org.apache.hadoop.io.Writable;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

/**
 * 对接外部数据的层,表结构定义最好跟外部数据源保持一致
 * 同时实现序列号,方便网络数据传播
 */
public class WebLogBean implements Writable {
    private boolean valid = true;   //标记数据是否合法
    private String remote_addr;     //访客IP地址
    private String remote_user;     //记录访客用户信息,忽略属性“-”
    private String time_local;      //记录访问时间与时区
    private String request;         //记录请求的URL
    private String status;          //请求状态
    private String body_bytes_sent; //记录发送给客户端文件主体内容大小
    private String http_referer;    //记录从哪个页面链接访问过来的
    private String http_user_agent; //记录客户浏览器的相关信息

    //设置 WebLogBean 进行字段数据封装
    public void setBean(boolean valid, String remote_addr, String remote_user,
                        String time_local, String request, String status,
                        String body_bytes_sent,
                        String http_referer, String http_user_agent) {
        this.valid = valid;
        this.remote_addr = remote_addr;
        this.remote_user = remote_user;
        this.time_local = time_local;
        this.request = request;
        this.status = status;
        this.body_bytes_sent = body_bytes_sent;
        this.http_referer = http_referer;
        this.http_user_agent = http_user_agent;
    }

    public boolean isValid() {
        return valid;
    }

    public void setValid(boolean valid) {
        this.valid = valid;
    }

    public String getRemote_addr() {
        return remote_addr;
    }

    public void setRemote_addr(String remote_addr) {
        this.remote_addr = remote_addr;
    }

    public String getRemote_user() {
        return remote_user;
    }

    public void setRemote_user(String remote_user) {
        this.remote_user = remote_user;
    }

    public String getTime_local() {
        return time_local;
    }

    public void setTime_local(String time_local) {
        this.time_local = time_local;
    }

    public String getRequest() {
        return request;
    }

    public void setRequest(String request) {
        this.request = request;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getBody_bytes_sent() {
        return body_bytes_sent;
    }

    public void setBody_bytes_sent(String body_bytes_sent) {
        this.body_bytes_sent = body_bytes_sent;
    }

    public String getHttp_referer() {
        return http_referer;
    }

    public void setHttp_referer(String http_referer) {
        this.http_referer = http_referer;
    }

    public String getHttp_user_agent() {
        return http_user_agent;
    }

    public void setHttp_user_agent(String http_user_agent) {
        this.http_user_agent = http_user_agent;
    }

    //重写 toString() 方法,使用 Hive 默认分隔符进行分隔,为后续导入 Hive 表提供便利
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(valid);

        sb.append("\001").append(this.getRemote_addr());
        sb.append("\001").append(this.getRemote_user());
        sb.append("\001").append(this.getTime_local());
        sb.append("\001").append(this.getRequest());
        sb.append("\001").append(this.getStatus());
        sb.append("\001").append(this.getBody_bytes_sent());
        sb.append("\001").append(this.getHttp_referer());
        sb.append("\001").append(this.getHttp_user_agent());
        return sb.toString();
    }

    //序列化方法

    @Override
    public void readFields(DataInput dataInput) throws IOException {
        this.valid = dataInput.readBoolean();
        this.remote_addr = dataInput.readUTF();
        this.remote_user = dataInput.readUTF();
        this.time_local = dataInput.readUTF();
        this.request = dataInput.readUTF();
        this.status = dataInput.readUTF();
        this.body_bytes_sent = dataInput.readUTF();
        this.http_referer = dataInput.readUTF();
        this.http_user_agent = dataInput.readUTF();
    }

    // 反序列化方法(注意与序列化方法顺序保持一致)

    @Override
    public void write(DataOutput dataOutput) throws IOException {
        dataOutput.writeBoolean(this.valid);
        dataOutput.writeUTF(this.remote_addr);
        dataOutput.writeUTF(this.remote_user);
        dataOutput.writeUTF(this.time_local);
        dataOutput.writeUTF(this.request);
        dataOutput.writeUTF(this.status);
        dataOutput.writeUTF(this.body_bytes_sent);
        dataOutput.writeUTF(this.http_referer);
        dataOutput.writeUTF(this.http_user_agent);
    }
}

(3) Create a MapReduce program and perform data preprocessing

        After creating the JavaBean entity class, the next step is to write the MapReduce program for data preprocessing.

WebLogPreProcess.java

package cn.itcast.weblog.preproces;

import cn.itcast.weblog.bean.WebLogBean;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

/**
 *  日志数据处理:数据清洗、日期格式转换、缺失字段填充默认值、字段添加合法标记
 */
public class WebLogPreProcess {
    public static void main(String[] args) throws Exception{
        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf);
        job.setJarByClass(WebLogPreProcess.class);
        job.setMapperClass(WebLogPreProcessMapper.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(NullWritable.class);
        //此次案例测试数据不是非常大,所以使用本地路径
        //(实际情况会对 HDFS 上存储的文件进行处理)
        FileInputFormat.setInputPaths(job, new Path("/home/huanganchi/Hadoop/实训项目/HadoopDemo/textHadoop/weblog/input"));
        FileOutputFormat.setOutputPath(job, new Path("/home/huanganchi/Hadoop/实训项目/HadoopDemo/textHadoop/weblog/output"));
        //将 ReduceTask 属设置为 0,不需要 Reduce 阶段
        job.setNumReduceTasks(0);
        boolean res = job.waitForCompletion(true);
        System.exit(res ? 0 : 1);
    }
    //mapreduce 程序 map 阶段
    public static class WebLogPreProcessMapper extends Mapper<LongWritable, Text, Text, NullWritable> {
        //用来存储网站 URL 分类数据
        Set<String> pages = new HashSet<String>();
        Text k = new Text();
        NullWritable v = NullWritable.get();
        /**
         * 设置初始化方法, 用来表示用户请求的是合法数据
         */
        @Override
        protected void setup(Context context) throws IOException, InterruptedException {
            pages.add("/about");
            pages.add("/black-ip-list");
            pages.add("/cassendra-cluster/");
            pages.add("/finance-rhive-repurchase");
            pages.add("/hadoop-family-roadmad");
            pages.add("/hadoop-hive-intro/");
            pages.add("/hadoop-zookeeper-intro");
            pages.add("/hadoop-mahout-roadmap");
        }
        /**
         * 重写 map()方法,对每行记录重新解析转换并输出
         */
        @Override
        protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
            //获取一行数据
            String line = value.toString();
            //调用解析类 WebLogParser 解析日志数据,最后封装为 WebLogBean 对象
            WebLogBean webLogBean = WebLogParser.parser(line);
            if (webLogBean != null) {
                //过滤 js/图片/css 等静态资源

                WebLogParser.filtStaticResource(webLogBean, pages);
                k.set(webLogBean.toString());
                context.write(k, v);
            }
        }
    }
}

WebLogParser.java

package cn.itcast.weblog.preproces;

import cn.itcast.weblog.bean.WebLogBean;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.Set;

public class WebLogParser {
    //定义时间格式
    public static SimpleDateFormat df1 = new SimpleDateFormat("dd/MMM/yyyy:HH:mm:ss", Locale.US);
    public static SimpleDateFormat df2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);

    /**
     * 根据采集的数据字段信息进行解析封装
     */
    public static WebLogBean parser(String line) {
        WebLogBean webLogBean = new WebLogBean();
        //把一行数据以空格字符切割并存入数组arr中
        String[] arr = line.split(" ");
        //如果数组长度小于等于11,说明这条数据不完整,因此可以忽略这条数据
        if (arr.length > 11) {
            //满足条件的数据逐个赋值给webLogBean对象
            webLogBean.setRemote_addr(arr[0]);
            webLogBean.setRemote_user(arr[1]);
            String time_local = formatDate(arr[3].substring(1));
            if (null == time_local || "".equals(time_local)) time_local = "-invalid_time-";
            webLogBean.setTime_local(time_local);
            webLogBean.setRequest(arr[6]);
            webLogBean.setStatus(arr[8]);
            webLogBean.setBody_bytes_sent(arr[9]);
            webLogBean.setHttp_referer(arr[10]);
            //如果useragent元素较多,拼接useragent
            if (arr.length > 12) {
                StringBuilder sb = new StringBuilder();
                for (int i = 11; i < arr.length; i++) {
                    sb.append(arr[i]);
                }
                webLogBean.setHttp_user_agent(sb.toString());
            } else {
                webLogBean.setHttp_user_agent(arr[11]);
            }
            //大于 400,HTTP 错误
            if (Integer.parseInt(webLogBean.getStatus()) >= 400) {
                webLogBean.setValid(false);
            }
            if ("-invalid_time-".equals(webLogBean.getTime_local())) {
                webLogBean.setValid(false);
            }
        } else {
            webLogBean = null;
        }
        return webLogBean;
    }
    //对请求路径资源是否合法进行标记
    public static void filtStaticResource(WebLogBean bean, Set<String> pages) {
        if (!pages.contains(bean.getRequest())) {
            bean.setValid(false);
        }
    }
    //格式化时间方法
    public static String formatDate(String time_local) {
        try {
            return df2.format(df1.parse(time_local));
        } catch (ParseException e) {
            return null;
        }
    }
}

operation result:

 2. Module development - data warehouse development

1. Upload files

Create a directory weblog under the root directory of the Linux system where Hadoop is started, and upload the result files generated by the preprocessing to the weblog directory.

cd
mkdir weblog
cd weblog
执行 rz 文件上传命令

Create a directory on HDFS to store preprocessed data and upload the data to HDFS.

hadoop fs -mkdir -p /weblog/preprocessed
hadoop fs -put part-m-00000 /weblog/preprocessed

2. Realize the data warehouse

启动Hive数据仓库,执行以下操作:

--创建数据仓库
DROP DATABASE IF EXISTS weblog;
CREATE DATABASE weblog;

USE weblog;

--创建表
CREATE TABLE ods_weblog_origin (
	valid string,	--有效标志
	remote_addr string, --来源IP
	remote_user string,	--用户标志
	time_local string,	--访问完整时间
	request string,		--请求的URL
	status string,		--响应码
	body_bytes_sent string,	--传输字节数
	http_referer string,	--来源URL
	http_user_agent string	--客户终端标志
	)
	partitioned by (datestr string)
	row format delimited fields terminated by '\001';

--导入数据
load data inpath '/weblog/preprocessed' overwrite into table ods_weblog_origin partition(datestr='20130918');

--生成明细表
--1. 创建明细表 ods_weblog_detwail 
CREATE TABLE ods_weblog_detwail (
	valid 		string,	--有效标志
	remote_addr	string, --来源IP
	remote_user	string,	--用户标志
	time_local 	string,	--访问完整时间
	daystr 		string,	--访问日期
	timestr 	string,	--访问时间
	month 	 	string,	--访问月
	day 	 	string,	--访问日
	hour 	 	string,	--访问时
	request 	string,	--请求的URL
	status 		string,		--响应码
	body_bytes_sent string,	--传输字节数
	http_referer 	string,	--来源URL
	ref_host 		string,	--来源的host
	ref_path		string,	--来源路径
	ref_query		string,	--来源参数query
	ref_query_id	string,	--来源参数query的值
	http_user_agent string	--客户终端标志
	)
	partitioned by (datestr string);
	
--2. 创建临时中间表 t_ods_tmp_referurl
CREATE TABLE t_ods_tmp_referurl as 	SELECT a.*, b.* 
	FROM ods_weblog_origin a LATERAL VIEW
	parse_url_tuple(regexp_replace(http_referer, "\"", ""),'HOST', 'PATH', 'QUERY', 'QUERY:id') b 
	as host, path, query, query_id;
	
--3. 创建临时中间表 t_ods_tmp_detail
CREATE TABLE t_ods_tmp_detail as 
	SELECT b.*, substring(time_local, 0, 10) as daystr,  
	substring(time_local, 12) as tmstr,
	substring(time_local, 6, 2) as month,
	substring(time_local, 9, 2) as day,
	substring(time_local, 11, 3) as hour
	FROM t_ods_tmp_referurl b;
	
--4. 修改默认动态分区参数
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;

--5. 向 ods_weblog_detwail 表中加载数据
insert overwrite table ods_weblog_detwail partition(datestr)
SELECT DISTINCT otd.valid, otd.remote_addr, otd.remote_user, 
otd.time_local, otd.daystr, otd.tmstr, otd.month, otd.day, otd.hour,
otr.request, otr.status, otr.body_bytes_sent,
otr.http_referer, otr.host, otr.path,
otr.query, otr.query_id, otr.http_user_agent, otd.daystr
FROM t_ods_tmp_detail as otd, t_ods_tmp_referurl as otr
WHERE otd.remote_addr = otr.remote_addr
AND otd.time_local = otr.time_local
AND otd.body_bytes_sent = otr.body_bytes_sent
AND otd.request = otr.request;

 

3. Module development - data analysis

--数据分析
--流量分析
--创建每日访问量表dw_pvs_everyday
CREATE TABLE IF NOT EXISTS dw_pvs_everyday(pvs bigint, month string, day string);

--从宽表 ods_weblog_detwail 获取每日访问量数据并插入维度表 dw_pvs_everyday
INSERT INTO TABLE dw_pvs_everyday
SELECT COUNT(*) AS pvs, owd.month AS month, owd.day AS day 
FROM ods_weblog_detwail owd GROUP BY owd.month, owd.day;

--人均浏览量分析
--创建维度表dw_avgpv_user_everyday
CREATE TABLE  IF NOT EXISTS dw_avgpv_user_everyday (day string, avgpv string);

--从宽表 ods_weblog_detwail 获取相关数据并插入维度表 dw_avgpv_user_everyday
INSERT INTO TABLE dw_avgpv_user_everyday
SELECT '2013-09-18', SUM(b.pvs)/COUNT(b.remote_addr) FROM
(SELECT remote_addr, COUNT(1) AS pvs FROM ods_weblog_detwail WHERE
datestr = '2013-09-18' GROUP by remote_addr) b;

INSERT INTO TABLE dw_avgpv_user_everyday
SELECT '2013-09-19', SUM(b.pvs)/COUNT(b.remote_addr) FROM
(SELECT remote_addr, COUNT(1) AS pvs FROM ods_weblog_detwail WHERE
datestr = '2013-09-19' GROUP by remote_addr) b;

INSERT INTO TABLE dw_avgpv_user_everyday
SELECT '2013-09-20', SUM(b.pvs)/COUNT(b.remote_addr) FROM
(SELECT remote_addr, COUNT(1) AS pvs FROM ods_weblog_detwail WHERE
datestr = '2013-09-20' GROUP by remote_addr) b;

INSERT INTO TABLE dw_avgpv_user_everyday
SELECT '2013-09-21', SUM(b.pvs)/COUNT(b.remote_addr) FROM
(SELECT remote_addr, COUNT(1) AS pvs FROM ods_weblog_detwail WHERE
datestr = '2013-09-21' GROUP by remote_addr) b;

INSERT INTO TABLE dw_avgpv_user_everyday
SELECT '2013-09-22', SUM(b.pvs)/COUNT(b.remote_addr) FROM
(SELECT remote_addr, COUNT(1) AS pvs FROM ods_weblog_detwail WHERE
datestr = '2013-09-22' GROUP by remote_addr) b;

INSERT INTO TABLE dw_avgpv_user_everyday
SELECT '2013-09-23', SUM(b.pvs)/COUNT(b.remote_addr) FROM
(SELECT remote_addr, COUNT(1) AS pvs FROM ods_weblog_detwail WHERE
datestr = '2013-09-23' GROUP by remote_addr) b;

INSERT INTO TABLE dw_avgpv_user_everyday
SELECT '2013-09-24', SUM(b.pvs)/COUNT(b.remote_addr) FROM
(SELECT remote_addr, COUNT(1) AS pvs FROM ods_weblog_detwail WHERE
datestr = '2013-09-24' GROUP by remote_addr) b;

 4. Module development - data export

1. 创建 MySql 数据库和表
--数据导出
--创建数据仓库
DROP DATABASE IF EXISTS sqoopdb;
CREATE DATABASE sqoopdb;

USE sqoopdb;

--创建表
CREATE TABLE t_avgpv_num (
dateStr VARCHAR(255) DEFAULT NULL,
avgPvNum DECIMAL(6,2) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;


2. 执行数据导出命令
sqoop export \
--connect jdbc:mysql://hadoop01.bgd01:3306/sqoopdb \
--username root \
--password 123456 \
--table t_avgpv_num \
--columns "dateStr,avgPvNum" \
--fields-terminated-by '\001' \
--export-dir /user/hive/warehouse/weblog.db/dw_avgpv_user_everyday

5. Module development - log analysis system report display

1. Build a log analysis system

(1) Create a project and add related dependencies

        Create a Maven project for the Java Web Framework

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.itcast</groupId>
    <artifactId>Weblog</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>
    <dependencies>
        <!-- Spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jms</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
        <!-- Mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.2.8</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.2.2</version>
        </dependency>
        <dependency>
            <groupId>com.github.miemiedev</groupId>
            <artifactId>mybatis-paginator</artifactId>
            <version>1.2.15</version>
        </dependency>
        <!-- MySql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.32</version>
        </dependency>
        <!-- 连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.9</version>
        </dependency>
        <!-- JSP相关 -->
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.4.2</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>

        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.2</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>

            <!-- 配置Tomcat插件 -->
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <path>/</path>
                    <port>8080</port>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

(2) Write configuration files

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/beans"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">

	<!-- 数据库连接池 -->
	<!-- 加载配置文件 -->
	<context:property-placeholder location="classpath:properties/db.properties" />
	<!-- 数据库连接池 -->
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
		destroy-method="close">
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
		<property name="driverClassName" value="${jdbc.driver}" />
		<property name="maxActive" value="10" />
		<property name="minIdle" value="5" />
	</bean>
	<!-- 让spring管理sqlsessionfactory使用mybatis和spring整合包中的 -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- 数据库连接池 -->
		<property name="dataSource" ref="dataSource" />
		<!-- 加载mybatis的全局配置文件 -->
		<property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml" />
	</bean>
	<!-- 使用扫描包的形式来创建mapper代理对象 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="cn.itcast.mapper" />
	</bean>

	<!-- 事务管理器 -->
	<bean id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<!-- 数据源 -->
		<property name="dataSource" ref="dataSource" />
	</bean>
	<!-- 通知 -->
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<!-- 传播行为 -->
			<tx:method name="save*" propagation="REQUIRED" />
			<tx:method name="insert*" propagation="REQUIRED" />
			<tx:method name="add*" propagation="REQUIRED" />
			<tx:method name="create*" propagation="REQUIRED" />
			<tx:method name="delete*" propagation="REQUIRED" />
			<tx:method name="update*" propagation="REQUIRED" />
			<tx:method name="find*" propagation="SUPPORTS" read-only="true" />
			<tx:method name="select*" propagation="SUPPORTS" read-only="true" />
			<tx:method name="get*" propagation="SUPPORTS" read-only="true" />
		</tx:attributes>
	</tx:advice>
	<!-- 切面 -->
	<aop:config>
		<aop:advisor advice-ref="txAdvice"
			pointcut="execution(* cn.itcast.service..*.*(..))" />
	</aop:config>

	<!-- 配置包扫描器,扫描所有带@Service注解的类 -->
	<context:component-scan base-package="cn.itcast.service" />

</beans>

db.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://192.168.8.201:3306/sqoopdb?characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456

springmvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd">

	<!-- 扫描指定包路径 使路径当中的@controller注解生效 -->
	<context:component-scan base-package="cn.itcast.controller" />
	<!-- mvc的注解驱动  -->
	<mvc:annotation-driven />
	
	<!-- 视图解析器 -->
	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/jsp/" />
		<property name="suffix" value=".jsp" />
	</bean>
	
	<!-- 配置资源映射 -->
	<mvc:resources location="/css/" mapping="/css/**"/>
	<mvc:resources location="/js/" mapping="/js/**"/>
	<mvc:resources location="/echarts/" mapping="/echarts/**"/>
	<mvc:resources location="/assets/" mapping="/assets/**"/>
	<mvc:resources location="/img/" mapping="/img/**"/>
</beans>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
  <display-name>Weblog</display-name>
  
  <welcome-file-list>
		<welcome-file>index.html</welcome-file>
	</welcome-file-list>

	<!-- 加载spring容器 -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:spring/applicationContext.xml</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- 解决post乱码 -->
	<filter>
		<filter-name>CharacterEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>utf-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>CharacterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

	<!-- 配置springmvc的前端控制器 -->
	<servlet>
		<servlet-name>data-report</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:spring/springmvc.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	
	<!-- 拦截所有请求 jsp除外 -->
	<servlet-mapping>
		<servlet-name>data-report</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

	<!-- 全局错误页面 -->
	<error-page>
		<error-code>404</error-code>
		<location>/WEB-INF/jsp/404.jsp</location>
	</error-page>
  
</web-app>

 SqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
</configuration>

2. Realize the report function display

(1) Create a persistent class

TAvgpvNum.java

package cn.itcast.pojo;

import java.math.BigDecimal;

public class TAvgpvNum {
	private String datestr;// 日期
	private BigDecimal avgpvnum;// 平均PV数量

	public String getDatestr() {
		return datestr;
	}

	public void setDatestr(String datestr) {
		this.datestr = datestr == null ? null : datestr.trim();
	}

	public BigDecimal getAvgpvnum() {
		return avgpvnum;
	}

	public void setAvgpvnum(BigDecimal avgpvnum) {
		this.avgpvnum = avgpvnum;
	}
}

AvgToPageBean.java

package cn.itcast.pojo;

public class AvgToPageBean {

    private String[] dates;

    private double[] data;

    public String[] getDates() {
        return dates;
    }

    public void setDates(String[] dates) {
        this.dates = dates;
    }

    public double[] getData() {
        return data;
    }

    public void setData(double[] data) {
        this.data = data;
    }

}

(2) Realize the DAO layer

TAvgpvNumMapper.java

package cn.itcast.mapper;

import java.util.List;

import cn.itcast.pojo.TAvgpvNum;

public interface TAvgpvNumMapper {

	public List<TAvgpvNum> selectByDate(String startDate, String endDate);

}

TAvgpvNumMapper.xml

<?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" >
<mapper namespace="cn.itcast.mapper.TAvgpvNumMapper">

	<select id="selectByDate" resultType="cn.itcast.pojo.TAvgpvNum"
		parameterType="String">
		select *
		from t_avgpv_num
		where dateStr between #{0} and #{1} order by dateStr asc;
	</select>

</mapper>

(3) Realize the Service layer

AvgPvService.java

package cn.itcast.service;

public interface AvgPvService {

    //根据日期查询数据
	public String getAvgPvNumByDates(String startDate, String endDate);

}

AvgPvServiceImpl.java

package cn.itcast.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import cn.itcast.mapper.TAvgpvNumMapper;
import cn.itcast.pojo.AvgToPageBean;
import cn.itcast.pojo.TAvgpvNum;
import cn.itcast.service.AvgPvService;

@Service
public class AvgPvServiceImpl implements AvgPvService {

	@Autowired
	private TAvgpvNumMapper mapper;

	@Override
	public String getAvgPvNumByDates(String startDate, String endDate) {
		
		//调用查询方法
		List<TAvgpvNum> lists = mapper.selectByDate(startDate, endDate);
		// 数组大小
		int size = 7;
		//保存日期数据
		String[] dates = new String[size];
		//保存人均浏览页面数据
		double[] datas = new double[size];
		int i = 0;
		for (TAvgpvNum tAvgpvNum : lists) {
			dates[i] = tAvgpvNum.getDatestr();
			datas[i] = tAvgpvNum.getAvgpvnum().doubleValue();
			i++;
		}
		//定义AvgToPageBean对象,用于前台页面展示
		AvgToPageBean bean = new AvgToPageBean();
		bean.setDates(dates);
		bean.setData(datas);
		//Jackson提供的类,用于把对象转换成Json字符串
		ObjectMapper om = new ObjectMapper();
		String beanJson = null;
		try {
			beanJson = om.writeValueAsString(bean);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		//返回Json格式的对象
		return beanJson;
	}

}

(4) Realize the Controller layer

IndexController.java

package cn.itcast.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import cn.itcast.service.AvgPvService;


@Controller
public class IndexController {

	@Autowired
	private AvgPvService pvService;

	@RequestMapping("/index")
	public String showIndex() {
		return "index";
	}

	@RequestMapping(value = "/avgPvNum", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public String getChart() {
		System.out.println("获取平均pv数据..");
		String data = pvService.getAvgPvNumByDates("2013-09-18", "2013-09-24");
		return data;
	}

}

(5) Implement page functions

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="en">
<head>
<!-- BEGIN META -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="Olive Enterprise">
<!-- END META -->
<script src="/js/jquery-1.11.3.min.js"></script>
<script src="/js/echarts.min.js"></script>
<script src="/js/china.js"></script>

<!-- BEGIN SHORTCUT ICON -->
<link rel="shortcut icon" href="/img/favicon.ico">
<!-- END SHORTCUT ICON -->
<title>流量运营分析 - pinyougou®itcast全站数据平台</title>
<!-- BEGIN STYLESHEET-->
<link href="/css/bootstrap.min.css" rel="stylesheet">
<!-- BOOTSTRAP CSS -->
<link href="/css/bootstrap-reset.css" rel="stylesheet">
<!-- BOOTSTRAP CSS -->
<link href="/assets/font-awesome/css/font-awesome.css" rel="stylesheet">
<!-- FONT AWESOME ICON CSS -->
<link href="/css/style.css" rel="stylesheet">
<!-- THEME BASIC CSS -->
<link href="/css/style-responsive.css" rel="stylesheet">
<!-- THEME RESPONSIVE CSS -->
<link href="/assets/morris.js-0.4.3/morris.css" rel="stylesheet">
<!-- MORRIS CHART CSS -->
<!--dashboard calendar-->
<link href="/css/clndr.css" rel="stylesheet">
<!-- CALENDER CSS -->
<!--[if lt IE 9]>
		<script src="js/html5shiv.js">
		</script>
		<script src="js/respond.min.js">
		</script>
		<![endif]-->
<!-- END STYLESHEET-->

</head>
<body>
	<!-- BEGIN SECTION -->
	<section id="container">
		<!-- BEGIN HEADER -->
		<header class="header white-bg">
			<!-- SIDEBAR TOGGLE BUTTON -->
			<div class="sidebar-toggle-box">
				<div data-placement="right" class="fa fa-bars tooltips"></div>
			</div>
			<!-- SIDEBAR TOGGLE BUTTON  END-->
			<a href="index.html" class="logo"> ITCAST <span> PINYOUGOU
			</span><span> 全站流量运营分析 </span>
			</a>
			<!-- START HEADER  NAV -->

			<nav class="nav notify-row" id="top_menu">

				<ul class="nav top-menu">
					<!-- START NOTIFY TASK BAR -->

					<li class="dropdown"><a data-toggle="dropdown"
						class="dropdown-toggle" href="#"> <i class="fa fa-tasks">
						</i> <span class="badge bg-success"> 6 </span>
					</a>

						<ul class="dropdown-menu extended tasks-bar">
							<li class="notify-arrow notify-arrow-blue"></li>
							<li>
								<p class="blue">You have 6 pending tasks</p>
							</li>
							<li><a href="#">
									<div class="task-info">
										<div class="desc">Dashboard v1.3</div>
										<div class="percent">40%</div>
									</div>
									<div class="progress progress-striped">
										<div class="progress-bar progress-bar-success set-40"
											role="progressbar" aria-valuenow="40" aria-valuemin="0"
											aria-valuemax="100">
											<span class="sr-only"> 40% Complete (success) </span>
										</div>
									</div>
							</a></li>
							<li><a href="#">
									<div class="task-info">
										<div class="desc">Database Update</div>
										<div class="percent">60%</div>
									</div>
									<div class="progress progress-striped">
										<div class="progress-bar progress-bar-warning set-60"
											role="progressbar" aria-valuenow="60" aria-valuemin="0"
											aria-valuemax="100">
											<span class="sr-only"> 60% Complete (warning) </span>
										</div>
									</div>
							</a></li>
							<li><a href="#">
									<div class="task-info">
										<div class="desc">Iphone Development</div>
										<div class="percent">87%</div>
									</div>
									<div class="progress progress-striped">
										<div class="progress-bar progress-bar-info set-87"
											role="progressbar" aria-valuenow="20" aria-valuemin="0"
											aria-valuemax="100">
											<span class="sr-only"> 87% Complete </span>
										</div>
									</div>
							</a></li>
							<li><a href="#">
									<div class="task-info">
										<div class="desc">Mobile App</div>
										<div class="percent">33%</div>
									</div>
									<div class="progress progress-striped">
										<div class="progress-bar progress-bar-danger set-33"
											role="progressbar" aria-valuenow="80" aria-valuemin="0"
											aria-valuemax="100">
											<span class="sr-only"> 33% Complete (danger) </span>
										</div>
									</div>
							</a></li>
							<li><a href="#">
									<div class="task-info">
										<div class="desc">Dashboard v1.3</div>
										<div class="percent">45%</div>
									</div>
									<div class="progress progress-striped active">
										<div class="progress-bar set-45" role="progressbar"
											aria-valuenow="45" aria-valuemin="0" aria-valuemax="100">
											<span class="sr-only"> 45% Complete </span>
										</div>

									</div>
							</a></li>
							<li class="external"><a href="#"> See All Tasks </a></li>
						</ul></li>
					<!-- END NOTIFY TASK BAR -->

					<!-- START NOTIFY INBOX BAR -->

					<li id="header_inbox_bar" class="dropdown"><a
						data-toggle="dropdown" class="dropdown-toggle" href="#"> <i
							class="fa fa-envelope-o"> </i> <span class="badge bg-important">
								5 </span>
					</a>
						<ul class="dropdown-menu extended inbox">
							<li class="notify-arrow notify-arrow-blue"></li>
							<li>
								<p class="blue">You have 5 new messages</p>
							</li>
							<li><a href="#"> <span class="photo"> <img
										alt="avatar" src="./img/avatar-mini.jpg">
								</span> <span class="subject"> <span class="from">
											Chintan Pandya </span> <span class="time"> Just now </span>
								</span> <span class="message"> Hello, this is an example msg. </span>
							</a></li>
							<li><a href="#"> <span class="photo"> <img
										alt="avatar" src="./img/avatar-mini2.jpg">
								</span> <span class="subject"> <span class="from"> Parth
											Jani </span> <span class="time"> 10 mins </span>
								</span> <span class="message"> Hi, Bro how are you ? </span>
							</a></li>
							<li><a href="#"> <span class="photo"> <img
										alt="avatar" src="./img/avatar-mini3.jpg">
								</span> <span class="subject"> <span class="from"> Jay
											Bardolia </span> <span class="time"> 3 hrs </span>
								</span> <span class="message"> This is awesome dashboard. </span>
							</a></li>
							<li><a href="#"> <span class="photo"> <img
										alt="avatar" src="./img/avatar-mini4.jpg">
								</span> <span class="subject"> <span class="from"> ADMIN
											BLACK </span> <span class="time"> Just now </span>
								</span> <span class="message"> Hello, this is metrolab </span>
							</a></li>
							<li><a href="#"> See all messages </a></li>
						</ul></li>
					<!-- END NOTIFY INBOX BAR -->

					<!-- START NOTIFY NOTIFICATION BAR -->

					<li id="header_notification_bar" class="dropdown"><a
						data-toggle="dropdown" class="dropdown-toggle" href="#"> <i
							class="fa fa-bell-o"> </i> <span class="badge bg-warning">
								7 </span>
					</a>
						<ul class="dropdown-menu extended notification">
							<li class="notify-arrow notify-arrow-blue"></li>
							<li>
								<p class="blue">You have 7 new notifications</p>
							</li>
							<li><a href="#"> <span class="label label-danger">
										<i class="fa fa-bolt"> </i>
								</span> Server #3 overloaded. <span class="small italic"> 34
										mins </span>
							</a></li>
							<li><a href="#"> <span class="label label-warning">
										<i class="fa fa-bell"> </i>
								</span> Server #10 not respoding. <span class="small italic"> 1
										Hours </span>
							</a></li>
							<li><a href="#"> <span class="label label-danger">
										<i class="fa fa-bolt"> </i>
								</span> Database overloaded 24%. <span class="small italic"> 4
										hrs </span>
							</a></li>
							<li><a href="#"> <span class="label label-success">
										<i class="fa fa-plus"> </i>
								</span> New user registered. <span class="small italic"> Just
										now </span>
							</a></li>
							<li><a href="#"> <span class="label label-primary">
										<i class="fa fa-bullhorn"> </i>
								</span> Application error. <span class="small italic"> 10 mins </span>
							</a></li>
							<li><a href="#"> See all notifications </a></li>
						</ul></li>
					<!-- END NOTIFY NOTIFICATION BAR -->

				</ul>


			</nav>
			<!-- END HEADER NAV -->

			<!-- START USER LOGIN DROPDOWN  -->

			<div class="top-nav ">
				<ul class="nav pull-right top-menu">
					<li><input type="text" class="form-control search"
						placeholder="Search"></li>
					<li class="dropdown"><a data-toggle="dropdown"
						class="dropdown-toggle" href="#"> <img alt=""
							src="img/avatar1_small.jpg"> <span class="username">
								ADMIN BLACK </span> <b class="caret"> </b>
					</a>
						<ul class="dropdown-menu extended logout">
							<li class="log-arrow-up"></li>
							<li><a href="#"> <i class=" fa fa-suitcase"> </i>
									Profile
							</a></li>
							<li><a href="#"> <i class="fa fa-cog"> </i> Settings
							</a></li>
							<li><a href="#"> <i class="fa fa-bell-o"> </i>
									Notification
							</a></li>
							<li><a href="login.html"> <i class="fa fa-key"> </i> Log
									Out
							</a></li>
						</ul></li>
				</ul>
			</div>
			<!-- END USER LOGIN DROPDOWN  -->
		</header>
		<!-- END HEADER -->
		<!-- BEGIN SIDEBAR -->
		<aside>
			<div id="sidebar" class="nav-collapse">
				<ul class="sidebar-menu" id="nav-accordion">
					<li><a href="index.html" class="active"> <i
							class="fa fa-dashboard"> </i> <span> 流量概况 </span>
					</a></li>


					<li class="sub-menu"><a href="javascript:;"> <i
							class="fa fa-book"> </i> <span> 流量分析 </span>
					</a>
						<ul class="sub">
							<li><a href="flow-trend.html"> 趋势分析 </a></li>
							<li><a href="flow-contract.html"> 对比分析 </a></li>
							<li><a href="flow-online.html"> 当前在线 </a></li>
							<li><a href="flow-detail.html"> 访问明细 </a></li>
						</ul></li>

					<li class="sub-menu"><a href="javascript:;"> <i
							class="fa fa-th"> </i> <span> 来源分析 </span>
					</a>
						<ul class="sub">
							<li><a href="#"> 来源分类 </a></li>
							<li><a href="#"> 搜索引擎 </a></li>
							<li><a href="#"> 搜索词 </a></li>
							<li><a href="#"> 来路域名 </a></li>
							<li><a href="#"> 来路页面 </a></li>
						</ul></li>

					<li class="sub-menu"><a href="javascript:;"> <i
							class="fa fa-book"> </i> <span> 受访分析 </span>
					</a>
						<ul class="sub">
							<li><a href="#"> 受访分析 </a></li>
							<li><a href="#"> 受访域名 </a></li>
							<li><a href="#"> 受访页面 </a></li>
							<li><a href="#"> 受访升降榜 </a></li>
							<li><a href="#"> 热点图 </a></li>
						</ul></li>

					<li class="sub-menu"><a href="javascript:;"> <i
							class="fa fa-th"> </i> <span> 访客分析 </span>
					</a>
						<ul class="sub">
							<li><a href="basic_table.html"> 地区/运营商 </a></li>
							<li><a href="responsive_table.html">终端详情 </a></li>
							<li><a href="dynamic_table.html"> 新老访客</a></li>
							<li><a href="advanced_table.html"> 忠诚度 </a></li>
							<li><a href="editable_table.html"> 活跃度 </a></li>
						</ul></li>
				</ul>
			</div>
		</aside>
		<!-- END SIDEBAR -->


		<!-- BEGIN MAIN CONTENT -->
		<section id="main-content">
			<!-- BEGIN WRAPPER  -->
			<section class="wrapper">

				<!-- 流量概况表 开始 -->
				<div class="row">
					<div class="col-lg-12 col-sm-12">
						<section class="panel">
							<div class="panel-body">
								<!-- 为ECharts准备一个具备大小(宽高)的Dom -->
								<div>
									<span><h3>流量信息概况</h3></span>
								</div>
								<div id="trendtable" style="width: 90%;">
									<table id='pv_table' class="table table-bordered" margin=auto>
										<thead style='font-weight: bold'>
											<tr>
												<td>日期</td>
												<td>浏览次数(PV)</td>
												<td>独立访客(UV)</td>
												<td>IP</td>
												<td>新独立访客</td>
												<td>访问次数</td>
											</tr>
										</thead>
										<tbody>
											<tr>
												<td>1001</td>
												<td>4702</td>
												<td>3096</td>
												<td>2880</td>
												<td>2506</td>
												<td>3773</td>
											</tr>
											<tr>
												<td>1002</td>
												<td>7528</td>
												<td>4860</td>
												<td>4435</td>
												<td>4209</td>
												<td>5975</td>
											</tr>
											<tr>
												<td>1003</td>
												<td>7286</td>
												<td>4741</td>
												<td>4409</td>
												<td>4026</td>
												<td>5817</td>
											</tr>
										</tbody>
									</table>
								</div>
							</div>
						</section>
					</div>
				</div>
				<!-- 流量概况表 结束-->


				<!-- BEGIN ROW  最近7天日平均PV量-->
				<div class="row">
					<div class="col-lg-6 col-sm-6">
						<section class="panel">
							<div class="panel-body">
								<div id="main1" style="width: 100%; height: 400px;"></div>
								<script type="text/javascript">
									$(document)
											.ready(
													function() {
														var myChart = echarts
																.init(document
																		.getElementById('main1'));
														// 显示标题,图例和空的坐标轴
														myChart
																.setOption({
																	title : {
																		text : '最近7天日平均PV量',
																		subtext : '动态数据'
																	},
																	tooltip : {},
																	legend : {
																		data : [ '日平均PV量' ]
																	},
																	xAxis : {
																		data : []
																	},
																	yAxis : {},
																	series : [ {
																		name : '日平均PV量',
																		type : 'bar',
																		data : []
																	} ]
																});
														//loading 动画
														myChart.showLoading();
														// 异步加载数据
														$.get('http://localhost:8080/avgPvNum').done(function(data) {
															//填入数据
															myChart.setOption({
																xAxis : {
																							data : data.dates
																						},
																						series : [ {
																							// 根据名字对应到相应的系列
																							name : 'PV量',
																							data : data.data
																						} ]
																					});
																			//数据加载完成后再调用 hideLoading 方法隐藏加载动画
																			myChart.hideLoading();
																		});
													});
								</script>

							</div>
						</section>
					</div>
					<div class="col-lg-6 col-sm-6">
						<section class="panel">
							<div class="panel-body">

								<div id="main2" style="width: 600px; height: 400px;"
									align="center"></div>
								<script type="text/javascript">
									// 基于准备好的dom,初始化echarts实例
									var myChart = echarts.init(document
											.getElementById('main2'));

									myChart
											.setOption({
												series : [ {
													name : '访问来源',
													type : 'pie',
													radius : '55%',
													data : [ {
														value : 235,
														name : '视频广告'
													}, {
														value : 274,
														name : '联盟广告'
													}, {
														value : 310,
														name : '邮件营销'
													}, {
														value : 335,
														name : '直接访问'
													}, {
														value : 400,
														name : '搜索引擎'
													} ]
												} ],
												itemStyle : {
													normal : {
														// 阴影的大小
														shadowBlur : 200,
														// 阴影水平方向上的偏移
														shadowOffsetX : 0,
														// 阴影垂直方向上的偏移
														shadowOffsetY : 0,
														// 阴影颜色
														shadowColor : 'rgba(0, 0, 0, 0.5)'
													}
												}
											})
								</script>
							</div>
						</section>
					</div>

				</div>
				<!-- END ROW  -->

				<!-- 折线图 row 开始 -->
				<div class="row">
					<div class="col-lg-12 col-sm-12">
						<section class="panel">
							<div class="panel-body">
								<div id="main3" style="width: 100%; height: 500px;"></div>
								<script type="text/javascript">
									// 基于准备好的dom,初始化echarts实例
									var myChart3 = echarts.init(document
											.getElementById('main3'));
									option = {
										title : {
											text : '访客来源地区分布图',
											subtext : '模拟数据',
											x : 'center'
										},
										tooltip : {
											trigger : 'item'
										},
										legend : {
											orient : 'vertical',
											x : 'left',
											data : [ '访客UV' ]
										},
										dataRange : {
											min : 0,
											max : 2500,
											x : 'left',
											y : 'bottom',
											text : [ '高', '低' ], // 文本,默认为数值文本
											calculable : true
										},
										toolbox : {
											show : true,
											orient : 'vertical',
											x : 'right',
											y : 'center',
											feature : {
												mark : {
													show : true
												},
												dataView : {
													show : true,
													readOnly : false
												},
												restore : {
													show : true
												},
												saveAsImage : {
													show : true
												}
											}
										},
										roamController : {
											show : true,
											x : 'right',
											mapTypeControl : {
												'china' : true
											}
										},
										series : [
												{
													name : '访客UV',
													type : 'map',
													mapType : 'china',
													roam : false,
													itemStyle : {
														normal : {
															label : {
																show : true
															}
														},
														emphasis : {
															label : {
																show : true
															}
														}
													},
													data : [
															{
																name : '北京',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '天津',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '上海',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '重庆',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '河北',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '河南',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '云南',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '辽宁',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '黑龙江',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '湖南',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '安徽',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '山东',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '新疆',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '江苏',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '浙江',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '江西',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '湖北',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '广西',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '甘肃',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '山西',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '内蒙古',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '陕西',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '吉林',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '福建',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '贵州',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '广东',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '青海',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '西藏',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '四川',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '宁夏',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '海南',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '台湾',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '香港',
																value : Math
																		.round(Math
																				.random() * 1000)
															},
															{
																name : '澳门',
																value : Math
																		.round(Math
																				.random() * 1000)
															} ]
												},

										]
									};

									myChart3.setOption(option);
								</script>
							</div>
						</section>
					</div>
				</div>


				<!-- 折线图 row 结束 -->
				<!-- 动态加载数据示例 开始-->
				<div class="row">
					<div class="col-lg-12 col-sm-12">
						<section class="panel">
							<div class="panel-body">
								<div id="main4" style="width: 100%; height: 400px;"></div>
								<script type="text/javascript">
									// 基于准备好的dom,初始化echarts实例
									var myChart4 = echarts.init(document
											.getElementById('main4'));

									// 指定图表的配置项和数据
									option = {
										title : {
											text : '近一周访客数量变化趋势',
											subtext : '动态数据'
										},
										tooltip : {
											trigger : 'axis'
										},
										legend : {
											data : [ '独立访客', '新独立访客' ]
										},
										toolbox : {
											show : true,
											feature : {
												mark : {
													show : true
												},
												dataView : {
													show : true,
													readOnly : false
												},
												magicType : {
													show : true,
													type : [ 'line', 'bar' ]
												},
												restore : {
													show : true
												},
												saveAsImage : {
													show : true
												}
											}
										},
										calculable : true,
										xAxis : [ {
											type : 'category',
											boundaryGap : false,
											data : []
										} ],
										yAxis : [ {
											type : 'value',
											axisLabel : {
												formatter : '{value} 人'
											}
										} ],
										series : [ {
											name : '独立访客',
											type : 'line',
											data : [],
											markPoint : {
												data : [ {
													type : 'max',
													name : '最大值'
												}, {
													type : 'min',
													name : '最小值'
												} ]
											},
											markLine : {
												data : [ {
													type : 'average',
													name : '平均值'
												} ]
											}
										}, {
											name : '新独立访客',
											type : 'line',
											data : [],
											markPoint : {
												data : [ {
													type : 'max',
													name : '最大值'
												}, {
													type : 'min',
													name : '最小值'
												} ]
											},
											markLine : {
												data : [ {
													type : 'average',
													name : '平均值'
												} ]
											}
										} ]
									};

									// 使用刚指定的配置项和数据显示图表。
									myChart4.setOption(option);
									myChart4.showLoading();
									// 异步加载数据
									$.get('http://localhost:8080/flowNum')
											.done(function(data) {
												// 填入数据
												myChart4.setOption({
													xAxis : {
														data : data.dates
													},
													series : [ {
														name : '独立访客',
														data : data.uvs
													}, {
														name : '新独立访客',
														data : data.new_uvs
													} ]
												});
												myChart4.hideLoading();
											});
								</script>
							</div>
						</section>
					</div>
				</div>
				<!-- 动态加载数据示例 结束-->


				<!-- BEGIN ROW  -->
				<div class="row">
					<div class="col-lg-6">
						<div class="panel">
							<div class="panel-body">
								<footer class="project-category">
									<ul>
										<li class="active">
											<h5>Project 1</h5>
											<div id="work-progress6"></div>
										</li>
										<li>
											<h5>Project 2</h5>
											<div id="work-progress7"></div>
										</li>
										<li>
											<h5>Project 3</h5>
											<div id="work-progress8"></div>
										</li>
									</ul>
									<h1>Projects accomplished</h1>
								</footer>
								<!-- END  FOOTER -->
							</div>
						</div>
					</div>
					<div class="col-lg-6">
						<div class="panel">
							<div class="panel-body">
								<div class="bio-chart">
									<input class="knob" data-width="100" data-height="100"
										data-displayPrevious=true data-thickness=".2" value="78"
										data-fgColor="#f9a3a3" data-bgColor="#e8e8e8">
									<h4 class="red">Profit</h4>
								</div>
								<div class="bio-chart">
									<input class="knob" data-width="100" data-height="100"
										data-displayPrevious=true data-thickness=".2" value="63"
										data-fgColor="#fcce54" data-bgColor="#e8e8e8">
									<h4 class="yellow">Expansion</h4>
								</div>
							</div>
						</div>
					</div>
				</div>
				<!-- END ROW  -->
			</section>
			<!-- END WRAPPER  -->
		</section>
		<!-- END MAIN CONTENT -->
		<!-- BEGIN FOOTER -->
		<footer class="site-footer">
			<div class="text-center">
				2017 &copy; PINYOUGOU by <a href="" target="_blank">
					www.itcast.cn </a> <a href="http://www.itcast.cn" class="go-top"> <i
					class="fa fa-angle-up"> </i>
				</a>
			</div>
		</footer>
		<!-- END  FOOTER -->
	</section>
	<!-- END SECTION -->
	<!-- BEGIN JS -->

	<!-- BASIC JQUERY 1.8.3 LIB. JS -->
	<script src="js/bootstrap.min.js"></script>
	<!-- BOOTSTRAP JS -->
	<script src="js/jquery.dcjqaccordion.2.7.js"></script>
	<!-- ACCORDIN JS -->
	<script src="js/jquery.scrollTo.min.js"></script>
	<!-- SCROLLTO JS -->
	<script src="js/jquery.nicescroll.js"></script>
	<!-- NICESCROLL JS -->
	<script src="js/respond.min.js"></script>
	<!-- RESPOND JS -->
	<script src="js/jquery.sparkline.js"></script>
	<!-- SPARKLINE JS -->
	<script src="js/sparkline-chart.js"></script>
	<!-- SPARKLINE CHART JS -->
	<script src="js/common-scripts.js"></script>
	<!-- BASIC COMMON JS -->
	<script src="js/count.js"></script>
	<!-- COUNT JS -->
	<!--Morris-->
	<script src="assets/morris.js-0.4.3/morris.min.js"></script>
	<!-- MORRIS JS -->
	<script src="assets/morris.js-0.4.3/raphael-min.js"></script>
	<!-- MORRIS  JS -->
	<script src="js/chart.js"></script>
	<!-- CHART JS -->
	<!--Calendar-->
	<script src="js/calendar/clndr.js"></script>
	<!-- CALENDER JS -->
	<script src="js/calendar/evnt.calendar.init.js"></script>
	<!-- CALENDER EVENT JS -->
	<script src="js/calendar/moment-2.2.1.js"></script>
	<!-- CALENDER MOMENT JS -->
	<!-- <script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.2/underscore-min.js"></script> -->
	<!-- UNDERSCORE JS -->
	<script src="assets/jquery-knob/js/jquery.knob.js"></script>
	<!-- JQUERY KNOB JS -->
	<script>
		//knob
		$(".knob").knob();
	</script>

	<!-- END JS -->
</body>
</html>

3. Display of system function modules


Reference books:

"Hadoop big data technology principle and application"

 

 

Guess you like

Origin blog.csdn.net/weixin_63507910/article/details/128747019