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. Er zijn veel manieren waarop we de headless-modus expliciet in Java kunnen instellen: 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. 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: Om ervoor te zorgen dat het correct is ingesteld, kunnen we gebruiken java.awt.GraphicsEnvironment#isHeadless: 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: In dit volgende voorbeeld kunnen we zien dat informatie van alle lettertypen, inclusief lettertypestatistieken, ook voor ons beschikbaar is: 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: Deze test beweert dat het gebruik van Kader in een headless-modus zal inderdaad een HeadlessException: 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. 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: Met dit patroon kunnen we een flexibele app maken die zijn gedrag aanpast aan de omgeving. 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.2. Headless-modus instellen
3. Voorbeelden van UI-componenten in Headless-modus
@Before public void setUpHeadlessMode () {System.setProperty ("java.awt.headless", "true"); }
@Test openbare leegte whenSetUpSuccessful_thenHeadlessIsTrue () {assertThat (GraphicsEnvironment.isHeadless ()). IsTrue (); }
@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 (); }
@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
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)
@Test openbare leegte whenHeadlessmode_thenFrameThrowsHeadlessException () {assertThatExceptionOfType (HeadlessException.class) .isThrownBy (() -> {Frame frame = nieuw frame (); frame.setVisible (true); frame.setSize (120, 120);}); }
5. Omzeilen van zware componenten in headless-modus
public void FlexibleApp () {if (GraphicsEnvironment.isHeadless ()) {System.out.println ("Hallo wereld"); } anders {JOptionPane.showMessageDialog (null, "Hallo wereld"); }}
6. Conclusie