Java Headless Mode

1. Oversikt

Noen ganger må vi jobbe med grafikkbaserte applikasjoner i Java uten en faktisk skjerm, tastatur eller mus, la oss si, på en server eller en container.

I denne korte opplæringen skal vi lære om Java's hodeløse modus for å løse dette scenariet. Vi vil også se på hva vi kan gjøre i hodeløs modus og hva vi ikke kan.

2. Sette opp hodeløs modus

Det er mange måter vi kan konfigurere hodeløs modus i Java eksplisitt:

  • Programmatisk innstilling av systemegenskapen java.awt.headless til ekte
  • Ved hjelp av kommandolinjeargumentet: java -Djava.awt.headless = sant
  • Legger til -Djava.awt.headless = sant til JAVA_OPTS miljøvariabel i et serveroppstartsskript

Hvis miljøet faktisk er hodeløst, ville JVM være klar over det implisitt. Imidlertid vil det være subtile forskjeller i noen scenarier. Vi ser dem snart.

3. Eksempler på UI-komponenter i hodeløs modus

Et typisk bruksområde for UI-komponenter som kjører i et hodeløst miljø, kan være en image converter-app. Selv om det trenger grafikkdata for bildebehandling, er en visning egentlig ikke nødvendig. Appen kan kjøres på en server og konverterte filer lagres eller sendes over nettverket til en annen maskin for visning.

La oss se dette i aksjon.

Først slår vi hodeløs modus på programmatisk i a JUnit klasse:

@Før offentlig ugyldig setUpHeadlessMode () {System.setProperty ("java.awt.headless", "true"); } 

For å sikre at den er riktig konfigurert, kan vi bruke den java.awt.GraphicsEnvironment#er hodeløs:

@Test offentlig ugyldig nårSetUpSuccessful_thenHeadlessIsTrue () {assertThat (GraphicsEnvironment.isHeadless ()). IsTrue (); } 

Vi må huske at testen ovenfor vil lykkes i et hodeløst miljø, selv om modusen ikke er eksplisitt slått på.

La oss nå se vår enkle bildekonverterer:

@Test offentlig ugyldig nårHeadlessMode_thenImagesWork () {boolean result = false; prøv (InputStream inStream = HeadlessModeUnitTest.class.getResourceAsStream (IN_FILE); FileOutputStream outStream = ny FileOutputStream (OUT_FILE)) {BufferedImage inputImage = ImageIO.read (inStream); resultat = ImageIO.write (inputImage, FORMAT, outStream); } assertThat (resultat) .isTrue (); }

I dette neste eksemplet kan vi se at informasjon om alle skriftene, inkludert skriftmålinger, også er tilgjengelig for oss:

@Test offentlig ugyldig nårHeadless_thenFontsWork () {GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment (); Strengskrifter [] = ge.getAvailableFontFamilyNames (); assertThat (fonter) .isNotEmpty (); Font font = new Font (fonter [0], Font.BOLD, 14); FontMetrics fm = (new Canvas ()). GetFontMetrics (font); assertThat (fm.getHeight ()). erGreaterThan (0); assertThat (fm.getAscent ()). erGreaterThan (0); assertThat (fm.getDescent ()). erGreaterThan (0); }

4. Hodeløst unntak

Det er komponenter som krever eksterne enheter og som ikke fungerer i hodeløs modus. De kaster en Hodeløst unntak når det brukes i et ikke-interaktivt miljø:

Unntak i tråden "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)

Denne testen hevder at bruk Ramme i hodeløs modus vil faktisk kaste en Hodeløst unntak:

@Test offentlig ugyldig nårHeadlessmode_thenFrameThrowsHeadlessException () {assertThatExceptionOfType (HeadlessException.class) .isThrownBy (() -> {Frame frame = new Frame (); frame.setVisible (true); frame.setSize (120, 120);}); } 

Husk at komponenter på toppnivå som f.eks Ramme og Knapp trenger alltid et interaktivt miljø og vil kaste dette unntaket. Derimot, det vil bli kastet som en uopprettelig Feil hvis hodeløs modus ikke er angitt eksplisitt.

5. Omgå tungvektskomponenter i hodeløs modus

På dette punktet kan vi stille et spørsmål til oss selv - men hva om vi har kode med GUI-komponenter som skal kjøres på begge typer miljøer - en produksjonsmaskin med hodet og en hodeløs kildekodeanalyseserver?

I eksemplene ovenfor har vi sett at tungvektskomponentene ikke fungerer på serveren og vil kaste et unntak.

Så vi kan bruke en betinget tilnærming:

offentlig ugyldig FlexibleApp () {if (GraphicsEnvironment.isHeadless ()) {System.out.println ("Hello World"); } annet {JOptionPane.showMessageDialog (null, "Hello World"); }}

Ved å bruke dette mønsteret kan vi lage en fleksibel app som justerer oppførselen i henhold til miljøet.

6. Konklusjon

Med forskjellige kodeeksempler så vi hvordan og hvorfor hodeløs modus i java. Denne tekniske artikkelen gir en komplett liste over hva alt kan gjøres mens du opererer i hodeløs modus.

Som vanlig er kildekoden for eksemplene ovenfor tilgjengelig på GitHub.


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