Режимът без глава на Java

1. Общ преглед

Понякога трябва да работим с графични приложения в Java без действителен дисплей, клавиатура или мишка , да кажем, на сървър или контейнер.

В този кратък урок ще научим за безглавния режим на Java за справяне с този сценарий. Ще разгледаме и какво можем да правим в режим без глава и какво не.

2. Настройване на режим без глава

Има много начини, по които можем да настроим изрично режим без глава в Java:

  • Програмно задаване на системното свойство java.awt.headless на true
  • Използване на аргумента от командния ред: java -Djava.awt.headless = true
  • Добавяне -Djava.awt.headless = вярно към променливата на средата 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. Заобикаляне на тежки компоненти в режим без глава

В този момент може да си зададем въпрос към себе си - но какво ще стане, ако имаме код с компоненти на GUI, който да работи и в двата типа среди - главна производствена машина и безглавен сървър за анализ на изходния код?

В горните примери видяхме, че тежкотоварните компоненти няма да работят на сървъра и ще създадат изключение.

И така, можем да използваме условен подход:

public void FlexibleApp() { if (GraphicsEnvironment.isHeadless()) { System.out.println("Hello World"); } else { JOptionPane.showMessageDialog(null, "Hello World"); } }

Използвайки този модел, можем да създадем гъвкаво приложение, което да коригира поведението си според средата.

6. Заключение

С различни примерни кодове видяхме как и защо режимът без глава в Java. Тази техническа статия предоставя пълен списък на всичко, което може да се направи, докато се работи в режим без глава.

Както обикновено, изходният код за горните примери е достъпен в GitHub.