使用Java FX在服务器端生成映像

时间:2022-10-21 17:06:14

Currently I'm working on Jax Rs application and I want to output Base64 encoded image to the client. The client is a mobile device.

目前我正在研究Jax Rs应用程序,我想将Base64编码的图像输出到客户端。客户端是移动设备。

The mobile device will call this service with some parameters and the server has to draw a bar chart and send it back to the device as a base64 encoded image string.

移动设备将使用一些参数调用此服务,服务器必须绘制条形图并将其作为base64编码的图像字符串发送回设备。

Since java Fx having the required chart libraries, I did a sample using following tutorial. "snapshot" function also worked correctly as expected (to create a image of the screen).

由于java Fx具有所需的图表库,我使用以下教程做了一个示例。 “快照”功能也按预期正常工作(创建屏幕图像)。

http://docs.oracle.com/javafx/2/charts/bar-chart.htm#CIHJFHDE

Now I want to do this without extending Application class because I need to this within the Jax Rs application. So that I can just use api to create a BuffredImage and then use that for create Base64 string.

现在我想在不扩展Application类的情况下这样做,因为我需要在Jax Rs应用程序中使用它。这样我就可以使用api创建一个BuffredImage然后用它来创建Base64字符串。

I found a way to do this using JFreeChart. But I prefer if I can do this using Java FX. I do not having any previous experience with Java Fx

我找到了一种使用JFreeChart来做到这一点的方法。但我更喜欢我能用Java FX做到这一点。我以前没有使用Java Fx的任何经验

Please advice

1 个解决方案

#1


8  

Server based JavaFX runtime Initialization

基于服务器的JavaFX运行时初始化

To run JavaFX on a server you need to either:

要在服务器上运行JavaFX,您需要:

  1. Launch a JavaFX Application OR
  2. 启动JavaFX应用程序或

  3. Use a JFXPanel.
  4. 使用JFXPanel。

Those are the only ways to get the JavaFX runtime system initialized in JavaFX 2 so that you can use it.

这些是在JavaFX 2中初始化JavaFX运行时系统的唯一方法,以便您可以使用它。

Using a JFXPanel is probably slightly less efficient processing wise than using a JavaFX Application.

与使用JavaFX应用程序相比,使用JFXPanel的处理效率可能略低。

There is further discussion on initialization of the JavaFX system in the * question: JavaFX 2.1: Toolkit not initialized.

在*问题中进一步讨论了JavaFX系统的初始化:JavaFX 2.1:Toolkit未初始化。

JavaFX is a single threaded system

JavaFX是一个单线程系统

You can create most JavaFX components in any thread. However to render components in a scene, you must perform the work on the JavaFX Application thread. This means that if you have a multi-threaded server process, which most servers are, and you want to generate multiple charts, you will need to single thread the chart rendering requests using concurrency constraints.

您可以在任何线程中创建大多数JavaFX组件。但是,要在场景中呈现组件,必须在JavaFX Application线程上执行工作。这意味着如果您有一个多线程服务器进程(大多数服务器都是这样,并且您想要生成多个图表),则需要使用并发约束来单独绘制图表呈现请求。

  1. When you get an incoming request for a chart, issue a Platform.runLater command. All code in the runLater block will be placed in a queue that will eventually run on the JavaFX application thread.
  2. 当您收到图表的传入请求时,请发出Platform.runLater命令。 runLater块中的所有代码都将放在最终将在JavaFX应用程序线程上运行的队列中。

  3. In the runLater block create a scene for your chart and snapshot it to an image. The callback version of snapshot might be the most appropriate one to use here as it likely doesn't tie up the JavaFX Application Thread as much, though it is likely tricker to use.
  4. 在runLater块中,为图表创建一个场景并将其快照到图像。快照的回调版本可能是最适合在这里使用的版本,因为它可能不会像JavaFX应用程序线程那样占用尽可能多,尽管它很可能会被使用。

  5. Convert the JavaFX image to a AWT image using SwingFXUtils.fromFXImage.
  6. 使用SwingFXUtils.fromFXImage将JavaFX图像转换为AWT图像。

  7. To get your image result back in your server handler thread, use the FutureTask technique outlined by sarcan in: Return result from javafx platform runlater.
  8. 要将图像结果返回到服务器处理程序线程中,请使用sarcan概述的FutureTask技术:从javafx platform runlater返回结果。

