Приложение предназначено для управления сервером с графическим интерфейсом.
Все написано с использованием JDK 11. Пользовательский интерфейс построен как веб с Spring Boot 2.x в фоновом режиме. Кроме того, приложение запускается с JavaFX 11 (без каких-либо этапов).
В этот момент приложение запускается как запланировано - веб-часть работает. Путь запроса / admin / screenshot должен позволять администратору делать скриншот рабочего стола всего сервера.
Для этого я создал сервис для снятия скриншотов с помощью javafx.scene.robot. * Когда я создаю объект и вызываю его методы из метода start () в классе, расширяющем javafx.application.Application, все работает. Конечно, робот должен работать в потоке JavaFX.
Чтобы сохранить это условие и позволить Spring получить доступ к сервису, я передал его в контекст Spring через фабрику бинов.
ScreenshotService screenshotService = new ScreenshotService();
springContext.getBeanFactory().registerSingleton("screenshotService", screenshotService);
Теперь в контроллере Spring, используя @Autowired ApplicationContext, я получаю доступ к бину через это имя. Метод с @RequestMapping в / admin / screenshot вызывает метод из сервиса и выдает «java.lang.IllegalStateException» из-за вызова Robot вне потока JavaFX. Тогда bean бесполезен, потому что я должен использовать javafx.application.Platform.runLater () для вызова сервиса и его методов.
Хорошо, на этом уровне снимок экрана можно взять и сохранить как объект класса BufferedImage. Пришло время отправить скриншот пользователю или хотя бы сохранить его в файловой системе.
Я попытался скопировать BufferedImage singleScreenshot в ответ HttpServletResponse:
BufferedImage singleScreenshot = screenshotService.takeScreenshot();
ImageIO.write(singleScreenshot, MediaType.IMAGE_JPEG_VALUE, response.getOutputStream());
Но это бросает:
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at org.apache.coyote.http11.Http11OutputBuffer$SocketOutputBuffer.flush(Http11OutputBuffer.java:564)
at org.apache.coyote.http11.filters.ChunkedOutputFilter.flush(ChunkedOutputFilter.java:157)
at org.apache.coyote.http11.Http11OutputBuffer.flush(Http11OutputBuffer.java:217)
at org.apache.coyote.http11.Http11Processor.flush(Http11Processor.java:1150)
at org.apache.coyote.AbstractProcessor.action(AbstractProcessor.java:394)
at org.apache.coyote.Response.action(Response.java:209)
at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:295)
at org.apache.catalina.connector.OutputBuffer.flush(OutputBuffer.java:262)
at org.apache.catalina.connector.CoyoteOutputStream.flush(CoyoteOutputStream.java:118)
at org.springframework.security.web.util.OnCommittedResponseWrapper$SaveContextServletOutputStream.flush(OnCommittedResponseWrapper.java:514)
at org.springframework.security.web.util.OnCommittedResponseWrapper$SaveContextServletOutputStream.flush(OnCommittedResponseWrapper.java:514)
at java.desktop/javax.imageio.stream.FileCacheImageOutputStream.close(FileCacheImageOutputStream.java:238)
at java.desktop/javax.imageio.ImageIO.write(ImageIO.java:1596)
at app.AdminController.lambda$test$0(AdminController.java:57)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:834)
И, наконец, мои последние вопросы.
Почему он умирает? Разве «ответ» не существует в потоке JavaFX (простая печать говорит, что он все еще здесь) или это проблема с «singleScreenshot» (но почему)? Кроме того, я могу сделать это немного лучше?
Пример источника: https://github.com/RaGreen/ScreenshotSpringFx