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. |