410013796724260
• Webmoney
R335386147728
Z369087728698
Cервлет c диаграммами Chart.jsПредставление на странице сайта графического изображения, сформированного динамически на основе числовых данных, является важной составляющей любого WEB-проекта. Это делает сайт более презентабельным и привлекательным. На текущей странице будет рассмотрен пример использования в сервлете графической JavaScript библиотеки Chart.js. Отличительной особенностью данной библиотеки является создание линейных графиков, столбцовых, круговых и радиальных диаграмм. Библиотека Chart.js поддерживает использование анимированных эффектов и имеет небольшой размер. Описание примераРассматриваемый пример создания интерактивных диаграмм с использованием сервлета и скриптовой библиотеки Chart.js демонстрирует :
WEB-приложение chart-js включает сервлет ChartServlet.java, скриптовые библиотеки js (Chart.js, Chart.min.js, color.js) и данные в директории js.data (bar.js, pie.js, line.js). Библиотека Chart.js в примере не используется. В файле color.js определен скриптовый объект формирования цветовой гаммы. Скриптовые данные директории js.data используются для создания диаграмм.
Статическая страница chart.html отображает диаграмму Chart.js с закрашиванием области под графиком. Статическая страница index.html открывается на сайте по умолчанию при старте и предлагает выбрать один из видов диаграммы. При нажатии на кнопку «Generate chart» вызывается сервлет, формирующий соответствующую страницу.
Листинг дескриптора web.xmlДескриптор приложения web.xml включает описание сервлета (servlet-name, servlet-class), его вызов (url-pattern) и открываемую страницу по умолчанию.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee">
<servlet>
<servlet-name>ChartServlet</servlet-name>
<servlet-class>common.servlets.ChartServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ChartServlet</servlet-name>
<url-pattern>/chartserver</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
Листинг файла colors.jsВ файле colors.js определяются глобальный объект color и массив данных chartColors, которые будут использованы при определении цветовой гаммы объектов диаграмм Chart.js.
var color = Chart.helpers.color;
var chartColors = {
red : 'rgb(255, 99, 132)',
orange : 'rgb(255, 159, 64)',
yellow : 'rgb(255, 205, 86)',
green : 'rgb( 75, 192, 192)',
blue : 'rgb( 54, 162, 235)',
purple : 'rgb(153, 102, 255)',
grey : 'rgb(201, 203, 207)'
};
Листинг сервлета ChartServlet.javaСервлет ChartServlet.java включает переменные и методы. В переменных определены шаблон формирования подключения строки скриптовых данных, наименование диаграммы и ее размеры. Переменная page_index_return определяет способ возврата со страницы с диаграммой на главную страницу. В методе doGet осуществляется обработка запроса браузера - анализ параметра и вызов соответствующих методов формирования диаграмм. Методы createCanvasDesc и createCanvasContext используются для определения места расположения диаграммы и создания контекста.
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ChartServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
private String SCRIPT = "<script src=\"js.data/%s\"></script>";
private final String CANVAS_name = "chart";
private final int CHART_width = 480;
private final int CHART_height = 320;
// Флаг вида перехода на индексную страницу 'page_index_return'
private int page_index_return = -1;
public ChartServlet() {}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
// см. код ниже
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private String createCanvasDesc(){
String TEMP = "<div id=\"container\" "
+ "style=\"border:1px solid #ccc;"
+ "width:%dpx;height:%dpx;padding:5px\">"
+ "<canvas id=\"%s\" width=\"%d\" height=\"%d\">"
+ "</canvas>"
+ "</div>";
return String.format(TEMP,CHART_width + 10,CHART_height + 10,
CANVAS_name,CHART_width,CHART_height);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private String createCanvasContext(){
String TEMP = "var ctx = document.getElementById(\"%s\")
.getContext(\"2d\");";
return String.format(TEMP, CANVAS_name);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private String createDataBar(final String fname)
{
String script = String.format(SCRIPT, fname);
// create data.js
return script;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private String createDataPie(final String fname)
{
String script = String.format(SCRIPT, fname);
// create data.js
return script;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private String createDataLine(final String fname)
{
String script = String.format(SCRIPT, fname);
// create data.js
return script;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private String startPage(final String param_chart)
{
// см. код ниже
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private String createBarChartPage()
{
// см. код ниже
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private String createPieChartPage()
{
// см. код ниже
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private String createLineChartPage()
{
// см. код ниже
}
}
Методы createDataBar, createDataPie, createDataLine предназначены для динамического формирования набора данных. Однако в примере наборы данных представлены в виде отдельных файлов, расположенных в директории js.data и динамически не формируются, чтобы не загромождать код лишней информацией (которой и так достаточно. Вы можете при необходимости самостоятельно оформить данные процедуры для динамического создания наборов данных в формате JavaScript. Методы createBarChartPage, createPieChartPage, createLineChartPage динамически формируют страницы с размещением в них соответствующих диаграмм библиотеки Chart.js и кнопок возврата на главную страницу сайта. Код данных процедур и интерфейс страниц представлен ниже. Метод startPage динамически создает страницу с интерфейсом статической главной страницы index.html, открываемой по умолчанию при переходе на сайт. Листинг метода doGet(HttpServletRequest, HttpServletResponse)В методе сервлета doGet анализируется входной параметр «chart» (переменная param_chart). В зависимости от его значения будет открыта соответствующая страница с диаграммой. Данный параметр сохраняется в сессии HttpSession в виде атрибута LAST_CALL, чтобы при создании стартовой страницы (метод startPage) устанавливать значение последней открытой страницы в radio-button. Если параметр «chart» неопределен (null), т.е. сервлет был вызван при возврате с одной из страниц с диаграммой, то принимается решение каким образом открыть главную страницу. Для этого используется переменная «page_index_return» (Вы можете самостоятельно выбрать вариант перехода). Вариант 1. На главную страницу можно попасть, вызвав метод sendRedirect класса HttpServletResponse. В этом случае обработка перехода будет выполнена в браузере и URL страницы обновится. Вариант 2. При использовании метода forward класса RequestDispatcher - обработка перехода выполняется в контейнере приложения (сервлете). В этом случае будет открыта соответствующая страница, но без изменения адреса URL. Т.е. в адресной строке останется вызов сервлета. Вариант 3. Можно динамически создать индексную страницу (метод startPage), которая и будет открыта в браузере. В этом случае адресная строка URL также не изменится и будет содержать вызов сервлета. При определенном значении параметра «chart» сервлет вызывает один из методов динамического формирования страницы с соответствующей диаграммой. Контент страницы записывается в выходной поток OutputStream в кодировке UTF-8, чтобы обеспечить правильное представление кириллицы.
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
String param_chart = request.getParameter("chart");
String last_call = null;
// Последний вызов
HttpSession session = request.getSession();
if (session != null)
last_call = (String) session.getAttribute("LAST_CALL");
OutputStream outStream = response.getOutputStream();
String content = "";
if (param_chart == null) {
ServletContext context = request.getSession().getServletContext();
// Перенаправление на страницу
if (page_index_return == -1) {
// Возврат на страницу проекта, используемую по умолчанию,
// с переопределением URL (обработка в браузере)
response.sendRedirect("/chart-js");
} else if ((page_index_return == 0) && (context != null)) {
// Возврат на страницу по умолчанию без переопределения
// URL (обработка в контейнере приложения)
RequestDispatcher dispatcher;
dispatcher = context.getRequestDispatcher("/index.html");
dispatcher.forward(request, response);
} else {
// Определение последнего вызова
if ((last_call != null) && (param_chart == null))
param_chart = last_call;
content = startPage(param_chart);
last_call = null;
}
} else if (param_chart.equalsIgnoreCase("bar")) {
last_call = param_chart;
content = createBarChartPage();
} else if (param_chart.equalsIgnoreCase("pie")) {
content = createPieChartPage();
last_call = param_chart;
} else if (param_chart.equalsIgnoreCase("line")) {
content = createLineChartPage();
last_call = param_chart;
}
outStream.write(content.getBytes("UTF-8"));
outStream.flush();
outStream.close();
// Сохранение последнего вызова
if (session != null)
session.setAttribute("LAST_CALL", last_call);
}
Листинг метода startPageМетод startPage формирует страницу, интерфейс которой соответствует индексной странице сайта index.html, определенной в дескрипторе приложения web.xml для открытия по умолчанию. В метод передается значение параметра «chart» сервлета (param_chart), определяющий последний вызов, чтобы установить соответствующий флаг в группе radio-кнопок интерфейса страницы.
private String startPage(final String param_chart)
{
String barChecked = " CHECKED";
String pieChecked = "";
String lineChecked = "";
if (param_chart != null) {
barChecked = (param_chart.equals("bar" ) ? " CHECKED" : "");
pieChecked = (param_chart.equals("pie" ) ? " CHECKED" : "");
lineChecked = (param_chart.equals("line") ? " CHECKED" : "");
}
String content = "";
content += "<!DOCTYPE html PUBLIC " +
"\"-//W3C//DTD HTML 4.01 Transitional//EN\" " +
"\"http://www.w3.org/TR/html4/loose.dtd\"> ";
content += "<html>";
content += "<head>";
content += "<meta charset=\"UTF-8\">";
content += "<title>Chart.js</title>";
content += "</head>";
content += "<body>";
content += "<h3>JavaScript библиотека Chart.js</h3>";
content += "<p>Выберите тип диаграммы :/p>";
content += "<FORM ACTION=\"chartserver\" METHOD=\"GET\">";
content += "<INPUT TYPE=\"radio\" NAME=\"chart\"";
content += "VALUE=\"bar\"" + barChecked + "> Bar Chart";
content += "<INPUT TYPE=\"radio\" NAME=\"chart\"";
content += "VALUE=\"pie\"" + pieChecked + "> Pie Chart";
content += "<INPUT TYPE=\"radio\" NAME=\"chart\"";
content += "VALUE=\"line\"" + lineChecked + "> Line Chart";
content += "<P />";
content += "<INPUT TYPE=\"submit\" VALUE=\"Generate chart\">";
content += "</FORM> ";
content += "</body>";
content += "</html>";
return content;
}
Интерфейс страницы представлен на следующем скриншоте. Следует обратить внимание на строку URL, которая включает вызов сервлета chartserver без параметров.
Код созданной страницы соответствует контенту индексной страницы index.html. Тег <meta> определяет кодировку страницы UTF-8.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Chart.js</title>
</head>
<body>
<h3>JavaScript библиотека Chart.js</h3>
<p>Выберите тип диаграммы :</p>
<FORM ACTION="chartserver">
<INPUT TYPE="radio" NAME="chart" VALUE="bar" CHECKED>Bar Chart
<INPUT TYPE="radio" NAME="chart" VALUE="pie">Pie Chart
<INPUT TYPE="radio" NAME="chart" VALUE="line"> Line Chart
<P />
<INPUT TYPE="submit" VALUE="Generate chart">
</FORM>
</body>
</html>
Листинг метода createBarChartPageМетод createBarChartPage вызывает процедуру подготовки данных (createDataBar(name)) при формировании страницы с гистограммой. В разделе заголовка страницы (head) определяются файлы скриптов (Chart.min.js, colors.js), которые необходимо загрузить браузеру при открытии страницы. Кодировка страницы UTF-8.
private String createBarChartPage()
{
String content = "";
content += "<!DOCTYPE html PUBLIC ";
content += "\"-//W3C//DTD HTML 4.01 Transitional//EN\" ";
content += "\"http://www.w3.org/TR/html4/loose.dtd\"> " ;
content += "<html>";
content += "<head>";
content += "<title>Bar Chart (chart.js)</title>";
content += "<meta charset=\"UTF-8\">";
content += "<script src=\"js/Chart.min.js\"></script>";
content += "<script src=\"js/colors.js\"></script>";
content += createDataBar("bar.js");
content += "</head>";
content += "<body>";
content += createCanvasDesc();
content += "<script>";
content += "window.onload = function() {"
+ createCanvasContext()
+ "window.bar = new Chart(ctx, {"
+ "type: 'bar',"
+ "data: barChartData,"
+ "options: {"
+ "responsive: true,"
+ "legend: {"
+ "position: 'bottom',"
+ "},"
+ "title: {"
+ "display: true,"
+ "text: 'Bar Chart (Chart.js)'"
+ "} "
+ "}"
+ "});"
+ "};";
content += "</script>";
content += "<P />";
content += "<FORM ACTION=\"chartserver\" METHOD=\"GET\">";
content += "<INPUT TYPE=\"submit\" VALUE=\"Назад\">";
content += "</FORM>";
content += "</body>";
content += "</html>";
return content;
}
В качестве опций диаграммы (options) определено нижнее размещение легенды (legend), перерисовка диаграммы при изменении размера контейнера (responsive) и заголовок. Интерфейс страницы с изображением гистограммы представлен на следующем скриншоте.
Всплывающая подсказка выводится при наведении курсора мыши на столбец по умолчанию. URL страницы включает вызов сервлета с параметром «/chartserver?chart=bar». Листинг данныхВ файле данных bar.js определена функция генерирования значения randomScalingFactor и объект данных barChartData, включающий массив меток labels и массив данных datasets из двух наборов. Для каждого набора определен цвет столбца и цвет рамки столбца.
randomScalingFactor = function()
{
return (Math.random() > 0.5 ? 1.0 : -1.0) *
Math.round(Math.random() * 100);
};
var barChartData = {
labels: ["Январь", "Февраль", "Март",
"Апрель", "Май", "Июнь", "Июль"],
datasets: [{
label: 'Dataset 1',
backgroundColor: color(chartColors.red).alpha(0.5).rgbString(),
borderColor: chartColors.red,
borderWidth: 1,
data: [
randomScalingFactor(),
randomScalingFactor(),
. . .
]
},
{
label: 'Dataset 2',
backgroundColor: color(chartColors.blue).alpha(0.5).rgbString(),
borderColor: chartColors.blue,
borderWidth: 1,
data: [
randomScalingFactor(),
randomScalingFactor(),
. . .
]
}]
};
Листинг метода createPieChartPageМетод createPieChartPage вызывает процедуру подготовки данных (createDataPie(name)) при формировании страницы с круговой диаграммой. В разделе заголовка страницы (head) определяются файлы скриптов (Chart.min.js, colors.js), которые необходимо загрузить браузеру при открытии страницы.
private String createPieChartPage()
{
String content = "";
content += "<!DOCTYPE html PUBLIC ";
content += "\"-//W3C//DTD HTML 4.01 Transitional//EN\" ";
content += "\"http://www.w3.org/TR/html4/loose.dtd\"> " ;
content += "<html>";
content += "<head>";
content += "<title>Pie Chart (chart.js)</title>";
content += "<meta charset=\"UTF-8\">";
content += "<script src=\"js/Chart.min.js\"></script>";
content += "<script src=\"js/colors.js\"></script>";
content += createDataPie("pie.js");
content += "</head>";
content += "<body>";
content += createCanvasDesc();
content += "<script>";
content += "window.onload = function() {"
+ createCanvasContext()
+ "window.pie = new Chart(ctx, config);"
+ "};";
content += "</script>";
content += "<P />";
content += "<FORM ACTION=\"chartserver\" METHOD=\"GET\">";
content += "<INPUT TYPE=\"submit\" VALUE=\"Назад\">";
content += "</FORM>";
content += "</body>";
content += "</html>";
return content;
}
Интерфейс страницы с изображением круговой диаграммы представлен на следующем скриншоте. В URL страницы включен вызов сервлета с параметром «/chartserver?chart=pie».
Всплывающая подсказка выводится по умолчанию при наведении курсора мыши на одну из секций диаграммы. Листинг данныхВ файле данных pie.js определена функция генерирования значения randomScalingFactor и объект конфигурации диаграммы config, включающий тип диаграммы и набор данных, содержащий массив data из пяти значений. Для каждого значения определен цвет backgroundColor. В массиве labels определены метки секций диаграммы. В качестве опций диаграммы (options) определено нижнее размещение легенды (legend) и перерисовка диаграммы при изменении размера контейнера (responsive).
randomScalingFactor = function()
{
return Math.round(Math.random() * 100);
};
var config = {
type: 'pie',
data: {
datasets: [{
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
],
backgroundColor: [
chartColors.red,
chartColors.orange,
chartColors.yellow,
chartColors.green,
chartColors.blue,
]
}],
labels: [
"Red",
"Orange",
"Yellow",
"Green",
"Blue"
]
},
options: {
responsive: true,
legend: {
position: 'bottom',
}
}
};
Листинг метода createLineChartPageМетод createLineChartPage вызывает процедуру подготовки данных (createDataLine(name)) при формировании страницы с линейными графиками. В разделе заголовка страницы (head) определяются файлы скриптов (Chart.min.js, colors.js), которые браузер загружает при открытии страницы.
private String createLineChartPage() {
String content = "";
content += "<!DOCTYPE html PUBLIC ";
content += "\"-//W3C//DTD HTML 4.01 Transitional//EN\" ";
content += "\"http://www.w3.org/TR/html4/loose.dtd\">";
content += "<html>";
content += "<head>";
content += "<title>Pie Chart (chart.js)</title>";
content += "<meta charset=\"UTF-8\">";
content += "<script src=\"js/Chart.min.js\"></script>";
content += "<script src=\"js/colors.js\"></script>";
content += createDataLine("line.js");
content += "</head>";
content += "<body>";
content += createCanvasDesc();
content += "<script>";
content += "window.onload = function() {"
+ createCanvasContext()
+ "window.line = new Chart(ctx, config);"
+ "};";
content += "</script>";
content += "<P />";
content += "<FORM ACTION=\"chartserver\" METHOD=\"GET\">";
content += "<INPUT TYPE=\"submit\" VALUE=\"Назад\">";
content += "</FORM>";
content += "</body>";
content += "</html>";
return content;
}
Интерфейс страницы с изображением линейных графиков представлен на следующем скриншоте. В URL страницы включен вызов сервлета с параметром «/chartserver?chart=line».
Всплывающая подсказка выводится по умолчанию для ближайших к курсору значений. Это определено параметрами опции <hover> (см. листинг данных). Листинг данныхВ файле данных line.js определена функция генерирования значения randomScalingFactor и объект конфигурации диаграммы config, включающий тип диаграммы, массив меток labels, которые размещаются по оси абсцисс, и два набора данных datasets, содержащих массивы data из семи значений. Для каждого набора определен цвет заполнителя backgroundColor и цвет графика borderColor. Поскольку флаг fill в наборах сброшен (false), то области под графиками не закрашиваются. На странице с описанием библиотеки Chart.js приведен пример, где представлен график с установленным флагом fill (true).
randomScalingFactor = function()
{
return Math.round(Math.random() * 100);
};
var config = {
type: 'line',
data: {
labels: ["Январь", "Февраль", "Март",
"Апрель", "Май", "Июнь", "Июль"],
datasets: [{
label: "Dataset1",
fill: false,
backgroundColor: chartColors.red,
borderColor: chartColors.red,
data: [
randomScalingFactor(),
randomScalingFactor(),
. . .
]
}, {
label: "Dataset2",
fill: false,
backgroundColor: chartColors.blue,
borderColor: chartColors.blue,
data: [
randomScalingFactor(),
randomScalingFactor(),
. . .
]
}]
},
options: {
responsive: true,
title:{
display:true,
text:'Line Chart (Chart.js)'
},
legend: {
position: 'bottom',
},
tooltips: {
mode: 'index',
intersect: false,
},
hover: {
mode: 'nearest',
intersect: true
},
scales: {
xAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Месяц'
}
}],
yAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Значение'
}
}]
}
}
};
В качестве опций диаграммы (options) определены перерисовка диаграммы при изменении размера контейнера (responsive), заголовок и нижнее размещение легенды (legend). Опции tooltips и hover определяют вывод подсказки ближайших к курсору значений. В секции <scales> определяются параметры осей абсцисс xAxis и ординат yAxes. На сайте описание наиболее значимых опций настройки диаграммы Chart.js с примерами представлено здесь. Скачать примерИсходный код примера сервлета в виде проекта Eclipse, рассмотренного в тексте страницы, можно скачать здесь (240 Кб). Проект включает библиотеку Chart.js. Проект включает страницу chart.html, рассмотренную в качестве примера при описании графической библиотеки Chart.js. |
