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.