大数据项目之_15_电信客服分析平台_05_数据展示+定时任务+项目总结
3.4、数据展示3.4.1、环境准备3.4.2、编写代码3.4.3、最终预览3.5、定时任务四、项目总结
3.4、数据展示
令人兴奋的时刻马上到了,接下来我们需要将某人按照不同维度查询出来的结果,展示到 web 页面上。
数据展示模块流程图:
3.4.1、环境准备
1) idea 新建 module 或项目:ct_web
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>com.china</groupId>
<artifactId>ct_web</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>ct_web Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.27</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.10</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.4</version>
</dependency>
</dependencies>
<build>
<finalName>ct_web</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- idea 专业版不需要此配置,idea 社区版需要配置
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<path>/</path>
<port>8080</port>
<uriEncoding>UTF-8</uriEncoding>
</configuration>
</plugin>
-->
</plugins>
</pluginManagement>
</build>
</project>
2) 创建包结构,根包:com.china
3) 类表
4) web目录结构,web部分的根目录:webapp
5) resources 目录下创建 spring 相关配置文件
dbconfig.properties 用于存放数据库连接配置
jdbc.user=root
jdbc.password=123456
jdbc.jdbcUrl=jdbc:mysql://hadoop102:3306/db_telecom?userUnicode=true&characterEncoding=UTF-8
jdbc.driverClass=com.mysql.jdbc.Driver
applicationContext.xml 用于 Spring 和 SpringMVC 配置
<?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/p"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 加载配置文件 -->
<context:property-placeholder location="classpath:dbconfig.properties"/>
<!-- 配置连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"/>
<property name="driverClass" value="${jdbc.driverClass}"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg name="dataSource" value="#{dataSource}"></constructor-arg>
</bean>
<bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg name="dataSource" value="#{dataSource}"></constructor-arg>
</bean>
<!-- 配置包扫描 -->
<context:component-scan base-package="com.china.controller"></context:component-scan>
<context:component-scan base-package="com.china.dao"></context:component-scan>
<!-- 配置视图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 配置静态资源映射,也可以配置在 web.xml 中 -->
<!--<mvc:annotation-driven />-->
<!--<mvc:default-servlet-handler />-->
<!--<mvc:resources location="/images/" mapping="/images/**"/>-->
<!--<mvc:resources location="/js/" mapping="/js/**"/>-->
<!--<mvc:resources location="/css/" mapping="/css/**"/>-->
</beans>
6) WEB-INF 目录下创建 web 相关配置
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>ct_wed</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 配置springmvc的前端控制器 -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<!-- /表示拦截所有请求,但不拦截jsp,/*表示拦截所有请求 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 配置解决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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 配置静态资源映射,也可以配置在 applicationContext.xml 中 -->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
</web-app>
7) 拷贝 js 框架到 js 目录下
js 框架名称:
echarts.min.js
jquery-3.2.0.min.js
3.4.2、编写代码
思路:
a) 首先测试数据通顺以及完整性,写一个查询联系人的测试用例。
b) 测试通过后,通过输入手机号码以及时间参数,查询指定维度的数据,并以图表展示。
代码:
1) 新建类:CallLog
package com.china.bean;
/**
* 封装从Mysql中取出来的数据
*
* @author chenmingjun
* 2019-03-21 18:38
*/
public class CallLog {
private String id_contact_date;
private int id_dimension_contact;
private int id_dimension_date;
private int call_sum;
private int call_duration_sum;
private String telephone;
private String name;
private int year;
private int month;
private int day;
public String getId_contact_date() {
return id_contact_date;
}
public void setId_contact_date(String id_contact_date) {
this.id_contact_date = id_contact_date;
}
public int getId_dimension_contact() {
return id_dimension_contact;
}
public void setId_dimension_contact(int id_dimension_contact) {
this.id_dimension_contact = id_dimension_contact;
}
public int getId_dimension_date() {
return id_dimension_date;
}
public void setId_dimension_date(int id_dimension_date) {
this.id_dimension_date = id_dimension_date;
}
public int getCall_sum() {
return call_sum;
}
public void setCall_sum(int call_sum) {
this.call_sum = call_sum;
}
public int getCall_duration_sum() {
return call_duration_sum;
}
public void setCall_duration_sum(int call_duration_sum) {
this.call_duration_sum = call_duration_sum;
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
@Override
public String toString() {
return "CallLog{" +
"id_contact_date='" + id_contact_date + '\'' +
", id_dimension_contact=" + id_dimension_contact +
", id_dimension_date=" + id_dimension_date +
", call_sum=" + call_sum +
", call_duration_sum=" + call_duration_sum +
", telephone='" + telephone + '\'' +
", name='" + name + '\'' +
", year=" + year +
", month=" + month +
", day=" + day +
'}';
}
}
2) 新建类:Contact
package com.china.bean;
/**
* @author chenmingjun
* 2019-03-22 0:17
*/
public class Contact {
private int id;
private String telephone;
private String name;
public Contact() {
}
public Contact(int id, String telephone, String name) {
this.id = id;
this.telephone = telephone;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Contact{" +
"id=" + id +
", telephone='" + telephone + '\'' +
", name='" + name + '\'' +
'}';
}
}
3) 新建类:QueryInfo
package com.china.bean;
/**
* 封装用于用户传递过来的数据
*
* @author chenmingjun
* 2019-03-21 18:43
*/
public class QueryInfo {
private String telephone;
private String year;
private String month;
private String day;
public QueryInfo() {
}
public QueryInfo(String telephone, String year, String month, String day) {
this.telephone = telephone;
this.year = year;
this.month = month;
this.day = day;
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public String getYear() {
return year;
}
public void setYear(String year) {
this.year = year;
}
public String getMonth() {
return month;
}
public void setMonth(String month) {
this.month = month;
}
public String getDay() {
return day;
}
public void setDay(String day) {
this.day = day;
}
@Override
public String toString() {
return "QueryInfo{" +
"telephone='" + telephone + '\'' +
", year='" + year + '\'' +
", month='" + month + '\'' +
", day='" + day + '\'' +
'}';
}
}
4) 新建类:CallLogDAO
package com.china.dao;
import com.china.bean.CallLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;
import java.util.HashMap;
import java.util.List;
/**
* @author chenmingjun
* 2019-03-21 18:48
*/
@Repository
public class CallLogDao {
// 自动装载
@Autowired
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
public List<CallLog> getCallLogList(HashMap<String, String> paramsMap) {
// 按照年统计:统计某个用户,1年12个月的所有的数据(不精确到天)
String sql = "SELECT `name`, `telephone`, `call_sum`, `call_duration_sum`, `year`, `month`, `day` FROM `tb_dimension_date` t4 INNER JOIN ( SELECT `id_dimension_date`, `call_sum`, `call_duration_sum`, `telephone`, `name` FROM `tb_call` t2 INNER JOIN ( SELECT `id`, `telephone`, `name` FROM `tb_dimension_contacts` WHERE `telephone` = :telephone ) t1 ON t2.id_dimension_contact = t1.id ) t3 ON t4.id = t3.id_dimension_date WHERE (`year` = :year AND `month` != :month AND `day` = :day) ORDER BY `year`, `month`;";
BeanPropertyRowMapper<CallLog> beanPropertyRowMapper = new BeanPropertyRowMapper<>(CallLog.class);
List<CallLog> list = namedParameterJdbcTemplate.query(sql, paramsMap, beanPropertyRowMapper);
return list;
}
}
5) 新建类:ContactDAO
package com.china.dao;
import com.china.bean.Contact;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;
import java.util.HashMap;
import java.util.List;
/**
* @author chenmingjun
* 2019-03-22 0:19
*/
@Repository
public class ContactDAO {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
public List<Contact> getContacts() {
String sql = "SELECT `id`, `telephone`, `name` FROM `tb_dimension_contacts`;";
BeanPropertyRowMapper<Contact> contactBeanPropertyRowMapper = new BeanPropertyRowMapper<>(Contact.class);
List<Contact> contactList = jdbcTemplate.query(sql, contactBeanPropertyRowMapper);
return contactList;
}
public List<Contact> getContactWithId(HashMap<String, String> hashMap) {
String sql = "SELECT `id`, `telephone`, `name` FROM `tb_dimension_contacts` WHERE `id` = :id;";
BeanPropertyRowMapper<Contact> contactBeanPropertyRowMapper = new BeanPropertyRowMapper<>(Contact.class);
List<Contact> contactList = namedParameterJdbcTemplate.query(sql, hashMap, contactBeanPropertyRowMapper);
return contactList;
}
}
6) 新建类:CallLogController
package com.china.controller;
import com.china.bean.CallLog;
import com.china.bean.Contact;
import com.china.bean.QueryInfo;
import com.china.dao.CallLogDao;
import com.china.dao.ContactDAO;
import com.google.gson.Gson;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import java.util.HashMap;
import java.util.List;
/**
* @author chenmingjun
* 2019-03-21 20:53
*/
@Controller
public class CallLogController {
@RequestMapping("/queryContact")
public ModelAndView query(Contact contact) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
ContactDAO contactDAO = applicationContext.getBean(ContactDAO.class);
HashMap<String, String> paramMap = new HashMap<>();
paramMap.put("id", String.valueOf(contact.getId()));
List<Contact> contactList = contactDAO.getContactWithId(paramMap);
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("jsp/queryContact");
modelAndView.addObject("contacts", contactList);
return modelAndView;
}
@RequestMapping("/queryContactList")
public ModelAndView querylist() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
ContactDAO contactDAO = applicationContext.getBean(ContactDAO.class);
List<Contact> contactList = contactDAO.getContacts();
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("jsp/queryContact");
modelAndView.addObject("contacts", contactList);
return modelAndView;
}
@RequestMapping("/queryCallLogList")
public ModelAndView queryCallLog(QueryInfo queryInfo) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
CallLogDao callLogDao = applicationContext.getBean(CallLogDao.class);
HashMap<String, String> paramMap = new HashMap<>();
paramMap.put("telephone", String.valueOf(queryInfo.getTelephone()));
paramMap.put("year", String.valueOf(queryInfo.getYear()));
paramMap.put("day", String.valueOf(queryInfo.getDay()));
List<CallLog> callLogList = callLogDao.getCallLogList(paramMap);
Gson gson = new Gson();
String resultList = gson.toJson(callLogList);
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("jsp/callLogList");
modelAndView.addObject("callLogList", resultList);
return modelAndView;
}
@RequestMapping("/queryCallLogList2")
public String queryCallLog2(Model model, QueryInfo queryInfo) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
CallLogDao callLogDao = applicationContext.getBean(CallLogDao.class);
// 封装传过来的数据
HashMap<String, String> paramMap = new HashMap<>();
paramMap.put("telephone", queryInfo.getTelephone());
paramMap.put("year", String.valueOf(queryInfo.getYear()));
paramMap.put("month", String.valueOf(queryInfo.getMonth()));
paramMap.put("day", String.valueOf(queryInfo.getDay()));
List<CallLog> callLogList = callLogDao.getCallLogList(paramMap);
StringBuilder dateString = new StringBuilder();
StringBuilder callSumString = new StringBuilder();
StringBuilder callDurationSumString = new StringBuilder();
// 1月,2月,3月,4月,5月,6月,7月,8月,9月,10月,11月,12月,
for (int i = 0; i < callLogList.size(); i++) {
CallLog callLog = callLogList.get(i);
if (Integer.valueOf(callLog.getMonth()) > 0) {
dateString.append(callLog.getMonth()).append("月").append(",");
callSumString.append(callLog.getCall_sum()).append(",");
callDurationSumString.append(callLog.getCall_duration_sum() / 60f).append(",");
}
}
dateString.deleteCharAt(dateString.length() - 1);
callSumString.deleteCharAt(callSumString.length() - 1);
callDurationSumString.deleteCharAt(callDurationSumString.length() - 1);
// 封装返回去的数据
model.addAttribute("telephone", callLogList.get(0).getTelephone());
model.addAttribute("name", callLogList.get(0).getName());
model.addAttribute("date", dateString.toString());
model.addAttribute("count", callSumString.toString());
model.addAttribute("duration", callDurationSumString.toString());
return "jsp/callLogListEchart";
}
}
7) 新建类:Contants
暂时没用上,也可以用上,主要用于存放一些常量。
8) 新建:index.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%
String path = request.getContextPath();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Show Time</title>
</head>
<body>
<form action="/queryContact">
id:<input type="text" name="id"/>
telephone:<input type="text" name="telephone"/>
<input type="submit" value="查询当前联系人"/>
</form>
<br/>
<form action="/queryContactList">
<input type="submit" value="查询所有联系人"/>
</form>
<br/>
<%--<form action='<c:url value="/queryCallLogList2"/>' method="post">--%>
<form action=/queryCallLogList2 method="post">
telephone:<input type="text" name="telephone"/>
year:<input type="text" name="year"/>
month:<input type="text" name="month"/>
day:<input type="text" name="day"/>
<input type="submit" value="查询该联系人的通话记录"/>
</form>
</body>
</html>
9) 新建:queryContact.jsp
<%--
Created by IntelliJ IDEA.
User: bruce
Date: 2019/3/22
Time: 0:25
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored = "false" %>
<html>
<head>
<title>查询联系人</title>
</head>
<body>
查询结果:<br/>
<h3>${requestScope.contacts}</h3>
</body>
</html>
10) 新建:callLogList.jsp
<%--
Created by IntelliJ IDEA.
User: bruce
Date: 2019/3/22
Time: 0:28
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored = "false" %>
<html>
<head>
<title>显示通话记录</title>
</head>
<body>
查询结果:<br/>
<h3>${requestScope.callLogList}</h3>
</body>
</html>
11) 新建:callLogListEchart.jsp
<%--
Created by IntelliJ IDEA.
User: bruce
Date: 2019/3/21
Time: 21:09
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<meta http-equiv="Content-Type" , content="text/html" charset="UTF-8">
<title>显示通话记录</title>
<script type="text/javascript" src="../js/echarts.min.js"></script>
<%--<script type="text/javascript" src="${pageContext.request.contextPath}/js/echarts.min.js"></script>--%>
<%--<script type="text/javascript" src="${pageContext.request.contextPath}/jquery-3.2.0.min.js"></script>--%>
<%--<script type="text/javascript" src="http://echarts.baidu.com/gallery/vendors/echarts/echarts-all-3.js"></script>--%>
</head>
<body style="height: 100%; margin: 0; background-color:#2B2B2B ">
<style type="text/css">
h3 {
font-size: 14px;
color: #ffffff;
display: inline;
}
</style>
<h4 style="color: #ffffff;text-align:center">通话月单查询:${requestScope.name}</h4>
<%--<h3 style="margin-left: 70%">通话次数</h3>--%>
<%--<h3 style="margin-left: 20%">通话时长</h3>--%>
<div id="container1" style="height: 80%; width: 50%; float:left"></div>
<div id="container2" style="height: 80%; width: 50%; float:right"></div>
<script type="text/javascript">
var telephone = "${requestScope.telephone}"
var name = "${requestScope.name}"
var date = "${requestScope.date}"//1月,2月,3月,xxxxx
var count = "${requestScope.count}"
var duration = "${requestScope.duration}"
var pieData = converterFun(duration.split(","), date.split(","))
callog1();
callog2();
function converterFun(duration, date) {
var array = [];
for (var i = 0; i < duration.length; i++) {
var map = {};
map['value'] = parseFloat(duration[i]);
map['name'] = date[i];
array.push(map);
}
return array;
}
function callog1() {
var dom = document.getElementById("container1");
var myChart = echarts.init(dom);
myChart.showLoading();
var option = {
title: {
text: '通话次数',
textStyle: {
//文字颜色
color: '#ffffff',
//字体风格,'normal','italic','oblique'
fontStyle: 'normal',
//字体粗细 'normal','bold','bolder','lighter',100 | 200 | 300 | 400...
fontWeight: 'bold',
//字体系列
fontFamily: 'sans-serif',
//字体大小
fontSize: 13
},
itemGap: 12,
},
grid: {
x: 80,
y: 60,
x2: 80,
y2: 60,
backgroundColor: 'rgba(0,0,0,0)',
borderWidth: 1,
borderColor: '#ffffff'
},
tooltip: {
trigger: 'axis'
},
legend: {
borderColor: '#ffffff',
itemGap: 10,
data: ['通话次数'],
textStyle: {
color: '#ffffff'// 图例文字颜色
}
},
toolbox: {
show: false,
feature: {
dataZoom: {
yAxisIndex: 'none'
},
dataView: {readOnly: false},
magicType: {type: ['line', 'bar']},
restore: {},
saveAsImage: {}
}
},
xAxis: {
data: date.split(","),
axisLine: {
lineStyle: {
color: '#ffffff',
width: 2
}
}
},
yAxis: {
axisLine: {
lineStyle: {
color: '#ffffff',
width: 2
}
}
},
series: [
{
type: 'line',
data: count.split(","),
itemStyle: {
normal: {
color: '#ffca29',
lineStyle: {
color: '#ffd80d',
width: 2
}
}
},
markPoint: {
data: [
{type: 'max', name: '最大值'},
{type: 'min', name: '最小值'}
]
},
markLine: {
data: [
{type: 'average', name: '平均值'}
]
}
}
]
};
if (option && typeof option === "object") {
myChart.setOption(option, true);
}
myChart.hideLoading()
}
function callog2() {
var dom = document.getElementById("container2");
var myChart = echarts.init(dom);
myChart.showLoading();
var option = {
title: {
text: '通话时长',
textStyle: {
//文字颜色
color: '#ffffff',
//字体风格,'normal','italic','oblique'
fontStyle: 'normal',
//字体粗细 'normal','bold','bolder','lighter',100 | 200 | 300 | 400...
fontWeight: 'bold',
//字体系列
fontFamily: 'sans-serif',
//字体大小
fontSize: 13
},
itemGap: 12,
},
tooltip: {
trigger: 'item',
formatter: "{a} <br/>{b} : {c} ({d}%)"
},
visualMap: {
show: false,
min: Math.min.apply(null, duration.split(",")),
max: Math.max.apply(null, duration.split(",")),
inRange: {
colorLightness: [0, 0.5]
}
},
series: [
{
name: '通话时长',
type: 'pie',
radius: '55%',
center: ['50%', '50%'],
data: pieData.sort(function (a, b) {
return a.value - b.value;
}),
roseType: 'radius',
label: {
normal: {
textStyle: {
color: 'rgba(255, 255, 255, 0.3)'
}
}
},
labelLine: {
normal: {
lineStyle: {
color: 'rgba(255, 255, 255, 0.3)'
},
smooth: 0.2,
length: 10,
length2: 20
}
},
itemStyle: {
normal: {
color: '#01c1c2',
shadowBlur: 200,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
},
animationType: 'scale',
animationEasing: 'elasticOut',
animationDelay: function (idx) {
return Math.random() * 200;
}
}
]
};
if (option && typeof option === "object") {
myChart.setOption(option, true);
}
myChart.hideLoading()
}
</script>
</body>
</html>
3.4.3、最终预览
前端界面:
查询人通话时长与通话次数统计大概如下所示,统一展示:
3.5、定时任务
新的数据每天都会产生,所以我们每天都需要更新离线的分析结果,所以此时我们可以用各种各样的定时任务调度工具来完成此操作。此例我们使用 crontab 来执行该操作。
1) 编写任务脚本:analysis.sh
#!/bin/bash
/opt/module/hadoop-2.7.2/bin/yarn jar ./ct_analysis-1.0-SNAPSHOT.jar com.china.analysis.runner.CountDurationRunner -libjars /opt/module/flume/job/ct/lib/mysql-connector-java-5.1.27-bin.jar
2) 制定 crontab 任务
# .------------------------------------------minute(0~59)
# | .----------------------------------------hours(0~23)
# | | .--------------------------------------day of month(1~31)
# | | | .------------------------------------month(1~12)
# | | | | .----------------------------------day of week(0~6)
# | | | | | .--------------------------------command
# | | | | | |
# | | | | | |
0 0 * * * /opt/module/flume/job/ct/analysis.sh
3) 考虑数据处理手段是否安全
a、定时任务统计结果是否会重复
b、定时任务处理的数据是否全面
四、项目总结
重新总结梳理整个项目流程和方法论。
1、实现月查询(某个月每一天的数据展示:重新编写 sql 语句即可实现)。
2、用户亲密度展示。
3、考虑 Hive 实现。
4、用户按照时间区间,查找所有的通话数据。