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

1. Огляд

Іноді нам потрібно працювати з графічними програмами на Java без реального дисплея, клавіатури або миші , скажімо, на сервері чи контейнері.

У цьому короткому навчальному посібнику ми дізнаємося про безголовий режим Java для вирішення цього сценарію. Ми також розглянемо, що ми можемо робити в безголовому режимі, а що - ні.

2. Налаштування режиму без голови

Існує багато способів явного налаштування безголового режиму в Java:

  • Програмно встановлюючи системну властивість java.awt.headless на true
  • Використання аргументу командного рядка: java -Djava.awt.headless = true
  • Додавання -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 при використанні в неінтерактивному середовищі:

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.