可视化

数据分析-可视化

2023-02-07  本文已影响0人  CoderInsight

1.使用简单的 html+Servlet+DBUtils 实现可视化

jsp+Servlet可视化结果(主站最受欢迎的TopN课程).png

(0).项目准备

1).新建 "maven-archetype-webapp" 的Maven项目

2).添加 pom.xml 依赖

<dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>jsp-api</artifactId>
    <version>2.0</version>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.38</version>
</dependency>

<dependency>
    <groupId>net.sf.json-lib</groupId>
    <artifactId>json-lib</artifactId>
    <version>2.4</version>
    <classifier>jdk15</classifier>
</dependency>

3),项目依赖 “echarts.min.js” 和 jquery.js

(1).Domain(实体类)

package top.wangyq.domain;

/**
 * TopN 实体类
 */
public class VideoAccessTopN {
    // 这里定义的字段属性值要和图中表示数据的部分是一致的

    // 属性名
    private String name;
    // 属性值
    private  long value;


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public long getValue() {
        return value;
    }

    public void setValue(long value) {
        this.value = value;
    }
}

(2).DBUtils(数据库连接工具类)

package top.wangyq.utiles;

import java.sql.*;

/**
 * 操作MySQL的工具类
 */
public class DBUtils {
    private  static final String USERNAME = "root";
    private  static final String PASSWORD = "111111";
    private  static final String DRIVERCLASS = "com.mysql.jdbc.Driver";
    private  static final String URL = "jdbc:mysql://localhost:3306/imooclog";