Your server handler thread can then use ImageIO to convert the AWT image to an output stream in a format like png. You can take the result stream and Base64 encode it and have the server return the base 64 encoded stream in response to the original image request call.

然后,您的服务器处理程序线程可以使用ImageIO将AWT图像转换为输出流,格式为png。您可以获取结果流并对其进行Base64编码,并让服务器返回基本64位编码的流以响应原始图像请求调用。

Ensure graceful shutdown

确保正常关机

You will want to invoke Platform.setImplicitExit(false) when your server starts up and register a shutdown hook or a ServletContextListener that monitors when the servlet is being destroyed, so that you also invoke Platform.exit() to shutdown the JavaFX system. If you don't do this, likely your server won't be able to shut down cleanly because the JavaFX application thread will continue running awaiting work to do.

您需要在服务器启动时调用Platform.setImplicitExit(false)并注册一个关闭钩子或ServletContextListener来监视servlet何时被销毁,以便您还调用Platform.exit()来关闭JavaFX系统。如果您不这样做,可能您的服务器将无法干净地关闭,因为JavaFX应用程序线程将继续运行等待工作。

JavaFX 2.2 is not really certified to run on a headless server

JavaFX 2.2并未真正经过认证,无法在无头服务器上运行

Swing applications can run in headless mode using a system property java.awt.headless. I am not aware of a similar property for JavaFX, though there may one and, if there were, you might find out what it was by asking the openjfx-dev mailing list.

Swing应用程序可以使用系统属性java.awt.headless在无头模式下运行。我不知道JavaFX的类似属性,虽然可能有一个,如果有的话,你可以通过询问openjfx-dev邮件列表找出它是什么。

JavaFX is primarily designed as a client graphics toolkit. While you might get it to work and run satisfactorily for your application on a server, to do so, you may need to ensure that the server is not setup as a headless server and that it has an appropriate graphic accelerator card to provide reasonable performance under load.

JavaFX主要设计为客户端图形工具包。虽然您可能会在服务器上运行并运行令人满意的应用程序,但您可能需要确保服务器未设置为无头服务器并且它具有适当的图形加速卡以提供合理的性能。加载。

You can file a request for official support of a headless mode in the JavaFX issue tracker.

您可以在JavaFX问题跟踪器中提交正式支持无头模式的请求。

#1


8  

Server based JavaFX runtime Initialization

基于服务器的JavaFX运行时初始化

To run JavaFX on a server you need to either:

要在服务器上运行JavaFX,您需要:

  1. Launch a JavaFX Application OR
  2. 启动JavaFX应用程序或

  3. Use a JFXPanel.
  4. 使用JFXPanel。

Those are the only ways to get the JavaFX runtime system initialized in JavaFX 2 so that you can use it.

这些是在JavaFX 2中初始化JavaFX运行时系统的唯一方法,以便您可以使用它。

Using a JFXPanel is probably slightly less efficient processing wise than using a JavaFX Application.

与使用JavaFX应用程序相比,使用JFXPanel的处理效率可能略低。

There is further discussion on initialization of the JavaFX system in the * question: JavaFX 2.1: Toolkit not initialized.

在*问题中进一步讨论了JavaFX系统的初始化:JavaFX 2.1:Toolkit未初始化。

JavaFX is a single threaded system

JavaFX是一个单线程系统

You can create most JavaFX components in any thread. However to render components in a scene, you must perform the work on the JavaFX Application thread. This means that if you have a multi-threaded server process, which most servers are, and you want to generate multiple charts, you will need to single thread the chart rendering requests using concurrency constraints.

