Рубрики
Без рубрики

Безголовый режим Java

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

Автор оригинала: 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 .