小编典典
因此,经过一些研究,我已经使用JavaFX实现了画布绘制,这是一个简化的示例:
首先,我制作了在单独的线程中启动的JavaFX应用程序(我使用Spring taskExecutor,但可以使用普通的Java线程)。
public class ChartGenerator extends Application {
private static Canvas canvas;
private static volatile byte[] result;
public static void initialize(TaskExecutor taskExecutor) {
taskExecutor.execute(new Runnable() {
@Override
public void run() {
launch(ChartGenerator.class);
}
});
}
public static synchronized byte[] generateChart(final Object... params) {
Platform.runLater(new Runnable() {
@Override
public void run() {
ByteArrayOutputStream baos = null;
try {
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
/**
* Do the work with canvas
**/
final SnapshotParameters snapshotParameters = new SnapshotParameters();
snapshotParameters.setFill(Color.TRANSPARENT);
WritableImage image = canvas.snapshot(snapshotParameters, null);
BufferedImage bImage = SwingFXUtils.fromFXImage(image, null);
baos = new ByteArrayOutputStream();
ImageIO.write(bImage, chartType.outputFormat, baos);
result = baos.toByteArray();
} catch (InstantiationException e) {
throw new ChartGenerationException(e);
} catch (IllegalAccessException e) {
throw new ChartGenerationException(e);
} catch (NoSuchMethodException e) {
throw new ChartGenerationException(e);
} catch (InvocationTargetException e) {
throw new ChartGenerationException(e);
} catch (IOException e) {
throw new ChartGenerationException(e);
} finally {
IOUtils.closeQuietly(baos);
}
}
});
while (result == null) {
//wait
}
byte[] ret = result;
result = null;
return ret;
}
@Override
public void start(Stage stage) {
canvas = new Canvas();
}
public static class ChartGenerationException extends RuntimeException {
public ChartGenerationException(String message) {
super(message);
}
public ChartGenerationException(Throwable cause) {
super(cause);
}
}
}
然后,当Spring应用程序启动时,我调用initialize()方法:
@Autowired private TaskExecutor taskExecutor;
@PostConstruct private void initChartGenerator() {
ChartGenerator.initialize(taskExecutor);
}
这种解决方案可以移植到非Spring应用程序中。
这是一个单线程解决方案(在我的情况下就足够了),但我认为可以将其用于多线程用法(也许使用RMI来调用draw方法)。
此解决方案也可以在Windows工作站上“按原样”运行,但在linux服务器环境中,应调用一些其他操作:
您无法在OpenJDK上使用JavaFX(从2013年8月开始)-必须切换到Oracle JDK
Java版本必须不少于Java 7u6
最复杂-您必须使用虚拟显示才能使JavaFX在无头环境中运行:
apt-get安装xvfb
//然后在应用程序服务器上启动:
export DISPLAY =“:99”
start-stop-daemon –start –background –user jetty –exec“ / usr / bin /
sudo”–u jetty / usr / bin / Xvfb:99 -screen 0 1024x768x24
PS您还可以使用此解决方案在服务器端使用其他JavaFX功能(例如,将html导出到图像)。
2020-10-09