    /**
     * 获取数据库的连接
     * @return
     */
    public static Connection getConnnection(){

        Connection connection = null;
        try {
            // 获得字符串参数中指定的类,并初始化该类;将Driver类获取出来
            Class.forName(DRIVERCLASS);
            connection = DriverManager.getConnection(URL,USERNAME,PASSWORD);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return connection;
    }

    /**
     * 释放数据库的连接资源
     */
    public static void release(Connection connection, PreparedStatement pstmt, ResultSet rs){
        if (rs != null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (pstmt != null){
            try {
                pstmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (pstmt != null){
            try {
                pstmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * 测试数据库连接是否获取成功
     */
    public static void main(String[] args) {
        System.out.println(getConnnection());
    }

}

(3).Dao层(底层操作数据库)

package top.wangyq.dao;

import top.wangyq.domain.VideoAccessTopN;
import top.wangyq.utiles.DBUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 完整的讲是应该采用面向接口的方式进行编程
 * 但是,我们这里直接是面向实现类进行编程的
 */
public class VideoAccessTopNDao {
    // 课程和编号的映射一般是直接写在关系型数据库中,然后使用一个接口去调用
    // 将课程编号与课程名称封装在map集合中
    static Map<String,String> courses = new HashMap<>();
    // 这里是在map集合中进行赋值,直接写死的,但是如果从数据中取值无非是将取出来的值遍历依次添加到Map中
    static {
        courses.put("2402", "机器学习");
        courses.put("1309", "redis");
        courses.put("3078", "神经网络");
        courses.put("1336", "Docker");
        courses.put("3369", "Java");
    }

    /**
     * 定义查询课程编号与课程名称的对应关系的方法
     */
    public String getCourseName(String courseId){
        // 直接使用get方法将map中的元素进行获取即可
        return courses.get(courseId);
    }

    /**
     * 根据day查询当天最受欢迎的Top5课程
     * 查询的结果保存在list集合中,那么在前端将数据获取出来的时候需要遍历list集合
     */
    public List<VideoAccessTopN> query(String day){

        List<VideoAccessTopN> list = new ArrayList<>();

        // 设置数据库的连接信息
        Connection connection = null; // 连接对象
        PreparedStatement pstmt = null; // 预编译对象
        ResultSet rs = null; // 结果对象

        try {
            // 初始化连接对象
            connection = DBUtils.getConnnection();
            // 编写sql语句的字符串
            // 这里将条件都直接写死了,是不对的,应该将其写使用传递的方式实现(待测试更改:使用开头,再加$)
            String sql = "select cms_id, times from day_video_access_topn_stat3 where day=? order by times desc  limit 5";
            // 初始化预编译对象
            pstmt = connection.prepareStatement(sql);
            // 给占位符进行赋值
            pstmt.setString(1,day);
            // 执行查询结果返回给ResultSet对象
            rs = pstmt.executeQuery();
            // 定义 VideoAccessTopN 实体类对象
            VideoAccessTopN domain = null;
            // 依次判断集合中是否有元素
            while (rs.next()){
                // 有则初始化对象
                domain = new VideoAccessTopN();
                /**
                在页面中应该显示的是课程名称,而我们在数据库中存储的是课程编号,需要再转换
                 *
                 * 如何根据课程编号去获取课程名称呢?
                 * 编号和名称是有一个对应关系的,一般情况下可以将其对应关系写在关系型数据库中
                 * 但是此时我们直接写在了程序的开头的静态代码块
                 */
                // 1.由于数据库的课程编号的类型是Long类型的,所以需要通过getLong("字段名")来将字段中的值取出来
                // 2.然后调用课程编号与客户才能名称的映射方法(getCourseName)
                domain.setName(getCourseName(rs.getLong("cms_id")+""));
                domain.setValue(rs.getLong("times"));
                // 将保存好数据的domain对象封装在list集合中
                list.add(domain);
            }

        }catch (Exception e){
         e.printStackTrace();
        }finally {
            // 关闭资源
            DBUtils.release(connection, pstmt, rs);
        }
        // 操作结束后将结果集合返回
        return list;
    }

  public static void main(String[] args) {

      VideoAccessTopNDao dao = new VideoAccessTopNDao();

      List<VideoAccessTopN> list = dao.query("20191110");

      for (VideoAccessTopN res : list) {
          System.out.println(res.getName() + "\t" + res.getValue());
      }
  }

}

(4).Servlet(前端请求处理层)

将从数据库中查询出来的数据转成json类型的数据,再将结果传递到前端

package top.wangyq.servlet;

import top.wangyq.dao.VideoAccessTopNDao;
import top.wangyq.domain.VideoAccessTopN;
import net.sf.json.JSONArray;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

/**
 * 最受欢迎的TopN课程
 *
 * 一般完成的项目时有三层的
 * Web ==> Service ==> Dao
 * 我们此时只有查询,并没有数据的添加等操作,所以我们只有两层
 * Web ==> Dao
 */
public class VideoAccessTopNServlet extends HttpServlet {
    // 定义操作数据库的实体类
    private VideoAccessTopNDao dao;

    @Override
    public void init() throws ServletException {
        // 初始化操作数据库的类
        dao = new VideoAccessTopNDao();
    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 定义变量将前端请求中拼接的字符串的值获取出来
        String day = req.getParameter("day");


        // 将获取的月份传入数据库操作类中的query方法,其函数的返回值是一个 VideoAccessTopN(实体类)的集合
        List<VideoAccessTopN> results =  dao.query(day);
        // 定义一个JSONArray对象,将list集合转换成json对象
        JSONArray json = JSONArray.fromObject(results);

        // 设置response的响应类型为html
        resp.setContentType("text/html;charset=utf-8");

        // 获取一个写对象,返回值是PrintWriter
        PrintWriter writer = resp.getWriter();
        // 将json数据响应给前端页面
        writer.println(json);
        // 刷新提交
        writer.flush();
        // 关闭写对象
        writer.close();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req,resp);
    }
}

(5).将servlet注册到web.xml中

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <!-- 在写完servlet之后需要在web.xml中进行注册-->
  <servlet>
    <servlet-name>stat</servlet-name>
    <servlet-class>top.wangyq.servlet.VideoAccessTopNServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>stat</servlet-name>
    <url-pattern>/stat</url-pattern>
  </servlet-mapping>
</web-app>

(6).topn.html(前端页面)

主要是编写对应js代码,使用Ajax技术将后端获取的数据进行拼接

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Echarts Demo </title>

    <!-- 引入 ECharts 文件 -->
    <script src="js/echarts.min.js"></script>
    <script src="js/jquery.js"></script>
</head>

<body>

    <!-- 为 ECharts 准备一个具备大小(宽高)的 DOM -->
    <div id="main" style="width: 600px;height:400px;"></div>
    <!-- 编写Echarts的脚本代码-->
    <script type="text/javascript">

        // 基于准备好的dom,初始化echarts实例
        var myChart = echarts.init(document.getElementById('main'));

        // 指定图表的配置项和数据
        var option = {
            title : {
                text: '主站最受欢迎的TopN课程',
                x:'center'
            },
            tooltip : {
                trigger: 'item',
                formatter: "{a} <br/>{b} : {c} ({d}%)"
            },
            legend: {
                orient: 'vertical',
                left: 'left',
                data: []  // 这里是设置图例的名称
            },
             series : [
            {
                name: '访问次数',
                type: 'pie',
                radius : '55%',
                center: ['50%', '60%'],
                data:(function(){
                    var courses = [];
                    $.ajax({
                        type:"GET", // 默认是get方式,也可指定为post方式,此时后端处理请求的时候是使用的get方式,所以在这里写就是get方式
                        url:"stat?day=20191110", // 这里是Servlet请求,请求的结果传递到回调函数中
                        dataType:'json', // 指定数据的响应类型是json
                        async:false, // 设置是否是异步提交数据为false(也就是同步提交)
                        // 在响应状态为success的时候执行回调函数
                        success:function(result) {
                            for(var i=0;i<result.length; i++){
                                // 将数据封装到数组对象中
                                courses.push({"name":result[i].name, "value": result[i].value});
                            }
                        }
                    })
                    // 最后将塞了数据的数组对象进行返回
                    return courses;
                })(),
                    itemStyle: {
                        emphasis: {
                            shadowBlur: 10,
                            shadowOffsetX: 0,
                            shadowColor: 'rgba(0, 0, 0, 0.5)'
                        }
                    }
                }
            ]
        };

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

猜你喜欢

热点阅读