«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
Есть компоненты, которые требуют периферийных устройств и не будут работать в автономном режиме. Они вызывают исключение HeadlessException при использовании в неинтерактивной среде:
Exception in thread "main" java.awt.HeadlessException
at java.awt.GraphicsEnvironment.checkHeadless(GraphicsEnvironment.java:204)
at java.awt.Window.<init>(Window.java:536)
at java.awt.Frame.<init>(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);
});
}
Как правило, помните, что вверх Компоненты уровня, такие как рамка и кнопка, всегда нуждаются в интерактивной среде и будут вызывать это исключение. Однако это будет выдано как неисправимая ошибка, если безголовый режим не установлен явно.
5. Обход тяжеловесных компонентов в безголовом режиме
В этот момент мы могли бы задать себе вопрос: а что, если у нас есть код с компонентами графического интерфейса для запуска в обоих типах сред? производственная машина и безголовый сервер анализа исходного кода?
В приведенных выше примерах мы видели, что тяжеловесные компоненты не будут работать на сервере и вызовут исключение.
Итак, мы можем использовать условный подход:
public void FlexibleApp() {
if (GraphicsEnvironment.isHeadless()) {
System.out.println("Hello World");
} else {
JOptionPane.showMessageDialog(null, "Hello World");
}
}
Используя этот шаблон, мы можем создать гибкое приложение, которое настраивает свое поведение в зависимости от среды.
6. Заключение
На разных примерах кода мы увидели, как и почему безголовый режим в java. В этой технической статье представлен полный список того, что можно делать при работе в автономном режиме.
Как обычно, исходный код приведенных выше примеров доступен на GitHub.