JavaWeb視覺化:Web+Echarts案例:豆瓣日劇豆列電影資訊視覺化(柱狀圖、餅狀圖、折線圖)
柱狀圖案例
柱狀圖用來比較多專案的數值情況,從構成上來說,柱狀圖以座標軸上的長方形元素作為變數,以此來達到展現並比較資料情況的目的。柱狀圖形式多種多樣,以適應不同場合資料展示,常用的有如下形式:
常用配置項引數:
- title:標題元件,包含主標題和副標題。
- title.show boolean[ default: true ],是否顯示標題元件
- title.text string[ default: '' ],主標題文字,支援使用 \n 換行
- title.target string[ default: 'blank' ],指定視窗開啟主標題超連結
- title.target string[ default: 'blank' ]
- title.textStyle.color Color[ default: '#333' ],主標題文字的顏色
- title.textStyle.fontStyle string[ default: 'normal' ],主標題文字字型的風格,可選:'normal','italic','oblique'
- title.textStyle.verticalAlign string文字垂直對齊方式,預設自動。可選:'top','middle','bottom
- title.subtext string[ default: '' ]
- legend:圖例元件
- grid:直角座標系內繪圖網格,單個 grid 內最多可以放置上下兩個 X 軸,左右兩個 Y 軸。可以在網格上繪製折線圖,柱狀圖,散點圖(氣泡圖)。
- xAxis:直角座標系 grid 中的 x 軸,一般情況下單個 grid 元件最多隻能放上下兩個 x 軸,多於兩個 x 軸需要通過配置 offset 屬性防止同個位置多個 x 軸的重疊
- yAxis:直角座標系 grid 中的 y 軸,一般情況下單個 grid 元件最多隻能放左右兩個 y 軸,多於兩個 y 軸需要通過配置 offset 屬性防止同個位置多個 Y 軸的重疊
- color
需求:將WebMagic爬蟲獲取到的豆瓣電影的評分以柱狀圖圖的形式展現出來。
1. 使用之前使用WebMagic爬取的豆瓣豆列電影資料,資料庫movies表如下:
2. 新建Java Web專案,紅框處需要勾選
3. 將下載的jstl.jar、standard.jar和mysql-connector-java-5.1.6-bin.jar拷貝至lib目錄下;在WebContent下新建res目錄,在res目錄下新建js目錄,然後將echarts.min.js、jquery-3.3.1.min.js拷貝到js目錄下。整體目錄結構如下:
4. 編寫Movie類,封裝電影資訊
package com.liudm.entity;
public class Movie {
//電影資訊
private int m_id;
private String m_title;
private String m_urls;
private float m_ratings;
//電影詳細資訊
private String m_dir;
private String m_actor;
private String m_type;
private String m_time;
public Movie() {
super();
}
public Movie(String m_title, String m_urls, float m_ratings,
String m_dir, String m_actor, String m_type, String m_time) {
super();
this.m_title = m_title;
this.m_urls = m_urls;
this.m_ratings = m_ratings;
this.m_dir = m_dir;
this.m_actor = m_actor;
this.m_type = m_type;
this.m_time = m_time;
}
public Movie(int m_id, String m_title, String m_urls, float m_ratings,
String m_dir, String m_actor, String m_type, String m_time) {
super();
this.m_id = m_id;
this.m_title = m_title;
this.m_urls = m_urls;
this.m_ratings = m_ratings;
this.m_dir = m_dir;
this.m_actor = m_actor;
this.m_type = m_type;
this.m_time = m_time;
}
public int getM_id() {
return m_id;
}
public void setM_id(int m_id) {
this.m_id = m_id;
}
public String getM_title() {
return m_title;
}
public void setM_title(String m_title) {
this.m_title = m_title;
}
public String getM_urls() {
return m_urls;
}
public void setM_urls(String m_urls) {
this.m_urls = m_urls;
}
public float getM_ratings() {
return m_ratings;
}
public void setM_ratings(float m_ratings) {
this.m_ratings = m_ratings;
}
public String getM_dir() {
return m_dir;
}
public void setM_dir(String m_dir) {
this.m_dir = m_dir;
}
public String getM_actor() {
return m_actor;
}
public void setM_actor(String m_actor) {
this.m_actor = m_actor;
}
public String getM_type() {
return m_type;
}
public void setM_type(String m_type) {
this.m_type = m_type;
}
public String getM_time() {
return m_time;
}
public void setM_time(String m_time) {
this.m_time = m_time;
}
@Override
public String toString() {
return "Movie [m_id=" + m_id + ", m_title=" + m_title + ", m_urls="
+ m_urls + ", m_ratings=" + m_ratings + ", m_dir=" + m_dir
+ ", m_actor=" + m_actor + ", m_type=" + m_type + ", m_time="
+ m_time + "]";
}
}
5. 編寫mysql.properties屬性檔案,儲存連線資料庫的相關配置資訊:其中資料庫名為movies
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/movies
username=root
pwd=nothing
6. 編寫MySqlUtil.java,連線資料庫的相關內容
package com.liudm.utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
public class MySqlUtil {
// 讀取屬性檔案,獲得連線
static Connection con = null;
static Properties ps = new Properties();
static {
// 讀取屬性檔案
InputStream in = MySqlUtil.class.getClassLoader().getResourceAsStream("mysql.properties");
try {
ps.load(in);
String driver = ps.getProperty("driver");
String url = ps.getProperty("url");
String username = ps.getProperty("username");
String pwd = ps.getProperty("pwd");
System.out.println(driver + url + username + pwd);
Class.forName(driver);
con = DriverManager.getConnection(url, username, pwd);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static Connection getConnection() {
return con;
}
// 關閉資源
public static void closeRes(ResultSet rs, PreparedStatement ps, Connection con) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (con != null) {
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
7. 編寫介面MovieDao.java,編寫抽象方法,實現電影資訊的查詢
package com.liudm.dao;
import java.util.List;
import com.liudm.entity.Movie;
public interface MovieDao {
public List<Movie> queryAllMovies();
}
8. 編寫MovieDaoImpl.java,重寫queryAllMovies方法
package com.liudm.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.liudm.entity.Movie;
import com.liudm.utils.MySqlUtil;
public class MovieDaoImpl implements MovieDao{
Connection con = null;
Movie movie = null;
PreparedStatement pre = null;
ResultSet rs = null;
@Override
public List<Movie> queryAllMovies() {
con = MySqlUtil.getConnection();
List list = new ArrayList();
String sql="select * from movies limit 30";
try {
pre=con.prepareStatement(sql);
rs= pre.executeQuery();
while(rs.next()){
int mid=rs.getInt("m_id");
String mtitle=rs.getString("m_title");
String murls=rs.getString("m_urls");
float mratings=rs.getFloat("m_ratings");
String mdir=rs.getString("m_dir");
String mactor=rs.getString("m_actor");
String mtype=rs.getString("m_type");
String mtime=rs.getString("m_time");
movie = new Movie(mid, mtitle, murls, mratings, mdir, mactor, mtype, mtime);
list.add(movie);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//MySQLUtil.closeRes(rs, pre, con);
}
return list;
}
}
9. 新建Servlet包。每開發一個Servlet,都要在web.xml中配置Servlet才能夠使用,這實在是很頭疼的事情,所以Servlet3.0之後提供了註解(annotation),使得不再需要在web.xml檔案中進行Servlet的部署描述,簡化開發流程。
編寫QueryMovieServlet.java,在doGet方法中獲取dao層資料並將其儲存在request中:
package com.liudm.servlet;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.liudm.dao.MovieDao;
import com.liudm.dao.MovieDaoImpl;
import com.liudm.entity.Movie;
/**
* Servlet implementation class QueryMovieServlet
*/
@WebServlet("/QueryMovieServlet")
public class QueryMovieServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public QueryMovieServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
MovieDao movieDao = new MovieDaoImpl();
List<Movie> movies = movieDao.queryAllMovies();
request.setAttribute("movies", movies);
//轉發到bar.jsp
request.getRequestDispatcher("bar.jsp").forward(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
10. 開啟WEB-INF下的web.xml,將我們新建的bar.jsp新增進去
<?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_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>MovieEchartsBar</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>bar.jsp</welcome-file>
</welcome-file-list>
</web-app>
11. 開啟jsp檔案,引入Echarts------>>在繪圖前我們需要為 ECharts 準備一個具備高寬的 DOM 容器---->>引入JSTL標籤庫------>>用EL表示式獲取request中的資料,使用遍歷元素
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!-- 引入JSTL標籤庫 -->
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!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>Insert title here</title>
<!-- 引入Echarts -->
<script type="text/javascript" src="res/js/echarts.min.js"></script>
</head>
<body>
<!-- 為ECharts準備一個具備大小(寬高)的Dom -->
<div id="main" style="width: 900px;height:600px;"></div>
<script type="text/javascript">
var rate=new Array()
var index=0;
<c:forEach items="${movies}" var="m">
rate[index]="${m.m_ratings}";
index++;
</c:forEach>
// 基於準備好的dom,初始化echarts例項
var myChart = echarts.init(document.getElementById('main'));
// 指定圖表的配置項和資料
option = {
color: ['#3398DB'],
title: {
text: '豆瓣電影評分',
subtext: '資料來自爬蟲mysql',
// verticalAlign: top,
left:'center'
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
//圖例
// data: ['2011年', '2012年']
show: false
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'value',
boundaryGap: [0, 0.01]
},
yAxis: {
type: 'category',
data:// ['巴西','印尼','美國','印度','中國','世界人口(萬)']
[ <c:forEach items="${movies}" var="g">
["${g.m_title}"],
</c:forEach> ]
},
series: [
{
name: '2011年',
type: 'bar',
data: rate
},
]
};
// 使用剛指定的配置項和資料顯示圖表。
myChart.setOption(option);
</script>
</body>
</html>
12. 將該專案部署到tomcat伺服器,啟動伺服器,執行專案;
餅狀圖案例
餅圖常用來做資料佔比的視覺化,僅排列在工作表的一列或一行中的資料可以繪製到餅圖中。餅圖顯示一個數據系列 (資料系列:在圖表中繪製的相關資料點,這些資料來源自資料表的行或列。圖表中的每個資料系列具有唯一的顏色或圖案並且在圖表的圖例中表示。可以在圖表中繪製一個或多個數據系列。餅圖只有一個數據系列。)各項的大小與各項總和的比例。餅圖中的資料點 (資料點:在圖表中繪製的單個值,這些值由條形、柱形、折線、餅圖或圓環圖的扇面、圓點和其他被稱為資料標記的圖形表示。相同顏色的資料標記組成一個數據系列。)顯示為整個餅圖的百分比。常用的有如下形式:
常用配置項引數:
- title:標題元件,包含主標題和副標題。
- title.show boolean[ default: true ],是否顯示標題元件
- title.text string[ default: '' ],主標題文字,支援使用 \n 換行
- title.target string[ default: 'blank' ],指定視窗開啟主標題超連結
- title.target string[ default: 'blank' ],指定視窗開啟主標題超連結。可選:'self' 當前視窗開啟;'blank' 新視窗開啟
- title.textStyle.color Color[ default: '#333' ],主標題文字的顏色
- title.textStyle.fontStyle string[ default: 'normal' ],主標題文字字型的風格,可選:'normal','italic','oblique'
- title.textStyle.verticalAlign string文字垂直對齊方式,預設自動。可選:'top','middle','bottom
- title.subtext string[ default: '' ],副標題文字,支援使用 \n 換行
- legend:圖例元件
- grid:直角座標系內繪圖網格,單個 grid 內最多可以放置上下兩個 X 軸,左右兩個 Y 軸。可以在網格上繪製折線圖,柱狀圖,散點圖(氣泡圖)。
- xAxis:直角座標系 grid 中的 x 軸,一般情況下單個 grid 元件最多隻能放上下兩個 x 軸,多於兩個 x 軸需要通過配置 offset 屬性防止同個位置多個 x 軸的重疊
- yAxis:直角座標系 grid 中的 y 軸,一般情況下單個 grid 元件最多隻能放左右兩個 y 軸,多於兩個 y 軸需要通過配置 offset 屬性防止同個位置多個 Y 軸的重疊
- color:調色盤顏色列表。如果系列沒有設定顏色,則會依次迴圈從該列表中取顏色作為系列顏色
需求:將WebMagic爬蟲獲取到的豆瓣電影不同型別總數以餅圖的形式展現出來。(步驟同上)
1. 編寫Movie類,新增屬性並提供構造器、set和get方法,重新編寫toString方法
package com.liudm.entity;
public class Movie {
//電影資訊
private int m_id;
private String m_title;
private String m_urls;
private float m_ratings;
//電影詳細資訊
private String m_dir;
private String m_actor;
private String m_type;
private String m_time;
public Movie() {
super();
}
//視覺化資料:餅圖
private int count_type;
public Movie(String m_type, int count_type){
super();
this.m_type = m_type;
this.setCount_type(count_type);
}
public Movie(String m_title, String m_urls, float m_ratings,
String m_dir, String m_actor, String m_type, String m_time) {
super();
this.m_title = m_title;
this.m_urls = m_urls;
this.m_ratings = m_ratings;
this.m_dir = m_dir;
this.m_actor = m_actor;
this.m_type = m_type;
this.m_time = m_time;
}
public Movie(int m_id, String m_title, String m_urls, float m_ratings,
String m_dir, String m_actor, String m_type, String m_time) {
super();
this.m_id = m_id;
this.m_title = m_title;
this.m_urls = m_urls;
this.m_ratings = m_ratings;
this.m_dir = m_dir;
this.m_actor = m_actor;
this.m_type = m_type;
this.m_time = m_time;
}
public int getM_id() {
return m_id;
}
public void setM_id(int m_id) {
this.m_id = m_id;
}
public String getM_title() {
return m_title;
}
public void setM_title(String m_title) {
this.m_title = m_title;
}
public String getM_urls() {
return m_urls;
}
public void setM_urls(String m_urls) {
this.m_urls = m_urls;
}
public float getM_ratings() {
return m_ratings;
}
public void setM_ratings(float m_ratings) {
this.m_ratings = m_ratings;
}
public String getM_dir() {
return m_dir;
}
public void setM_dir(String m_dir) {
this.m_dir = m_dir;
}
public String getM_actor() {
return m_actor;
}
public void setM_actor(String m_actor) {
this.m_actor = m_actor;
}
public String getM_type() {
return m_type;
}
public void setM_type(String m_type) {
this.m_type = m_type;
}
public String getM_time() {
return m_time;
}
public void setM_time(String m_time) {
this.m_time = m_time;
}
public int getCount_type() {
return count_type;
}
public void setCount_type(int count_type) {
this.count_type = count_type;
}
@Override
public String toString() {
return "Movie [m_id=" + m_id + ", m_title=" + m_title + ", m_urls="
+ m_urls + ", m_ratings=" + m_ratings + ", m_dir=" + m_dir
+ ", m_actor=" + m_actor + ", m_type=" + m_type + ", m_time="
+ m_time + ", count_type=" + count_type + "]";
}
}
編寫mysql.properties屬性檔案,儲存連線資料庫的相關配置資訊:其中資料庫名為movies
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/movies
username=root
pwd=nothing
編寫MySqlUtil.java,連線資料庫的相關內容
package com.liudm.utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
public class MySqlUtil {
// 讀取屬性檔案,獲得連線
static Connection con = null;
static Properties ps = new Properties();
static {
// 讀取屬性檔案
InputStream in = MySqlUtil.class.getClassLoader().getResourceAsStream("mysql.properties");
try {
ps.load(in);
String driver = ps.getProperty("driver");
String url = ps.getProperty("url");
String username = ps.getProperty("username");
String pwd = ps.getProperty("pwd");
System.out.println(driver + url + username + pwd);
Class.forName(driver);
con = DriverManager.getConnection(url, username, pwd);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static Connection getConnection() {
return con;
}
// 關閉資源
public static void closeRes(ResultSet rs, PreparedStatement ps, Connection con) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (con != null) {
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
2. 編寫介面MovieDao.java,新增抽象方法,實現電影型別的查詢
package com.liudm.dao;
import java.util.List;
import com.liudm.entity.Movie;
public interface MovieDao {
public List<Movie> queryAllMovies();
//電影型別查詢
public List<Movie> queryMovieType();
}
3. 編寫MovieDaoImpl.java,重寫queryMovieType方法,該查詢的sql語句為:以電影的型別分組查詢並計算每組的總數,限制查詢前20條,否則由於資料量大,種類繁多,餅圖顯示很醜,在統計學中會有抽樣統計等。
package com.liudm.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.liudm.entity.Movie;
import com.liudm.utils.MySqlUtil;
public class MovieDaoImpl implements MovieDao{
Connection con = null;
Movie movie = null;
PreparedStatement pre = null;
ResultSet rs = null;
@Override
public List<Movie> queryAllMovies() {
con = MySqlUtil.getConnection();
List list = new ArrayList();
String sql="select * from movies limit 30";
try {
pre = con.prepareStatement(sql);
rs = pre.executeQuery();
while(rs.next()){
int mid=rs.getInt("m_id");
String mtitle=rs.getString("m_title");
String murls=rs.getString("m_urls");
float mratings=rs.getFloat("m_ratings");
String mdir=rs.getString("m_dir");
String mactor=rs.getString("m_actor");
String mtype=rs.getString("m_type");
String mtime=rs.getString("m_time");
movie = new Movie(mid, mtitle, murls, mratings, mdir, mactor, mtype, mtime);
list.add(movie);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//MySQLUtil.closeRes(rs, pre, con);
}
return list;
}
public List<Movie> queryMovieType() {
con = MySqlUtil.getConnection();
List list = new ArrayList();
//sql語句+通道
//String sql="select * from movies order by m_ratings desc limit 30";
String sql = "SELECT m_type, COUNT(m_type) as count_type FROM movies GROUP BY m_type limit 20";
try {
pre = con.prepareStatement(sql);
rs = pre.executeQuery();
while (rs.next()) { //一次while迴圈拿到下一條記錄
//在記錄中拿到欄位
//int mid=rs.getInt("m_id");
String m_type = rs.getString("m_type");
int count_type = rs.getInt("count_type");
movie = new Movie(m_type,count_type);
list.add(movie);
}
} catch (SQLException e) {
// TODO: handle exception
e.printStackTrace();
} finally {
//MySqlUtil.closeRes(rs, pre, con);
}
return list;
}
}
4. 新建home.jsp檔案,開啟WEB-INF下的web.xml,將剛才新建的home.jsp新增進去
<?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" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>MovieEchartsBar1</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>home.jsp</welcome-file>
</welcome-file-list>
</web-app>
5. 開啟home.jsp,編寫兩個a標籤,讓其跳轉到後臺servlet中獲取資料庫中資料,然後攜帶資料到前端jsp頁面顯示servlet就相當於一箇中轉站,處理資料。a標籤中的href屬性說明:
- href是a標籤跳轉目標的地址
- ${ pageContext.request.contextPath}是EL表示式獲取專案所在路徑的寫法
- RatingsServlet是我們編寫的servlet的url,tomcat伺服器通過這個url找到servlet所在的類並執行doGet或者doPost方法
- ?:是拼接引數的符號
- params=bar_t":引數通過鍵值對的形式存在
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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>Insert title here</title>
</head>
<body>
<a href="${ pageContext.request.contextPath}/QueryMovieServlet?params=bar">電影評分條狀圖</a>
</br>
<a href="${ pageContext.request.contextPath}/QueryMovieServlet?params=pie">電影型別餅狀圖</a>
</br>
</body>
</html>
6. 編寫QueryMovieServlet.java
package com.liudm.servlet;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.liudm.dao.MovieDao;
import com.liudm.dao.MovieDaoImpl;
import com.liudm.entity.Movie;
@WebServlet("/QueryMovieServlet")
public class QueryMovieServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public QueryMovieServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
MovieDao movieDao = new MovieDaoImpl();
String params = request.getParameter("params");
if("bar".equals(params)){
List<Movie> movies=movieDao.queryAllMovies();
request.setAttribute("movies", movies);
request.getRequestDispatcher("bar.jsp").forward(request, response);
}else if("pie".equals(params)){
List<Movie> moviestype = movieDao.queryMovieType();
request.setAttribute("moviestype", moviestype);
request.getRequestDispatcher("pie.jsp").forward(request, response);
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
7. 編寫pie.jsp檔案,用EL表示式獲取request中的資料,使用遍歷元素,pie.jsp完整程式碼為:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!-- 引入JSTL標籤庫 -->
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!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>Insert title here</title>
<!-- 引入 ECharts -->
<script src="${ pageContext.request.contextPath }/res/js/echarts.min.js"></script>
</head>
<body>
<!--${moviestype} -->
<!-- 為ECharts準備一個具備大小(寬高)的Dom容器 -->
<div id="main" style="width: 100%;height:400px;"></div>
<script type="text/javascript">
// 基於準備好的dom,初始化echarts例項
var myChart = echarts.init(document.getElementById('main'));
// 指定圖表的配置項和資料
option = {
title : {
text: '南丁格爾玫瑰圖',
subtext: '電影型別佔比圖',
x:'center'
},
tooltip : {
trigger: 'item',
formatter: "{a} <br/>{b} : {c} ({d}%)"
},
legend: {
x : 'center',
y : 'bottom',
data://['rose1','rose2','rose3','rose4','rose5','rose6','rose7','rose8']
[
<c:forEach items="${movies}" var="g">
['${g.m_type}'],
</c:forEach>
]
},
toolbox: {
show : true,
feature : {
mark : {show: true},
dataView : {show: true, readOnly: false},
magicType : {
show: true,
type: ['pie', 'funnel']
},
restore : {show: true},
saveAsImage : {show: true}
}
},
calculable : true,
series : [
{
name:'面積模式',
type:'pie',
radius : [30, 110],
center : ['45%', '50%'],
roseType : 'area',
data:[
<c:forEach items="${moviestype}" var="g">
{value:"${g.count_type}",name:"${g.m_type}"},
</c:forEach>
// {value:10, name:'rose1'},
// {value:5, name:'rose2'},
// {value:15, name:'rose3'},
// {value:25, name:'rose4'},
// {value:20, name:'rose5'},
// {value:35, name:'rose6'},
// {value:30, name:'rose7'},
// {value:40, name:'rose8'}
]
}
]
};
// 使用剛指定的配置項和資料顯示圖表。
myChart.setOption(option);
</script>
</body>
</html>
8. 將該專案部署到tomcat伺服器,啟動伺服器,執行專案,開啟火狐瀏覽器,輸入地址:http://localhost:8080/MovieEchartsBar,回車,出現如圖所示資訊:
分別點選超連結:
折線圖案例
折線圖是排列在工作表的列或行中的資料可以繪製到折線圖中。折線圖可以顯示隨時間(根據常用比例設定)而變化的連續資料,因此非常適用於顯示在相等時間間隔下資料的趨勢。在折線圖中,類別資料沿水平軸均勻分佈,所有值資料沿垂直軸均勻分佈。常用的有如下形式:
常用配置項引數:
- title:標題元件,包含主標題和副標題。
- title.show boolean[ default: true ],是否顯示標題元件
- title.text string[ default: '' ],主標題文字,支援使用 \n 換行
- title.target string[ default: 'blank' ],指定視窗開啟主標題超連結
- title.target string[ default: 'blank' ],指定視窗開啟主標題超連結。可選:'self' 當前視窗開啟;'blank' 新視窗開啟
- title.textStyle.color Color[ default: '#333' ],主標題文字的顏色
- title.textStyle.fontStyle string[ default: 'normal' ],主標題文字字型的風格,可選:'normal','italic','oblique'
- title.textStyle.verticalAlign string文字垂直對齊方式,預設自動。可選:'top','middle','bottom
- title.subtext string[ default: '' ],副標題文字,支援使用 \n 換行
- legend:圖例元件
- grid:直角座標系內繪圖網格,單個 grid 內最多可以放置上下兩個 X 軸,左右兩個 Y 軸。可以在網格上繪製折線圖,柱狀圖,散點圖(氣泡圖)。
- xAxis:直角座標系 grid 中的 x 軸,一般情況下單個 grid 元件最多隻能放上下兩個 x 軸,多於兩個 x 軸需要通過配置 offset 屬性防止同個位置多個 x 軸的重疊
- yAxis:直角座標系 grid 中的 y 軸,一般情況下單個 grid 元件最多隻能放左右兩個 y 軸,多於兩個 y 軸需要通過配置 offset 屬性防止同個位置多個 Y 軸的重疊
- color:調色盤顏色列表。如果系列沒有設定顏色,則會依次迴圈從該列表中取顏色作為系列顏色
要求:將WebMagic爬蟲獲取到的豆瓣電影不同年份電影數量以折線圖的形式展現出來。
1. 編寫Movie類,新增屬性並提供構造器、set和get方法,重新編寫toString方法
package com.liudm.entity;
public class Movie {
private int m_id;
private String m_title;
private String m_urls;
private float m_ratings;
private String m_dir;
private String m_actor;
private String m_type;
private String m_time;
public Movie() {
super();
}
private int count_type;
private int count_title;
public Movie(String m_type, int count_type){
super();
this.m_type = m_type;
this.count_type = count_type;
}
public Movie(int m_id, String m_time, int count_title){
super();
this.m_id = m_id;
this.m_time = m_time;
this.count_title = count_title;
}
public Movie(String m_title, String m_urls, float m_ratings,
String m_dir, String m_actor, String m_type, String m_time) {
super();
this.m_title = m_title;
this.m_urls = m_urls;
this.m_ratings = m_ratings;
this.m_dir = m_dir;
this.m_actor = m_actor;
this.m_type = m_type;
this.m_time = m_time;
}
public Movie(int m_id, String m_title, String m_urls, float m_ratings,
String m_dir, String m_actor, String m_type, String m_time) {
super();
this.m_id = m_id;
this.m_title = m_title;
this.m_urls = m_urls;
this.m_ratings = m_ratings;
this.m_dir = m_dir;
this.m_actor = m_actor;
this.m_type = m_type;
this.m_time = m_time;
}
public int getM_id() {
return m_id;
}
public void setM_id(int m_id) {
this.m_id = m_id;
}
public String getM_title() {
return m_title;
}
public void setM_title(String m_title) {
this.m_title = m_title;
}
public String getM_urls() {
return m_urls;
}
public void setM_urls(String m_urls) {
this.m_urls = m_urls;
}
public float getM_ratings() {
return m_ratings;
}
public void setM_ratings(float m_ratings) {
this.m_ratings = m_ratings;
}
public String getM_dir() {
return m_dir;
}
public void setM_dir(String m_dir) {
this.m_dir = m_dir;
}
public String getM_actor() {
return m_actor;
}
public void setM_actor(String m_actor) {
this.m_actor = m_actor;
}
public String getM_type() {
return m_type;
}
public void setM_type(String m_type) {
this.m_type = m_type;
}
public String getM_time() {
return m_time;
}
public void setM_time(String m_time) {
this.m_time = m_time;
}
public int getCount_type() {
return count_type;
}
public void setCount_type(int count_type) {
this.count_type = count_type;
}
public int getCount_title() {
return count_title;
}
public void setCount_title(int count_title) {
this.count_title = count_title;
}
@Override
public String toString() {
return "Movie [m_id=" + m_id + ", m_title=" + m_title + ", m_urls="
+ m_urls + ", m_ratings=" + m_ratings + ", m_dir=" + m_dir
+ ", m_actor=" + m_actor + ", m_type=" + m_type + ", m_time="
+ m_time + ", count_type=" + count_type + ", count_title=" + count_title + "]";
}
}
mysql.properties屬性檔案和MySqlUtil.java連線資料庫,內容同上。
2. 編寫MovieDao.java,新增抽象方法,實現電影型別的查詢
package com.liudm.dao;
import java.util.List;
import com.liudm.entity.Movie;
public interface MovieDao {
public List<Movie> queryAllMovies();
public List<Movie> queryMovieType();
public List<Movie> queryMovieTime();
}
3. 編寫MovieDaoImpl.java,重寫queryMovieTime方法,該查詢的sql語句為:以電影的時間分組查詢並計算每組的總數,限制查詢前30條,否則由於資料量大,種類繁多,餅圖顯示很醜,在統計學中會有抽樣統計等。
package com.liudm.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.liudm.entity.Movie;
import com.liudm.utils.MySqlUtil;
public class MovieDaoImpl implements MovieDao{
Connection con = null;
Movie movie = null;
PreparedStatement pre = null;
ResultSet rs = null;
@Override
public List<Movie> queryAllMovies() {
con = MySqlUtil.getConnection();
List list = new ArrayList();
String sql="select * from movies limit 30";
try {
pre=con.prepareStatement(sql);
rs= pre.executeQuery();
while(rs.next()){
int mid=rs.getInt("m_id");
String mtitle=rs.getString("m_title");
String murls=rs.getString("m_urls");
float mratings=rs.getFloat("m_ratings");
String mdir=rs.getString("m_dir");
String mactor=rs.getString("m_actor");
String mtype=rs.getString("m_type");
String mtime=rs.getString("m_time");
movie = new Movie(mid, mtitle, murls, mratings, mdir, mactor, mtype, mtime);
list.add(movie);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//MySQLUtil.closeRes(rs, pre, con);
}
return list;
}
public List<Movie> queryMovieType() {
con = MySqlUtil.getConnection();
List list = new ArrayList();
String sql = "SELECT m_type, COUNT(m_type) as count_type FROM movies GROUP BY m_type limit 20";
try {
pre = con.prepareStatement(sql);
rs = pre.executeQuery();
while (rs.next()) {
String m_type = rs.getString("m_type");
int count_type = rs.getInt("count_type");
movie = new Movie(m_type,count_type);
list.add(movie);
}
} catch (SQLException e) {
// TODO: handle exception
e.printStackTrace();
} finally {
//MySqlUtil.closeRes(rs, pre, con);
}
return list;
}
@Override
public List<Movie> queryMovieTime() {
// TODO Auto-generated method stub
con = MySqlUtil.getConnection();
List list = new ArrayList();
String sql = "SELECT m_time, COUNT(m_title) as count_title FROM movies GROUP BY m_time limit 30";
try {
pre = con.prepareStatement(sql);
rs = pre.executeQuery();
while (rs.next()) {
String m_time = rs.getString("m_time");
int count_title = rs.getInt("count_title");
movie = new Movie(1,m_time,count_title);
list.add(movie);
}
} catch (SQLException e) {
// TODO: handle exception
e.printStackTrace();
} finally {
//MySqlUtil.closeRes(rs, pre, con);
}
return list;
}
}
4. 開啟home.jsp,編寫兩個a標籤,讓其跳轉到後臺servlet中獲取資料庫中資料,然後攜帶資料到前端jsp頁面顯示servlet就相當於一箇中轉站,處理資料。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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>Insert title here</title>
</head>
<body>
<a href="${ pageContext.request.contextPath}/QueryMovieServlet?params=bar">電影評分條狀圖</a>
</br>
<a href="${ pageContext.request.contextPath}/QueryMovieServlet?params=pie">電影型別餅狀圖</a>
</br>
<a href="${ pageContext.request.contextPath}/QueryMovieServlet?params=line">上映時間折線圖</a>
</br>
</body>
</html>
5. 開啟QueryMovieServlet.java,新增處理引數是line時呼叫dao層queryMovieTime的方法。
package com.liudm.servlet;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.liudm.dao.MovieDao;
import com.liudm.dao.MovieDaoImpl;
import com.liudm.entity.Movie;
@WebServlet("/QueryMovieServlet")
public class QueryMovieServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public QueryMovieServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
MovieDao movieDao = new MovieDaoImpl();
String params = request.getParameter("params");
if("bar".equals(params)){
List<Movie> movies=movieDao.queryAllMovies();
request.setAttribute("movies", movies);
request.getRequestDispatcher("bar.jsp").forward(request, response);
}else if("pie".equals(params)){
List<Movie> moviestype = movieDao.queryMovieType();
request.setAttribute("moviestype", moviestype);
request.getRequestDispatcher("pie.jsp").forward(request, response);
} else if("line".equals(params)){
List<Movie> moviestime = movieDao.queryMovieTime();
request.setAttribute("moviestime", moviestime);
request.getRequestDispatcher("line.jsp").forward(request, response);
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
6. 在WebContent下新建line.jsp,編寫line.jsp檔案:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!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>Insert title here</title>
<script src="${ pageContext.request.contextPath }/res/js/echarts.min.js"></script>
</head>
<body>
<!-- 為ECharts準備一個具備大小(寬高)的Dom -->
<div id="main" style="width: 100%;height:400px;"></div>
<script type="text/javascript">
// 基於準備好的dom,初始化echarts例項
var myChart = echarts.init(document.getElementById('main'));
// 指定圖表的配置項和資料
option = {
title: {
text: '電影年份走勢圖'
},
tooltip: {
trigger: 'axis'
},
legend: {
data:['不同年份受歡迎電影總數']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: //['週一','週二','週三','週四','週五','週六','週日']
[
<c:forEach items="${moviestime}" var="g">
["${g.m_time}"],
</c:forEach>
]
},
yAxis: {
type: 'value'
},
series: [
{
name:'電影總數',
type:'line',
stack: '總量',
data://[120, 132, 101, 134, 90, 230, 210]
[
<c:forEach items="${moviestime}" var="m">
("${m.count_title}"),
</c:forEach>
]
},
]
};
// 使用剛指定的配置項和資料顯示圖表。
myChart.setOption(option);
</script>
</body>
</html>
7. 將該專案部署到tomcat伺服器,啟動伺服器,執行專案,開啟火狐瀏覽器,輸入地址:http://localhost:8080/MovieEchartsBar,回車,出現如圖所示資訊:
點選折線圖超連結: