Cервлет c диаграммами Chart.js

Представление на странице сайта графического изображения, сформированного динамически на основе числовых данных, является важной составляющей любого WEB-проекта. Это делает сайт более презентабельным и привлекательным. На текущей странице будет рассмотрен пример использования в сервлете графической JavaScript библиотеки Chart.js. Отличительной особенностью данной библиотеки является создание линейных графиков, столбцовых, круговых и радиальных диаграмм. Библиотека Chart.js поддерживает использование анимированных эффектов и имеет небольшой размер.

Описание примера

Рассматриваемый пример создания интерактивных диаграмм с использованием сервлета и скриптовой библиотеки Chart.js демонстрирует :

  • динамическое формирование страниц с диаграммами Chart.js с помощью сервлетов;
  • переход на страницы с использованием :
    • метода sendRedirect класса HttpServletResponse - обработка перехода выполняется в браузере с переопределением URL;
    • метода forward класса RequestDispatcher - обработка перехода выполняется в контейнере приложения без изменения адреса URL;
    • динамически создаваемых страниц - «обработка перехода» в сервлете.
  • использование объекта сессии HttpSession для хранения параметра.

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.

  Рейтинг@Mail.ru