De Java Headless-modus

1. Overzicht

Af en toe moeten we dat doen werken met grafische applicaties in Java zonder een echt beeldscherm, toetsenbord of muis, laten we zeggen, op een server of een container.

In deze korte tutorial gaan we leren over Java's headless-modus om dit scenario aan te pakken. We zullen ook kijken naar wat we kunnen doen in de headless-modus en wat we niet kunnen.

2. Headless-modus instellen

Er zijn veel manieren waarop we de headless-modus expliciet in Java kunnen instellen:

  • Programmatisch instellen van de systeemeigenschap java.awt.headless naar waar
  • Met behulp van het opdrachtregelargument: java -Djava.awt.headless = waar
  • Toevoegen -Djava.awt.headless = waar naar de JAVA_OPTS omgevingsvariabele in een opstartscript van een server

Als de omgeving werkelijk headless is, zou de JVM daar impliciet van op de hoogte zijn. In sommige scenario's zullen er echter subtiele verschillen zijn. We zullen ze binnenkort zien.

3. Voorbeelden van UI-componenten in Headless-modus

Een typisch gebruik van UI-componenten die in een headless-omgeving worden uitgevoerd, kan een app voor het converteren van afbeeldingen zijn. Hoewel het grafische gegevens nodig heeft voor beeldverwerking, is een beeldscherm niet echt nodig. De app kan op een server worden uitgevoerd en geconverteerde bestanden kunnen worden opgeslagen of via het netwerk naar een andere machine worden gestuurd voor weergave.

Laten we dit in actie zien.

Eerst zetten we de headless-modus programmatisch aan in een JUnit klasse:

@Before public void setUpHeadlessMode () {System.setProperty ("java.awt.headless", "true"); } 

Om ervoor te zorgen dat het correct is ingesteld, kunnen we gebruiken java.awt.GraphicsEnvironment#isHeadless:

@Test openbare leegte whenSetUpSuccessful_thenHeadlessIsTrue () {assertThat (GraphicsEnvironment.isHeadless ()). IsTrue (); } 

We moeten in gedachten houden dat de bovenstaande test zal slagen in een headless-omgeving, zelfs als de modus niet expliciet is ingeschakeld.

Laten we nu eens kijken naar onze eenvoudige afbeeldingsconverter:

@Test openbare leegte whenHeadlessMode_thenImagesWork () {booleaans resultaat = false; probeer (InputStream inStream = HeadlessModeUnitTest.class.getResourceAsStream (IN_FILE); FileOutputStream outStream = nieuwe FileOutputStream (OUT_FILE)) {BufferedImage inputImage = ImageIO.read (inStream); result = ImageIO.write (inputImage, FORMAT, outStream); } assertThat (resultaat) .isTrue (); }

In dit volgende voorbeeld kunnen we zien dat informatie van alle lettertypen, inclusief lettertypestatistieken, ook voor ons beschikbaar is:

@Test openbare leegte whenHeadless_thenFontsWork () {GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment (); Tekenreekslettertypen [] = ge.getAvailableFontFamilyNames (); assertThat (lettertypen) .isNotEmpty (); Font font = nieuw font (fonts [0], Font.BOLD, 14); FontMetrics fm = (nieuw Canvas ()). GetFontMetrics (lettertype); assertThat (fm.getHeight ()). isGreaterThan (0); assertThat (fm.getAscent ()). isGreaterThan (0); assertThat (fm.getDescent ()). isGreaterThan (0); }

4. HeadlessException

Er zijn componenten die randapparatuur vereisen en die niet werken in de headless-modus. Ze gooien een HeadlessException bij gebruik in een niet-interactieve omgeving:

Uitzondering in thread "main" java.awt.HeadlessException op java.awt.GraphicsEnvironment.checkHeadless (GraphicsEnvironment.java:204) op java.awt.Window. (Window.java:536) op java.awt.Frame. (Frame. Java: 420)

Deze test beweert dat het gebruik van Kader in een headless-modus zal inderdaad een HeadlessException:

@Test openbare leegte whenHeadlessmode_thenFrameThrowsHeadlessException () {assertThatExceptionOfType (HeadlessException.class) .isThrownBy (() -> {Frame frame = nieuw frame (); frame.setVisible (true); frame.setSize (120, 120);}); } 

Houd er als vuistregel rekening mee dat componenten van het hoogste niveau, zoals Kader en Knop hebben altijd een interactieve omgeving nodig en zullen deze uitzondering veroorzaken. Echter, het zal worden geworpen als een onherstelbaar Fout als de headless-modus niet expliciet is ingesteld.

5. Omzeilen van zware componenten in headless-modus

Op dit punt stellen we ons misschien een vraag - maar wat als we code met GUI-componenten hebben die op beide soorten omgevingen kunnen worden uitgevoerd - een productiemachine met kop en een server voor broncodeanalyse zonder kop?

In de bovenstaande voorbeelden hebben we gezien dat de zwaargewicht componenten niet werken op de server en een uitzondering zullen genereren.

We kunnen dus een voorwaardelijke benadering gebruiken:

public void FlexibleApp () {if (GraphicsEnvironment.isHeadless ()) {System.out.println ("Hallo wereld"); } anders {JOptionPane.showMessageDialog (null, "Hallo wereld"); }}

Met dit patroon kunnen we een flexibele app maken die zijn gedrag aanpast aan de omgeving.

6. Conclusie

Met verschillende codevoorbeelden zagen we het hoe en waarom van de headless-modus in java. Dit technische artikel biedt een volledige lijst van wat er allemaal kan worden gedaan terwijl u in de headless-modus werkt.

Zoals gewoonlijk is de broncode voor de bovenstaande voorbeelden beschikbaar op GitHub.


$config[zx-auto] not found$config[zx-overlay] not found