FreeMarker algemene bewerkingen

1. Inleiding

FreeMarker is een sjabloonengine, geschreven in Java en onderhouden door de Apache Foundation. We kunnen de FreeMarker-sjabloontaal, ook bekend als FTL, gebruiken om veel op tekst gebaseerde indelingen te genereren, zoals webpagina's, e-mail of XML-bestanden.

In deze tutorial zullen we zien wat we out-of-the-box kunnen doen met FreeMarker, maar houd er rekening mee dat het behoorlijk configureerbaar is en zelfs goed integreert met Spring.

Laten we beginnen!

2. Snel overzicht

Om dynamische inhoud in onze pagina's te injecteren, moeten we gebruik een syntaxis die FreeMarker begrijpt:

  • ${…} in de sjabloon wordt in de gegenereerde uitvoer vervangen door de werkelijke waarde van de uitdrukking tussen de accolades - we noemen dit interpolatie - een paar voorbeelden zijn ${1 + 2} en $ {variableName}
  • FTL-tags zijn als HTML-tags (maar bevatten # of @) en FreeMarker interpreteert ze bijvoorbeeld
  • Opmerkingen in FreeMarker beginnen met <#– en eindigen met –>

3. De include-tag

De FTL omvatten richtlijn is voor ons een manier om het DRY-principe in onze applicatie te volgen. We zullen de repetitieve inhoud in een bestand definiëren en deze hergebruiken in verschillende FreeMarker-sjablonen met single omvatten label.

Een voorbeeld van zo'n use case is wanneer we het menugedeelte op veel pagina's willen opnemen. Eerst definiëren we het menugedeelte in een bestand - we noemen het menu.ftl - met de volgende inhoud:

Dashboard Nieuw eindpunt toevoegen

En laten we op onze HTML-pagina de gemaakte menu.ftl:

Dashboardpagina

En we kunnen ook FTL in onze fragmenten opnemen, wat geweldig is.

4. Omgaan met het bestaan ​​van waarde

FTL zal elk overwegen nul waarde als een ontbrekende waarde. We moeten dus extra voorzichtig zijn en logica toevoegen om te verwerken nulbinnen onze sjabloon.

We kunnen de ?? operator om te controleren of een attribuut of geneste eigenschap bestaat. Het resultaat is een booleaanse waarde:

$ {kenmerk ??}

Daarom hebben we het kenmerk getest op nul, maar dat is niet altijd genoeg. Laten we nu een standaardwaarde definiëren als reserve voor deze ontbrekende waarde. Hiervoor hebben we de ! operator geplaatst achter de naam van de variabele:

$ {attribuut! 'standaardwaarde'}

Door ronde haakjes te gebruiken, kunnen we veel geneste attributen omwikkelen.

Om bijvoorbeeld te controleren of het attribuut bestaat en een geneste eigenschap heeft met een andere geneste eigenschap, verpakken we alles:

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

Tot slot, door alles samen te voegen, kunnen we deze insluiten in statische inhoud:

Testen of student eigendom bestaat: $ {student ??? c}

Standaardwaarde gebruiken voor ontbrekende leerling: $ {student! 'John Doe'}

Geneste eigenschappen van studenten verpakken: $ {(student.address.street) ??? c}

En als het leerling waren nulzouden we zien:

Testen is de eigenschap van de student bestaat: false

Standaardwaarde gebruiken voor ontbrekende leerling: John Doe

Geneste eigenschappen van student omwikkelen: false

Let alstublieft op de aanvullende ? c richtlijn gebruikt na de ??. We hebben het gedaan om de booleaanse waarde om te zetten in een door mensen leesbare tekenreeks.

5. De If-Else-tag

Controlestructuren zijn aanwezig in FreeMarker en de traditionele if-else is waarschijnlijk bekend:

Terwijl de elseif en anders branches zijn optioneel, de voorwaarden moeten worden omgezet in een booleaanse waarde.

Om ons te helpen met onze evaluaties, zullen we waarschijnlijk een van de volgende gebruiken:

  • x == y controleren is X is gelijk aan y
  • x! = y terugbrengen waar alleen als X is anders dan y
  • x lt y betekent dat X moet strikt kleiner zijn dan y - we kunnen ook gebruiken < in plaats van lt
  • x gt y evalueert naar waar alleen als X is strikt groter dan y - we kunnen gebruiken > in plaats van gt
  • x lte y test of X is kleiner dan of gelijk aan y - het alternatief voor lte is <=
  • x gte y test of X is groter dan of gelijk aan y - het alternatief van gte is> =
  • X?? om het bestaan ​​van X
  • reeks? seqContains (x) valideert het bestaan ​​van X binnen een reeks

Het is erg belangrijk om dat in gedachten te houden FreeMarker beschouwt> = en> als afsluitende karakters voor een FTL-tag. De oplossing is om het gebruik ervan tussen haakjes of gebruik gte of gt in plaats daarvan.

Samenstellen voor de volgende sjabloon:

$ {status.reason}

Ontbrekende status!

We eindigen met de resulterende HTML-code:

404 Niet Gevonden

Ontbrekende status!

6. Containers met subvariabelen

In FreeMarker hebben we drie soorten containers voor subvariabelen:

  • Hashes zijn een reeks sleutel-waardeparen - de sleutel moet uniek zijn in de hash en we hebben geen bestelling
  • Opeenvolgingen zijn lijsten waarin we een index hebben die aan elke waarde is gekoppeld - een opmerkelijk feit is dat subvariabelen van verschillende typen kunnen zijn
  • Collecties zijn een speciaal geval van reeksen waarbij we geen toegang hebben tot de grootte of waarden kunnen ophalen via index - we kunnen ze nog steeds herhalen met de lijst tag wel!

6.1. Items herhalen

We kunnen een container op twee basismanieren herhalen. De eerste is waar we elke waarde herhalen en logica voor elk ervan laten gebeuren:

Of, als we een Hash, toegang tot zowel de sleutel als de waarde:

De tweede vorm is krachtiger omdat het ons ook in staat stelt om de logica te definiëren die moet gebeuren bij verschillende stappen in de iteratie:

De item vertegenwoordigt de naam van de lusvariabele, maar we kunnen deze hernoemen naar wat we willen. De anders branch is optioneel.

Voor een praktisch voorbeeld, definieer goed een sjabloon waarin we enkele statussen vermelden:

  • $ {status}

Geen statussen beschikbaar

Dit zal ons de volgende HTML teruggeven wanneer onze container dat is ["200 OK", "404 niet gevonden", "500 interne serverfout"]:

  • 200 OK
  • 404 Niet Gevonden
  • 500 Interne server fout

6.2. Afhandeling van items

Een hash biedt ons twee eenvoudige functies: sleutels om alleen de sleutels op te halen, en waarden om alleen de waarden op te halen.

Een reeks is complexer; we kunnen de meest bruikbare functies groeperen:

  • brok en toetreden om een ​​subreeks te krijgen of om twee reeksen te combineren
  • omgekeerde, soort, en sorteer op voor het wijzigen van de volgorde van elementen
  • eerste en laatste haalt respectievelijk het eerste of het laatste element op
  • grootte vertegenwoordigt het aantal elementen in de reeks
  • seq Bevat, seqIndexOf, of seqLastIndexOf om een ​​element te zoeken

7. Type afhandeling

FreeMarker wordt geleverd met een enorme verscheidenheid aan functies (ingebouwd) die beschikbaar zijn voor het werken met objecten. Laten we eens kijken naar enkele veelgebruikte functies.

7.1. Omgaan met snaren

  • url en urlPath zal URL-ontsnappen aan de string, met de uitzondering dat urlPath zal niet ontsnappen aan slash /
  • jString, jsString, en jsonString past de ontsnappingsregels toe voor respectievelijk Java, Javascript en JSON
  • capFirst, uncapFirst, upperCase, lowerCase en kapitaliseren zijn handig om het hoofdlettergebruik van onze tekenreeks te wijzigen, zoals geïmpliceerd door hun namen
  • boolean, datum, tijd, datum Tijd en aantal zijn functies voor het converteren van een string naar andere typen

Laten we nu een paar van die functies gebruiken:

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

$ {'Using "in text'? JsString}

$ {'mijn waarde? upperCase}

$ {'2019-01-12'? Date ('jjjj-MM-dd')}

En de uitvoer voor de bovenstaande sjabloon zal zijn:

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

MIJN WAARDE

Gebruik \ "in tekst

12.01.2019

Bij gebruik van de datum functie, hebben we ook het patroon doorgegeven dat moet worden gebruikt voor het parseren van het String-object. FreeMarker gebruikt het lokale formaat, tenzij anders aangegeven, bijvoorbeeld in de draad functie beschikbaar voor datumobjecten.

7.2. Nummerafhandeling

  • ronde, verdieping en plafond kan helpen bij het afronden van getallen
  • buikspieren retourneert de absolute waarde van een getal
  • draad converteert het nummer naar een string. We kunnen ook vier vooraf gedefinieerde getalnotaties doorgeven: computer, valuta, aantal, of procent of bepaal ons eigen formaat, zoals [ “0.###” ]

Laten we een reeks wiskundige bewerkingen uitvoeren:

$ {(7,3? Rond + 3,4? Plafond + 0,1234)? String ('0. ##')}

En zoals verwacht is de resulterende waarde 11.12.

7.3. Datumafhandeling

  • .nu vertegenwoordigt de huidige datum-tijd
  • datum, tijd en datum Tijd kan de datum- en tijdsecties van het datum-tijdobject retourneren
  • draad converteert datum-tijden naar strings - we kunnen ook het gewenste formaat doorgeven of een vooraf gedefinieerd formaat gebruiken

We gaan nu de huidige tijd ophalen en de uitvoer formatteren in een tekenreeks die alleen de uren en minuten bevat:

$ {. nu? tijd? string ('HH: mm')}

De resulterende HTML zal zijn:

15:39

8. Afhandeling van uitzonderingen

We zien twee manieren om uitzonderingen af ​​te handelen voor een FreeMarker-sjabloon.

De eerste manier is om te gebruiken poging om te herstellen tags om te definiëren wat we moeten proberen uit te voeren en een codeblok dat moet worden uitgevoerd in geval van een fout.

De syntaxis is:

Beide poging en herstellen tags zijn verplicht. In het geval van een fout, draait het de poging tot blok terug en wordt alleen de code in het herstellen sectie.

Laten we, rekening houdend met deze syntaxis, onze sjabloon definiëren als:

Voorbereiden om te evalueren

Kenmerk is $ {attributeWithPossibleValue ??}

Kenmerk ontbreekt

Klaar met de evaluatie

Wanneer attributeWithPossibleValue ontbreekt, we zullen zien:

Voorbereiden om te evalueren

Kenmerk ontbreekt

Klaar met de evaluatie

En de output wanneer attributeWithPossibleValue bestaat is:

Voorbereiden om te evalueren

Kenmerk is 200 OK

Klaar met de evaluatie

De tweede manier is om FreeMarker te configureren wat er moet gebeuren in het geval van uitzonderingen.

Met Spring Boot configureren we dit eenvoudig via het eigenschappenbestand; hier zijn enkele beschikbare configuraties:

  • spring.freemarker.setting.template_exception_handler = opnieuw gooien gooit de uitzondering opnieuw
  • spring.freemarker.setting.template_exception_handler = foutopsporing voert de stacktrace-informatie uit naar de client en gooit vervolgens de uitzondering opnieuw.
  • spring.freemarker.setting.template_exception_handler = html_debug voert de stacktrace-informatie uit naar de client, formatteert deze zodat deze gewoonlijk goed leesbaar is in de browser en gooit de uitzondering opnieuw.
  • spring.freemarker.setting.template_exception_handler = negeren slaat de mislukte instructies over en laat de sjabloon doorgaan met uitvoeren.
  • spring.freemarker.setting.template_exception_handler = standaard

9. Methoden aanroepen

Soms willen we Java-methoden aanroepen vanuit onze FreeMarker-sjablonen. We zullen nu zien hoe het moet.

9.1. Statische leden

Om toegang te krijgen tot statische leden, kunnen we onze globale FreeMarker-configuratie bijwerken of een S toevoegentaticModels typ attribuut op het model, onder de attribuutnaam statica:

model.addAttribute ("statics", nieuwe DefaultObjectWrapperBuilder (nieuwe versie ("2.3.28")) .build (). getStaticModels ());

Toegang krijgen tot statische elementen is eenvoudig.

Eerst importeren we de statische elementen van onze klasse met behulp van de assign-tag, beslissen vervolgens over een naam en ten slotte het Java-klassenpad.

Hier is hoe we importeren Wiskunde class in onze sjabloon, toon de waarde van de static PI veld en gebruik het static pow methode:

PI-waarde: $ {MathUtils.PI}

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

De resulterende HTML is:

PI-waarde: 3,142

2 * 10 is: 1024

9.2. Bean-leden

Bean-leden zijn heel gemakkelijk toegankelijk: gebruik de punt (.) en dat is het!

Voor ons volgende voorbeeld zullen we een Willekeurig bezwaar tegen ons model:

model.addAttribute ("random", new Random ());

Laten we in onze FreeMarker-sjabloon een willekeurig getal genereren:

Willekeurige waarde: $ {random.nextInt ()}

Dit zal een output veroorzaken die lijkt op:

Willekeurige waarde: 1.329.970.768

9.3. Aangepaste methoden

De eerste stap voor het toevoegen van een aangepaste methode is om een ​​klasse te hebben die FreeMarker's implementeert TemplateMethodModelEx interface en definieert onze logica binnen de exec methode:

public class LastCharMethod implementeert TemplateMethodModelEx {public Object exec (List arguments) gooit TemplateModelException}

We voegen een instantie van onze nieuwe klasse toe als kenmerk aan het model:

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

De volgende stap is om onze nieuwe methode in onze sjabloon te gebruiken:

Voorbeeld van laatste teken: $ {lastChar ('mystring')}

Ten slotte is de resulterende uitvoer:

Voorbeeld laatste teken: g

10. Conclusie

In dit artikel hebben we gezien hoe we de FreeMarker-sjabloonengine binnen ons project kunnen gebruiken. We hebben ons gericht op algemene bewerkingen, het manipuleren van verschillende objecten en een paar meer geavanceerde onderwerpen.

De implementatie van al deze fragmenten is beschikbaar op GitHub.