您可以在任何线程中创建大多数JavaFX组件。但是,要在场景中呈现组件,必须在JavaFX Application线程上执行工作。这意味着如果您有一个多线程服务器进程(大多数服务器都是这样,并且您想要生成多个图表),则需要使用并发约束来单独绘制图表呈现请求。

  1. When you get an incoming request for a chart, issue a Platform.runLater command. All code in the runLater block will be placed in a queue that will eventually run on the JavaFX application thread.
  2. 当您收到图表的传入请求时,请发出Platform.runLater命令。 runLater块中的所有代码都将放在最终将在JavaFX应用程序线程上运行的队列中。

  3. In the runLater block create a scene for your chart and snapshot it to an image. The callback version of snapshot might be the most appropriate one to use here as it likely doesn't tie up the JavaFX Application Thread as much, though it is likely tricker to use.
  4. 在runLater块中,为图表创建一个场景并将其快照到图像。快照的回调版本可能是最适合在这里使用的版本,因为它可能不会像JavaFX应用程序线程那样占用尽可能多,尽管它很可能会被使用。

  5. Convert the JavaFX image to a AWT image using SwingFXUtils.fromFXImage.
  6. 使用SwingFXUtils.fromFXImage将JavaFX图像转换为AWT图像。

  7. To get your image result back in your server handler thread, use the FutureTask technique outlined by sarcan in: Return result from javafx platform runlater.
  8. 要将图像结果返回到服务器处理程序线程中,请使用sarcan概述的FutureTask技术:从javafx platform runlater返回结果。

Your server handler thread can then use ImageIO to convert the AWT image to an output stream in a format like png. You can take the result stream and Base64 encode it and have the server return the base 64 encoded stream in response to the original image request call.

然后,您的服务器处理程序线程可以使用ImageIO将AWT图像转换为输出流,格式为png。您可以获取结果流并对其进行Base64编码,并让服务器返回基本64位编码的流以响应原始图像请求调用。

Ensure graceful shutdown

确保正常关机

You will want to invoke Platform.setImplicitExit(false) when your server starts up and register a shutdown hook or a ServletContextListener that monitors when the servlet is being destroyed, so that you also invoke Platform.exit() to shutdown the JavaFX system. If you don't do this, likely your server won't be able to shut down cleanly because the JavaFX application thread will continue running awaiting work to do.

您需要在服务器启动时调用Platform.setImplicitExit(false)并注册一个关闭钩子或ServletContextListener来监视servlet何时被销毁,以便您还调用Platform.exit()来关闭JavaFX系统。如果您不这样做,可能您的服务器将无法干净地关闭,因为JavaFX应用程序线程将继续运行等待工作。

JavaFX 2.2 is not really certified to run on a headless server

JavaFX 2.2并未真正经过认证,无法在无头服务器上运行

Swing applications can run in headless mode using a system property java.awt.headless. I am not aware of a similar property for JavaFX, though there may one and, if there were, you might find out what it was by asking the openjfx-dev mailing list.

Swing应用程序可以使用系统属性java.awt.headless在无头模式下运行。我不知道JavaFX的类似属性,虽然可能有一个,如果有的话,你可以通过询问openjfx-dev邮件列表找出它是什么。

JavaFX is primarily designed as a client graphics toolkit. While you might get it to work and run satisfactorily for your application on a server, to do so, you may need to ensure that the server is not setup as a headless server and that it has an appropriate graphic accelerator card to provide reasonable performance under load.

JavaFX主要设计为客户端图形工具包。虽然您可能会在服务器上运行并运行令人满意的应用程序,但您可能需要确保服务器未设置为无头服务器并且它具有适当的图形加速卡以提供合理的性能。加载。

You can file a request for official support of a headless mode in the JavaFX issue tracker.

您可以在JavaFX问题跟踪器中提交正式支持无头模式的请求。