Автор оригинала: Sampada Wagde.
1. Обзор
Иногда нам нужно работать с графическими приложениями на Java без реального дисплея, клавиатуры или мыши , скажем, на сервере или контейнере.
В этом коротком уроке мы узнаем о безголовом режиме Java для решения этого сценария. Мы также рассмотрим, что мы можем делать в безголовом режиме, а что нет.
2. Настройка безголового режима
Есть много способов явно настроить безголовый режим в Java:
- Программно установив системное свойство java.awt.headless в true
- Использование аргумента командной строки: java
- Добавление -Djava.awt.headless=true в переменную среды JAVA_OPTS в сценарии запуска сервера
Если среда на самом деле безголовая, JVM будет знать об этом неявно. Однако в некоторых сценариях будут небольшие различия. Мы скоро их увидим.
3. Примеры компонентов пользовательского интерфейса в безголовом режиме
Типичным примером использования компонентов пользовательского интерфейса, работающих в безголовой среде, может быть приложение для преобразования изображений. Хотя для обработки изображений ему нужны графические данные, дисплей на самом деле не нужен. Приложение может быть запущено на сервере и преобразовано в файлы, сохраненные или отправленные по сети на другую машину для отображения.
Давайте посмотрим на это в действии.
Во-первых, мы включим безголовый режим программно в классе JUnit :
@Before public void setUpHeadlessMode() { System.setProperty("java.awt.headless", "true"); }
Чтобы убедиться, что он настроен правильно, мы можем использовать java.awt.GraphicsEnvironment # |/isHeadless :
@Test public void whenSetUpSuccessful_thenHeadlessIsTrue() { assertThat(GraphicsEnvironment.isHeadless()).isTrue(); }
Мы должны иметь в виду, что приведенный выше тест будет успешным в безголовой среде, даже если режим явно не включен.
Теперь давайте посмотрим на наш простой конвертер изображений:
@Test public void whenHeadlessMode_thenImagesWork() { boolean result = false; try (InputStream inStream = HeadlessModeUnitTest.class.getResourceAsStream(IN_FILE); FileOutputStream outStream = new FileOutputStream(OUT_FILE)) { BufferedImage inputImage = ImageIO.read(inStream); result = ImageIO.write(inputImage, FORMAT, outStream); } assertThat(result).isTrue(); }
В следующем примере мы видим, что нам также доступна информация обо всех шрифтах, включая метрики шрифтов:
@Test public void whenHeadless_thenFontsWork() { GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); String fonts[] = ge.getAvailableFontFamilyNames(); assertThat(fonts).isNotEmpty(); Font font = new Font(fonts[0], Font.BOLD, 14); FontMetrics fm = (new Canvas()).getFontMetrics(font); assertThat(fm.getHeight()).isGreaterThan(0); assertThat(fm.getAscent()).isGreaterThan(0); assertThat(fm.getDescent()).isGreaterThan(0); }
4. Исключение HeadlessException
Есть компоненты, которые требуют периферийных устройств и не будут работать в безголовом режиме. Они выбрасывают HeadlessException при использовании в неинтерактивной среде:
Exception in thread "main" java.awt.HeadlessException at java.awt.GraphicsEnvironment.checkHeadless(GraphicsEnvironment.java:204) at java.awt.Window.(Window.java:536) at java.awt.Frame. (Frame.java:420)
Этот тест утверждает, что использование Frame в безголовом режиме действительно вызовет исключение HeadlessException :
@Test public void whenHeadlessmode_thenFrameThrowsHeadlessException() { assertThatExceptionOfType(HeadlessException.class).isThrownBy(() -> { Frame frame = new Frame(); frame.setVisible(true); frame.setSize(120, 120); }); }
Как правило, помните, что компоненты верхнего уровня, такие как Frame и Button , всегда нуждаются в интерактивной среде и будут вызывать это исключение. Однако он будет выдан как неисправимая Ошибка , если безголовый режим явно не задан .
5. Обход тяжеловесных компонентов в Безголовом режиме
В этот момент мы могли бы задать себе вопрос – но что, если у нас есть код с компонентами графического интерфейса для запуска в обоих типах сред – рабочей машине с головкой и сервере анализа исходного кода без головы?
В приведенных выше примерах мы видели, что тяжелые компоненты не будут работать на сервере и вызовут исключение.
Таким образом, мы можем использовать условный подход:
public void FlexibleApp() { if (GraphicsEnvironment.isHeadless()) { System.out.println("Hello World"); } else { JOptionPane.showMessageDialog(null, "Hello World"); } }
Используя этот шаблон, мы можем создать гибкое приложение, которое настраивает свое поведение в соответствии с окружающей средой.
6. Заключение
С помощью различных примеров кода мы увидели, как и почему работает безголовый режим в java. Эта техническая статья содержит полный список того, что можно сделать при работе в безголовом режиме.
Как обычно, исходный код для приведенных выше примеров доступен на GitHub .