Как я могу отобразить JFreeChart в веб-браузере с Stripes Framework

Это ситуация: моя страница "metrics.jsp" представляет пару переменных, которые необходимы для создания диаграммы. ProjectActionBean.java вызывает несколько других классов Java, которые создают JFreeChart. Я могу отобразить диаграмму во всплывающем окне, но я хочу, чтобы она отображалась в исходном окне браузера.

JFreeChart placeChart = ChartFactory.createBarChart(
                                    "ChartName",
                "",             //x-axis label
                "",             //y-axis label
                dataset,
                PlotOrientation.VERTICAL,
                false,          //legend
                true,           //tooltype
                false);         //generate urls
        ChartFrame frame = new ChartFrame(name, placeChart);
        frame.pack();
        frame.setVisible(true);

3 ответа

Я написал такое заявление, поэтому могу вас заверить, что это выполнимо:)

Во-первых, вам нужно избавиться от всего, что является GUI. У вас просто нет графического интерфейса на сервере. Это означает, что ваш ChartFrame frame сбрасывается. Моя основная процедура создания диаграммы выглядит следующим образом:

  private void createChart(XYPlot plot, String fileName, String caption) throws IOException {
      JFreeChart chart = new JFreeChart(caption, plot);
      chart.addSubtitle(this.subtitle);
      if (plot.getRangeAxis() instanceof LogarithmicAxis) {
         chart.addSubtitle(1, new TextTitle("(logarithmische Skala)"));
      }
      File file = new File(fileName);
      file.delete();
      ChartUtilities.saveChartAsPNG(file, chart, CHART_WIDTH, CHART_HEIGHT);
   }

Это создает файл, который вы можете использовать в качестве <img> с вашей веб-страницы. В качестве альтернативы (но немного более продвинутого) вы можете использовать ChartUtilities для создания потока, который вы можете использовать в ответ на запрос URL-адреса изображения.

Еще одно волшебство, которое требуется, - сообщить Java, что вы запускаете графический код без графического интерфейса. Вам необходимо установить переменную среды

-Djava.awt.headless=true

Для сервера веб-приложений, такого как Tomcat, это входит в сценарий запуска Tomcat.


Обновить

хорошо, да, не 'ChartUtilities.saveChartAsPNG();' просто сохранить график в файловой системе? Я хочу, чтобы пользователь мог вводить переменные, а затем диаграмма отображалась прямо в браузере.

Пока у вас есть только один пользователь, запись изображений в файловую систему будет работать нормально для сценария, который вы описываете. На самом деле, так работала моя первая версия: у меня было 4 <img> теги на моей странице ответа HTML из формы, где пользователь указал параметры; и те указали на имена 4 файлов с моими изображениями. Пока вы заканчиваете писать эти файлы, прежде чем возвращать ответ пользователю, это работает нормально.

Проблемы появляются, когда у вас есть несколько пользователей. Они могут в конечном итоге просматривать графики, указанные другим пользователем. Существуют возможные обходные пути с кодированием идентификатора пользователя или сеанса в именах файлов диаграммы, но это становится ужасно быстро. Существует лучший способ, основанный на динамической генерации каждого изображения по требованию, отдельно.

Я не знаю, как много вы знаете о HTML/HTTP, поэтому я надеюсь, что не буду утомлять вас этим:

Для любого данного HTTP-запроса вы можете вернуть только один поток данных. Как правило, это HTML-страница, то есть поток текста. Если вы хотите изображения на вашей HTML-странице, вы вставляете <img> ссылки с различными URL-адресами на вашу HTML-страницу, и вы все еще просто возвращаете страницу, полную текста. Затем браузер отправляет запросы и запрашивает изображения, запуская запросы для тех URL, которые указаны в <img> теги. Это довольно легко, когда ваши изображения - это просто файлы в файловой системе. Если вам нужны динамически генерируемые изображения, такие как диаграммы, вам нужно придумать URL-адрес для каждого типа изображения, которое вы хотите сгенерировать, и сопоставить каждый из этих URL-адресов с сервлетом, который знает, как генерировать такое изображение.

В моем приложении было 4 разных графика на одной странице, поэтому в моей HTML-странице было 4 <img> теги с 4 различными URL-адресами, которые все сопоставлены с одним и тем же сервлетом, генерирующим диаграммы, но в URL-адресе были некоторые параметры, которые указывали сервлету, какой тип диаграммы нужен. После получения запроса сервлет выполняет магию JFreeChart, а затем использует ChartUtilities.writeChartAsPNG() выгрузить сгенерированное изображение в выходной поток сервлета.

Вам нужно написать сервлет, который записывает изображение (поток байтов) в выходной поток для клиента. Нет необходимости создавать файлы. В принципе что-то вроде этого должно работать:

public class ChartServlet extends HttpServlet {
  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException {

        JFreeChart chart = .. // create your chart
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ChartUtilities.writeChartAsPNG(bos, chart, width, height);

            response.setContentType("image/png");
            OutputStream out = new BufferedOutputStream(response.getOutputStream());
            out.write(bos.toByteArray());
            out.flush();
            out.close();
  }
}

Затем сопоставьте его с некоторым URL-адресом в вашем файле web.xml и используйте тег "img" в HTML/JSP. Очевидно, что вы можете передать ему параметры и т. Д.

Если вы хотите остаться в рамках Stripes, вы можете использовать пользовательское расширение StreamingResolution, таким образом:

Создайте новую нормальную реализацию ActionBean, которая будет представлять URL-адрес вашей диаграммы (будет включен в ваш тег img):

@DefaultHandler
public Resolution view() {
    JFreeChart chart = ...
    return new ChartStreamingResolution(chart);
}

Затем пользовательский StreamingResolution выглядит следующим образом:

public class ChartStreamingResolution extends StreamingResolution {
    private JFreeChart chart;
    public ChartStreamingResolution(JFreeChart chart) {
        super("image/png");
        this.chart = chart;
    }

    @Override
    public void stream(HttpServletResponse response) {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ChartUtilities.writeChartAsPNG(bos, chart, 400, 200);
            OutputStream out = new BufferedOutputStream(response.getOutputStream());
            out.write(bos.toByteArray());
            out.flush();
            out.close();
        } catch (Exception e) {
            //something sensible
        }
    }
}
Другие вопросы по тегам