FreeMarker almindelige operationer

1. Introduktion

FreeMarker er en skabelonmotor, skrevet i Java og vedligeholdt af Apache Foundation. Vi kan bruge FreeMarker Template Language, også kendt som FTL, til at generere mange tekstbaserede formater som websider, e-mail eller XML-filer.

I denne vejledning ser vi, hvad vi kan gøre out-of-the-box med FreeMarker, men bemærk, at det er ret konfigurerbart og endda integreres pænt med Spring.

Lad os komme igang!

2. Hurtig oversigt

For at indsprøjte dynamisk indhold på vores sider skal vi brug en syntaks, som FreeMarker forstår:

  • ${…} i skabelonen vil blive erstattet i den genererede output med den aktuelle værdi af udtrykket inden for de krøllede parenteser - vi kalder det interpolation - et par eksempler er ${1 + 2} og $ {variableName}
  • FTL-tags er som HTML-tags (men indeholder # eller @) og FreeMarker fortolker dem f.eks
  • Kommentarer i FreeMarker starter med <#– og slut med –>

3. Inkluder tag

FTL omfatte direktivet er en måde for os at følge DRY-princippet i vores anvendelse. Vi definerer det gentagne indhold i en fil og genbruger det på tværs af forskellige FreeMarker-skabeloner med en enkelt omfatte tag.

En sådan brugssag er, når vi vil inkludere menusektionen på mange sider. Først definerer vi menusektionen inde i en fil - vi kalder den menu.ftl - med følgende indhold:

Dashboard Tilføj nyt slutpunkt

Og lad os medtage det oprettede på vores HTML-side menu.ftl:

Dashboard-side

Og vi kan også inkludere FTL i vores fragmenter, hvilket er fantastisk.

4. Håndtering af værdieksistens

FTL vil overveje noget nul værdi som en manglende værdi. Derfor skal vi være ekstra forsigtige og tilføj logik til håndtering nulinde i vores skabelon.

Vi kan bruge ?? operatør for at kontrollere, om der findes en attribut eller en indlejret ejendom. Resultatet er en boolsk:

$ {attribut ??}

Så vi har testet attributten for nul, men det er ikke altid nok. Lad os nu definere en standardværdi som en reserve for denne manglende værdi. For at gøre dette har vi brug for ! operatør placeret efter navnet på variablen:

$ {attribut! 'standardværdi'}

Ved hjælp af runde parenteser kan vi pakke mange indlejrede attributter.

For at kontrollere, om attributten eksisterer og har en indlejret ejendom med en anden indlejret ejendom, pakker vi alt sammen:

$ {(attribut.nestedProperty.nestedProperty) ??}

Endelig, når vi sætter alt sammen, kan vi integrere disse blandt statisk indhold:

Testning er, at studerendes ejendom findes: $ {student ??? c}

Brug af standardværdien for manglende elev: $ {student! 'John Doe'}

Indpakning af studerendes indlejrede egenskaber: $ {(student.address.street) ??? c}

Og hvis den studerende var nul, ville vi se:

Testning er studerendes ejendom: falsk

Brug af standardværdi for manglende elev: John Doe

Indpakning af studerendes indlejrede egenskaber: falsk

Bemærk venligst det ekstra ? c direktiv anvendt efter ??. Vi gjorde det for at konvertere den boolske værdi til en menneskelig læsbar streng.

5. If-Else-mærket

Kontrolstrukturer er til stede i FreeMarker, og den traditionelle if-else er sandsynligvis kendt:

Mens elseif og andet filialer er valgfri, skal betingelserne løses til en boolsk værdi.

For at hjælpe os med vores evalueringer bruger vi sandsynligvis en af:

  • x == y at kontrollere er x er lig med y
  • x! = y at vende tilbage rigtigt kun hvis x adskiller sig fra y
  • x lt y betyder at x skal være strengt mindre end y - vi kan også bruge < i stedet for lt
  • x gt y evaluerer til rigtigt kun hvis x er strengt større end y - vi kan bruge > i stedet for gt
  • x lte y test hvis x er mindre end eller lig med y - alternativet til lte er <=
  • x gte y test hvis x er større end eller lig med y - alternativet til gte er> =
  • x?? for at kontrollere eksistensen af x
  • sekvens? seq Indeholder (x) validerer eksistensen af x inde i en sekvens

Det er meget vigtigt at huske på det FreeMarker betragter> = og> som afsluttende tegn for et FTL-tag. Løsningen er at pakke deres anvendelse i parentes eller brug gte eller gt i stedet.

Sætter det sammen til følgende skabelon:

$ {status.reason}

Manglende status!

Vi ender med den resulterende HTML-kode:

404 Ikke fundet

Manglende status!

6. Beholdere af undervariabler

I FreeMarker har vi tre typer containere til undervariabler:

  • Hashes er en sekvens af nøgleværdipar - nøglen skal være unik inde i hashen, og vi har ikke en ordre
  • Sekvenser er lister, hvor vi har et indeks tilknyttet hver værdi - en bemærkelsesværdig kendsgerning er, at undervariabler kan være af forskellige typer
  • Samlinger er et specielt tilfælde af sekvenser, hvor vi ikke kan få adgang til størrelsen eller hente værdier efter indeks - vi kan stadig gentage dem med liste tag dog!

6.1. Itererende genstande

Vi kan gentage over en container på to grundlæggende måder. Den første er hvor vi gentager hver værdi og får logik til at ske for hver af dem:

Eller når vi vil gentage en Hash, adgang til både nøglen og værdien:

Den anden form er mere kraftfuld, fordi den også giver os mulighed for at definere den logik, der skal ske i forskellige trin i iterationen:

Det vare repræsenterer navnet på den loopede variabel, men vi kan omdøbe den til det, vi ønsker. Det andet gren er valgfri.

For et praktisk eksempel skal du definere en skabelon, hvor vi viser nogle statusser:

  • $ {status}

Ingen status tilgængelige

Dette giver os følgende HTML, når vores container er [“200 OK”, “404 ikke fundet”, “500 intern serverfejl”]:

  • 200 OK
  • 404 Ikke fundet
  • 500 intern serverfejl

6.2. Varebehandling

En hash giver os to enkle funktioner: nøgler for kun at hente de nøgler, der findes, og værdier for kun at hente værdierne.

En sekvens er mere kompleks; vi kan gruppere de mest nyttige funktioner:

  • luns og tilslutte for at få en undersekvens eller kombinere to sekvenser
  • baglæns, sortere, og Sorter efter til ændring af rækkefølgen af ​​elementer
  • først og sidst henter henholdsvis det første eller sidste element
  • størrelse repræsenterer antallet af elementer i sekvensen
  • sek. Indeholder, seqIndexOf, eller seqLastIndexOf at kigge efter et element

7. Skriv håndtering

FreeMarker leveres med et stort udvalg af funktioner (indbyggede) til rådighed til arbejde med objekter. Lad os se nogle ofte anvendte funktioner.

7.1. Strenghåndtering

  • url og urlPath vil URL-slippe strengen med undtagelse af, at urlPath undgår ikke skråstreg /
  • jString, jsString, og jsonString vil anvende de undslippende regler for henholdsvis Java, Javascript og JSON
  • capFirst, uncapFirst, store bogstaver, små bogstaver og kapitalisere er nyttige til at ændre tilfældet med vores streng som antydet af deres navne
  • boolsk, dato, tid, dato tid og nummer er funktioner til konvertering fra en streng til andre typer

Lad os nu bruge et par af disse funktioner:

$ {'// myurl.com/?search=Hello World'? urlPath}

$ {'Brug "i tekst'? JsString}

$ {'min værdi? upperCase}

$ {'2019-01-12'? Dato ('åååå-MM-dd')}

Og output for skabelonen ovenfor vil være:

http% 3A // myurl.com /% 3Fsearch% 3DHello% 20World

MIN VÆRDI

Brug \ "i tekst

12.01.2019

Når du bruger dato funktion, har vi også passeret det mønster, der skal bruges til at analysere strengobjektet. FreeMarker bruger det lokale format, medmindre andet er angivet, for eksempel i snor funktion tilgængelig for datoobjekter.

7.2. Nummerhåndtering

  • rund, etage og loft kan hjælpe med afrunding af numre
  • abs returnerer et tals absolutte værdi
  • snor konverterer tallet til en streng. Vi kan også videregive fire foruddefinerede nummerformater: computer, betalingsmiddel, nummer, eller procent eller definer vores eget format, ligesom [ “0.###” ]

Lad os lave en kæde med et par matematiske operationer:

$ {(7.3? Runde + 3.4? Loft + 0.1234)? Streng ('0. ##')}

Og som forventet er den resulterende værdi 11.12.

7.3. Datahåndtering

  • .nu repræsenterer den aktuelle dato-tid
  • dato, tid og dato tid kan returnere dato og klokkeslæt for objektet dato-klokkeslæt
  • snor konverterer dato-tidspunkter til strenge - vi kan også videregive det ønskede format eller bruge et foruddefineret format

Vi skal nu få det aktuelle tidspunkt og formatere output til en streng, der kun indeholder timer og minutter:

$ {. nu? tid? streng ('HH: mm')}

Den resulterende HTML vil være:

15:39

8. Undtagelse Håndtering

Vi ser to måder at håndtere undtagelser for en FreeMarker-skabelon på.

Den første måde er at bruge forsøg at genoprette tags til at definere, hvad vi skal prøve at udføre, og en blok kode, der skal udføres i tilfælde af fejl.

Syntaksen er:

Begge forsøg og gendanne tags er obligatoriske. I tilfælde af en fejl ruller den forsøgsblokken tilbage og udfører kun koden i gendanne afsnit.

Når vi holder denne syntaks i tankerne, skal vi definere vores skabelon som:

Forbereder sig på at evaluere

Attribut er $ {attributeWithPossibleValue ??}

Attribut mangler

Færdig med evalueringen

Hvornår attributWithPossibleValue mangler, vi ser:

Forbereder sig på at evaluere

Attribut mangler

Færdig med evalueringen

Og output når attributWithPossibleValue eksisterer er:

Forbereder sig på at evaluere

Attributten er 200 OK

Færdig med evalueringen

Den anden måde er at konfigurere FreeMarker, hvad der skal ske i tilfælde af undtagelser.

Med Spring Boot konfigurerer vi dette let via egenskabsfilen; her er nogle tilgængelige konfigurationer:

  • spring.freemarker.setting.template_exception_handler = retrow genkaster undtagelsen
  • spring.freemarker.setting.template_exception_handler = fejlretning sender staksporingsoplysninger til klienten og kaster derefter undtagelsen igen.
  • spring.freemarker.setting.template_exception_handler = html_debug udsender stack-sporingsoplysningerne til klienten, formaterer den, så den normalt er letlæselig i browseren, og kaster derefter undtagelsen igen.
  • spring.freemarker.setting.template_exception_handler = ignorere springer de manglende instruktioner over og lader skabelonen fortsætte med at udføre.
  • spring.freemarker.setting.template_exception_handler = standard

9. Opkaldsmetoder

Nogle gange vil vi kalde Java-metoder fra vores FreeMarker-skabeloner. Vi ser nu, hvordan man gør det.

9.1. Statiske medlemmer

For at begynde at få adgang til statiske medlemmer kan vi enten opdatere vores globale FreeMarker-konfiguration eller tilføje en StaticModels skriv attribut på modellen under attributnavnet statik:

model.addAttribute ("statics", ny DefaultObjectWrapperBuilder (ny version ("2.3.28")) .build (). getStaticModels ());

Adgang til statiske elementer er ligetil.

Først importerer vi de statiske elementer i vores klasse ved hjælp af tildelingsmærket og beslutter derefter et navn og endelig Java-klassestien.

Sådan importerer vi Matematik klasse i vores skabelon, viser værdien af ​​det statiske PI felt, og brug det statiske pow metode:

PI-værdi: $ {MathUtils.PI}

2 * 10 er: $ {MathUtils.pow (2, 10)}

Den resulterende HTML er:

PI-værdi: 3.142

2 * 10 er: 1.024

9.2. Bønnemedlemmer

Bønnemedlemmer er meget nemme at få adgang til: brug prikken (.) og det er det!

Til vores næste eksempel vil vi tilføje en Tilfældig modsætter sig vores model:

model.addAttribute ("tilfældig", ny Random ());

Lad os generere et tilfældigt tal i vores FreeMarker-skabelon:

Tilfældig værdi: $ {random.nextInt ()}

Dette vil medføre output svarende til:

Tilfældig værdi: 1.329.970.768

9.3. Brugerdefinerede metoder

Det første trin til tilføjelse af en brugerdefineret metode er at have en klasse, der implementerer FreeMarker's TemplateMethodModelEx interface og definerer vores logik inde i udføre metode:

offentlig klasse LastCharMethod implementerer TemplateMethodModelEx {public Object exec (Liste argumenter) kaster TemplateModelException}

Vi tilføjer en forekomst af vores nye klasse som attribut på modellen:

model.addAttribute ("lastChar", ny LastCharMethod ());

Det næste trin er at bruge vores nye metode i vores skabelon:

Sidste char-eksempel: $ {lastChar ('mystring')}

Endelig er den resulterende output:

Sidste char-eksempel: g

10. Konklusion

I denne artikel har vi set, hvordan vi bruger FreeMarker-skabelonmotoren i vores projekt. Vi har fokuseret på almindelige operationer, hvordan man manipulerer forskellige objekter og et par mere avancerede emner.

Implementeringen af ​​alle disse uddrag er tilgængelig på GitHub.