Template Engine Pebble (Java) - Leitfaden

Dies ist ein Dokument von Pebble, einer Java-Template-Engine mit Twig- oder Django-ähnlicher Syntax. Es scheint, dass Sie es ziemlich anpassen können. Wir werden die grundlegende Verwendung von Pebble erläutern (von der ersten Einführung bis zu fortgeschrittenen Benutzern, die Anpassungen vornehmen möchten). Die Erläuterung der Tags, Filter, Funktionen, Tests und Operatoren, die standardmäßig verwendet werden können, ist in ↓ geschrieben. Template Engine Pebble \ (Java ) \ -Tags, Filter, Funktionen, Tests, Operatoren \ -Qiita

Dieser Artikel wird erstellt, indem die folgenden Dokumente als Übersetzungen und Ergänzungen hinzugefügt werden. http://www.mitchellbosecke.com/pebble/documentation Ich werde keine Verantwortung übernehmen, auch wenn die Beschreibung falsch ist, aber ich würde es begrüßen, wenn Sie es mir sagen könnten.

Installation & Konfiguration

Installation

Da es im Maven Central Repository veröffentlicht wird, müssen Sie nur Folgendes zu pom.xml hinzufügen.

pom.xml


<!-- https://mvnrepository.com/artifact/io.pebbletemplates/pebble -->
<dependency>
    <groupId>io.pebbletemplates</groupId>
    <artifactId>pebble</artifactId>
    <version>2.6.2</version>
</dependency>

Hinweis: Wenn Sie Version 2.4.0 oder niedriger verwenden möchten, scheint groupId anders zu sein.

pom.xml


<!-- https://mvnrepository.com/artifact/com.mitchellbosecke/pebble -->
<dependency>
    <groupId>com.mitchellbosecke</groupId>
    <artifactId>pebble</artifactId>
    <version>2.4.0</version>
</dependency>

#### **`pom.xml`**
```xml


## installieren
 Wenn Sie [hier] in Spring MVC integrieren möchten (in Zusammenarbeit mit #Spring)

 Erste Schritte mit PebbleEngine
 Lassen Sie uns die Vorlage bearbeiten und die Vorlage in Pebble festlegen.
 Dies ist ein Beispiel, das die Vorlage kompiliert und das Ergebnis als Zeichenfolge ausgibt.

```java
PebbleEngine engine = new PebbleEngine.Builder().build();
PebbleTemplate compiledTemplate = engine.getTemplate("templateName");
Writer writer = new StringWriter();

Map<String, Object> context = new HashMap<>();
context.put("name", "Mitchell");

compiledTemplate.evaluate(writer, context);

String output = writer.toString();

Template Loader Mit Pebble Engine können Sie festlegen, wie die Vorlage geladen werden soll. Wenn Sie keinen Loader angeben, werden ClasspathLoader und FileLoader automatisch intern festgelegt.

Bei Verwendung von servletContext


//Geben Sie die Methode zum Laden von Vorlagen mit dem Argument loader an
PebbleEngine engine = new PebbleEngine.Builder()
    .loader(new ServletLoader(servletContext))
    .build();
Loader Erläuterung Standard
ClasspathLoader Suche nach Klassenpfad ON
FileLoader Suche nach Dateipfad ON
ServletLoader Suche aus dem Servlet-Kontext. Dies wird empfohlen, wenn Sie einen Anwendungsserver verwenden. OFF
StringLoader Zum Debuggen. Es funktioniert, indem der Vorlagenname als Vorlageninhalt betrachtet wird. OFF
DelegatingLoader Es wird verwendet, wenn mehrere Loader in der Sammlung angegeben werden. ON

Pebble Engine Settings

Setting Description Default
cache Verwenden Sie Guave, um die Vorlage zwischenzuspeichern. Wenn null gesetzt ist, ist der Cache ungültig und Engine.Kompilieren Sie jedes Mal, wenn Sie getTemplate aufrufen. 200 Vorlagen werden zwischengespeichert
defaultLocale Das Standardgebietsschema, das an jede kompilierte Vorlage übergeben wird. Vorlagen verwenden dieses Gebietsschema für Funktionen wie i18n. Vorlagen können während der Auswertung auch ein eindeutiges Gebietsschema zugewiesen werden. Locale.getDefault()
executorService Wird bei Verwendung des parallelen Tags verwendet. Für Multithreading. null
loader Ich habe es früher erklärt ... Classpath Loader und File Loader sind im Delegating Loader aktiviert.
strictVariables Wenn true festgelegt ist, wird beim Zugriff auf eine nicht vorhandene Variable oder ein nicht vorhandenes Attribut oder beim Versuch, auf das Attribut einer Nullvariablen zuzugreifen, eine Ausnahme ausgelöst. Wenn false, ist die Variable nicht vorhanden, und wenn es sich um ein Attribut handelt, wird sie übersprungen. false

Arbeitet mit dem Frühling

Stichprobe

Ein voll funktionsfähiges Beispielprojekt steht unter github als Referenz zur Verfügung. Wenn Sie ein Projekt erstellen, können Sie es mit mvn installieren und den Ausgabekrieg bereitstellen. Setup Pebble unterstützt 3.x und 4.x, Spring Boot. Sie werden separate Bibliotheken sein. Fügen Sie unten pom.xml hinzu. Dadurch werden die erforderlichen ViewResolver- und View-Klassen bereitgestellt.

pom.xml


<dependency>
	<groupId>com.mitchellbosecke</groupId>
	<artifactId>pebble-spring{version}</artifactId>
	<version>${pebble.version}</version>
</dependency>

Für Spring Boot

pom.xml


<!-- https://mvnrepository.com/artifact/com.mitchellbosecke/pebble-spring-boot-starter -->
<dependency>
    <groupId>com.mitchellbosecke</groupId>
    <artifactId>pebble-spring-boot-starter</artifactId>
    <version>2.4.0</version>
</dependency>

Hinweis: Es scheint, dass es auch das Funkengerüst des Mikrogerüsts unterstützt. Gibt es eine andere FW, die dies unterstützt? Beispielquelle * GitHub

pom.xml


<!-- https://mvnrepository.com/artifact/com.sparkjava/spark-template-pebble -->
<dependency>
    <groupId>com.sparkjava</groupId>
    <artifactId>spark-template-pebble</artifactId>
    <version>2.5.5</version>
</dependency>

Stellen Sie als Nächstes sicher, dass sich die Vorlagendatei im Klassenpfad befindet (Beispiel: / WEB-INF / templates /). Definieren Sie PebbleEngine und PebbleViewResolver.

MvcConfig.java


@Configuration
@ComponentScan(basePackages = { "com.example.controller", "com.example.service" })
@EnableWebMvc
public class MvcConfig extends WebMvcConfigurerAdapter {

    @Autowired
    private ServletContext servletContext;

    @Bean
    public Loader templateLoader(){
        return new ServletLoader(servletContext);
    }
    
    @Bean
    public SpringExtension springExtension() {
        return new SpringExtension();
    }

    @Bean 
    public PebbleEngine pebbleEngine() {
         return new PebbleEngine.Builder()
                .loader(this.templateLoader())
                .extension(springExtension())
                .build();
    }

    @Bean
    public ViewResolver viewResolver() {
        PebbleViewResolver viewResolver = new PebbleViewResolver();
        viewResolver.setPrefix("/WEB-INF/templates/");
        viewResolver.setSuffix(".html");
        viewResolver.setPebbleEngine(pebbleEngine());
        return viewResolver;
    }

}

Klassen mit der Annotation @Controller sollten bei Verwendung von jsp wie gewohnt den Vorlagennamen zurückgeben.

ProfileController.java


@Controller
@RequestMapping(value = "/profile")
public class ProfileController {

	@Autowired
	private UserService userService;

	@RequestMapping
	public ModelAndView getUserProfile(@RequestParam("id") long id) {
		ModelAndView mav = new ModelAndView();
		mav.addObject("user", userService.getUser(id));
		mav.setViewName("profile");
		return mav;
	}

}

Im obigen Beispiel wird \ WEB-INF \ templates \ profile.html gerendert. Das Benutzerobjekt kann in der Vorlage verwendet werden.

Einige Funktionen von Pebble

Über den Zugang zu Spring Beans

Natürlich können Sie in der Vorlage auf Spring Beans zugreifen.

{{ beans.beanName }}

Sie können auch auf http-Anforderungen, http-Antworten und http-Sitzungen zugreifen.

{{ request.contextPath }}
{{ response.contentType }}
{{ session.maxInactiveInterval }}

Verlängerungen für den Frühling

Href function Weist automatisch einen Kontextpfad zu

<a href="{{ href('/foobar') }}">Example</a>

Message function Es verhält sich wie die i18n-Funktion. Ein wenig anders ist die Verwendung der konfigurierten Spring messageSource (normalerweise ResourceBundleMessageSource).

Label = {{ message('label.test') }}
Label with params = {{ message('label.test.params', 'params1', 'params2') }}

Spring validations and error messages

To check if there's any error:

Wenn Sie wissen möchten, ob ein Fehler vorliegt

{{ hasErrors('formName' }}

{{ hasGlobalErrors('formName' }}

{{ hasFieldErrors('formName', 'fieldName' }}

Bei der Behandlung mehrerer Fehler

{% for err in getAllErrors('formName') %}
    <p>{{ err }}</p>
{% endfor %}

{% for err in getGlobalErrors('formName') %}
    <p>{{ err }}</p>
{% endfor %}

{% for err in getFieldErrors('formName', 'fieldName') %}
    <p>{{ err }}</p>
{% endfor %}

Timer Mit PebbleView können Sie die für die Verarbeitung der Vorlage benötigte Zeit ausgeben. Fügen Sie es einfach zu log4j.xml hinzu.

log4j.xml


<Logger name="com.mitchellbosecke.pebble.spring.PebbleView.timer" level="DEBUG" additivity="false">
      <AppenderRef ref="STDOUT" />
</Logger> 

Grundlegende Verwendung

Einführung

Pebble-Vorlagen können alles als Text ausgeben. HTML wird für die allgemeine Verwendung angenommen, kann aber auch für CSS, XML, JS usw. verwendet werden (Ergänzung: Ich verwende es für die SQL-Vorlagen-Engine). Die Vorlage enthält sowohl die Syntax der Sprache, die Sie ausgeben möchten, als auch die Syntax von Pebble. Hier ist eine kleine Beispiel-HTML-Vorlage.

<html>
	<head>
		<title>{{ websiteTitle }}</title>
	</head>
	<body>
		{{ content }}
	</body>
</html>

Bei der Auswertung dieser Vorlage (dh beim Aufrufen der Auswertungsmethode) Sie benötigen ein Kartenobjekt mit den oben genannten "Website-Titeln" und "Inhalten" als Schlüssel.

Der folgende Code ist erforderlich, um Pebble-Engine-Objekte zu erstellen und Vorlagen zu kompilieren.

PebbleEngine engine = new PebbleEngine.Builder().build();

Die Kompilierung durch die Pebble-Engine ist wie folgt

PebbleTemplate compiledTemplate = engine.getTemplate("templates/home.html");

Bereiten Sie abschließend ein java.io.Writer-Objekt und ein Map-Objekt vor.

Writer writer = new StringWriter();

Map<String, Object> context = new HashMap<>();
context.put("websiteTitle", "My First Website");
context.put("content", "My Interesting Content");

compiledTemplate.evaluate(writer, context);

String output = writer.toString();

Syntax

Formel Erläuterung
{{ ... }} Gibt das Ergebnis des Ausdrucks zurück. Bitte geben Sie den Variablennamen usw. an.
{% ... %} Steuert den Fluss der Vorlage. Zum Beispiel{% if... %},{% extends... %},{% block... %}es gibt.

Variable

Dies ist ein Beispiel für die direkte Ausgabe von Variablen in eine Vorlage. Wenn das Kartenobjekt eine Variable namens foo mit dem Wert "bar" enthält, wird "bar" ausgegeben.

{{ foo }}

Sie können auch mit dem Punkt (.) Auf die Attribute von Variablen zugreifen. Wenn der Attributwert unbestimmt ist, können Sie [] auch für assoziative Array-Ticks verwenden.

{{ foo.bar }}
{{ foo["bar"] }}

Wenn Sie "foo.bar" schreiben, wird der folgende Zugriff als interne Operation versucht.

Wenn der Wert null ist, wird (standardmäßig) ein leeres Zeichen ausgegeben.

Typensicherheit

Pebble hat einen dynamischen Typ. Und bis es tatsächlich evaluiert ist, gibt es keine Probleme mit der Typensicherheit. Hinweis: Es scheint zu bedeuten, dass es möglich ist, Variablennamen zu beschreiben, die in der Vorlage nicht vorhanden sind. In Pebble können Sie jedoch in der Einstellung "strenge Variablen" auswählen, wie mit Typensicherheitsproblemen umgegangen werden soll. Der Standardwert ist false.

{{ foo.bar }}

Wenn in diesem Beispiel beispielsweise foo nicht über das Balkenbalkenattribut verfügt und strictVariables auf true gesetzt ist, Bei der Auswertung der Vorlage wird eine Ausnahme ausgelöst. Wenn strictVariables false ist, ist es auch nullsafe. Selbst wenn die folgenden foo und bar null sind, wird ein leeres Zeichen ausgegeben.

{{ foo.bar.baz }}

Der Standardfilter ist in dieser Situation möglicherweise am besten geeignet. Hinweis: Der Standardfilter gibt den Standardtext aus, wenn der Wert null oder ein leeres Zeichen / eine leere Liste ist.

Filter

Filter ist eine Funktion, mit der Sie die Ausgabe von der Ausgabe weiter ändern können. Verwenden Sie eine Pipe (|), um den Variablennamen, den Filternamen (und seine Argumente) zu trennen. Wenn Sie mehrere Filter verwenden, können Sie diese zusammen schreiben. auf diese Weise….

{{ "If life gives you lemons, eat lemons." | upper | abbreviate(13) }}

Im obigen Beispiel lautet die Ausgabe wie folgt.

IF LIFE GI...

Funktion

Der Filter diente nur dazu, die Ausgabe zu ändern. Funktionen schaffen neue Funktionen. Es ist das gleiche wie in anderen Sprachen. Rufen Sie mit () auf.

{{ max(user.score, highscore) }}

Steuerungssyntax

Pebble verfügt über mehrere Steuerungssyntaxen. Hauptsächlich für und wenn.

{% for article in articles %}
    <h3>{{ article.title }}</h3>
    <p>{{ article.content }}</p>
{% else %}
    <p> There are no articles. </p>
{% endfor %}
{% if category == "news" %}
    {{ news }}
{% elseif category == "sports" %}
    {{ sports }}
{% else %}
    <p>Please select a category</p>
{% endif %}

Aus anderen Vorlagen einschließen

Sie können das Include-Tag verwenden, um Ausgaben von anderen Vorlagen zu erhalten.

<div class="sidebar">
	{% include "advertisement.html" %}
</div>

Vorlagenvererbung

Dies ist eine der Stärken von Pebble. Sie können einen überschreibbaren Abschnitt in Ihrer untergeordneten Vorlage haben. Schreiben Sie das "Block" -Tag in die übergeordnete Vorlage. Schauen Sie sich zunächst diese übergeordnete Vorlage an.

<html>
<head>
	<title>{% block title %}My Website{% endblock %}</title>
</head>
<body>
	<div id="content">
		{% block content %}{% endblock %}
	</div>
	<div id="footer">
		{% block footer %}
			Copyright 2013
		{% endblock %}
	</div>
</body>
</html>

Oben kann der Block-Tag-Teil mit einer untergeordneten Vorlage überschrieben werden.

Es ist eine untergeordnete Vorlage.

{% extends "./parent.html" %}

{% block title %} Home {% endblock %}

{% block content %}
	<h1> Home </h1>
	<p> Welcome to my home page.</p>
{% endblock %}

Es gibt ein "Extended" -Tag. Erstens ist es ohne dieses Tag nutzlos. Es kann nur einer verwendet werden. (Ergänzung: Es ist ähnlich wie Java).

Wenn Sie diese untergeordnete Vorlage auswerten, erhalten Sie folgende Ausgabe:


<html>
<head>
	<title>Home</title>
</head>
<body>
	<div id="content">
		<h1> Home </h1>
		<p> Welcome to my home page.</p>
	</div>
	<div id="footer">
		Copyright 2013
	</div>
</body>
</html>

In diesem Beispiel wird der Fußzeilenblock in der untergeordneten Vorlage nicht überschrieben. In diesem Fall wird die in der übergeordneten Vorlage beschriebene verwendet.

Sie können auch die dynamische Vererbung verwenden.

{% extends ajax ? 'ajax.html' : 'base.html' %}

Makro

Makros können Teile der Vorlage wiederverwenden. Verwenden Sie das Makro-Tag. Hinweis: Ähnliche Dinge können durch Schreiben von Java-Code für Funktionserweiterungen getan werden. Ich frage mich, ob es verwendet wird, wenn Sie keinen HTML-Code in Java schreiben möchten oder wenn es keine bestimmte arithmetische Verarbeitung gibt und nur die Vorlagenbeschreibung ausreicht.

{% macro input(type, name) %}
	<input type="{{ type }}" name="{{ name }}" />
{% endmacro %}

Es kann wie eine Funktion aufgerufen und verwendet werden.

{{ input("text", "name", "Mitchell") }}

Die untergeordnete Vorlage kann das in der übergeordneten Vorlage definierte Makro verwenden. Wenn Sie ein Makro in einer anderen Datei verwenden möchten, verwenden Sie das Tag "import". Makros können nicht auf Kartenobjekte (Kontext) zugreifen. Sie können nur auf die Argumente zugreifen.

Benannte Argumente

Sie können benannte Argumente in Filtern, Funktionen, Tests und Makros verwenden. Wenn Sie den Standardwert nicht ändern, müssen Sie das Argument nicht angeben.

{{ stringDate | date(existingFormat="yyyy-MMMM-d", format="yyyy/MMMM/d") }}

Positionierte und benannte Argumente können verwechselt werden. Positionierte Argumente müssen vor benannten Argumenten stehen.

{{ stringDate | date("yyyy/MMMM/d", existingFormat="yyyy-MMMM-d") }}

Dies ist besonders nützlich, wenn Sie Makros verwenden. Dies liegt daran, dass häufig nicht verwendete Argumente vorhanden sind.

{% macro input(type="text", name, value) %}
	<input type="{{ type }}" name="{{ name }}" value="{{ value }}" />
{% endmacro %}

{{ input(name="country") }}

{# will output: <input type="text" name="country" value="" /> #}

Flucht

XSS-Schwachstellen sind typisch für WEB-Apps. Um dies zu vermeiden, müssen Sie potenziell unsicheren Daten entkommen. Bei Pebble ist die automatische Escape-Funktion standardmäßig aktiviert. Die automatische Escape-Funktion kann ebenfalls deaktiviert werden. Mit Pebble können Sie feinere Escape-Einstellungen vornehmen.

Dies ist ein Beispiel dafür, wie der in der Variablen festgelegte Wert maskiert wird.

{% set danger = "<br>" %}
{{ danger }}

{# will output: &lt;br&gt; #}

Wenn Sie die automatische Escape-Funktion deaktiviert haben, können Sie sie auf diese Weise maskieren.

{% set danger = "<br>" %}
{{ danger | escape }}

{# will output: &lt;br&gt; #}

Standardmäßig ist HTML so eingestellt, dass es maskiert wird. Sie können die Escape-Strategie auswählen (Ergänzung: Die interne Logik scheint ein Strategiemuster zu sein).

{% set danger = "alert(...)" %}
<script>var username="{{ danger | escape(strategy="js") }}"</script>

Siehe auch die Fluchtanleitung. Es gibt weitere Informationen. Es gibt Inhalte wie das Deaktivieren und das Umschalten der Escape-Strategie.

Leer

Der erste Zeilenumbruch unmittelbar nach dem Pebble-Tag wird standardmäßig ignoriert. Ansonsten wird wie gewohnt ausgegeben.

Pebble hat auch die Möglichkeit, die vorderen und hinteren Rohlinge zu kürzen. Schreiben Sie so. Verwenden Sie das Trennzeichen "{{-...-}}".

<p> 		{{- "no whitespace" -}}		</p>
{# output: "<p>no whitespace</p>" #}

Wenn Sie so schreiben, wird nur einer abgeschnitten.

<p> 		{{- "no leading whitespace" }}		</p>
{# output: "<p>no whitespace		</p>" #}

Kommentar

Sie können den Teilen der Vorlage auch Kommentare hinzufügen. Es ist eine Abgrenzung namens "{# ... #}". Dies wird nicht ausgegeben.

{# THIS IS A COMMENT #}
{% for article in articles %}
	<h3>{{ article.title }}</h3>
	<p>{{ article.content }}</p>
{% endfor %}

Formel

Die Ausdrücke, die in den Vorlagen von Pebble angezeigt werden, sind denen in Java sehr ähnlich.

wörtlich

Literal ist eine sehr einfache Formel, nicht wahr? Sie können Java-String- und Integer-Typen verwenden.

Sammlung

Sie können Listen und Karten direkt in Ihren Vorlagen verwenden.

Arithmetik

Es unterstützt auch grundlegende arithmetische Operationen. Wir unterstützen diese.

Logik

Sie können zwei Ausdrücke mit einer logischen Operation kombinieren. Sie können diese verwenden.

Vergleichsberechnung

Diese werden unterstützt.

==, ! =, <, >, > = Und <=

{% if user.age >= 18 %}
	...
{% endif %}

Prüfung

Der Operator "is" führt den Test aus. Diese Testfunktion kann verwendet werden, um bestimmte Werte usw. zu bestimmen. Der Operand rechts von ist der Name des Tests.

{% if 3 is odd %}
	...
{% endif %}

Die Testfunktion kann die Verweigerung durch den Operator "nicht" verwenden.

{% if name is not null %}
	...
{% endif %}

Dreiecksoperator

Sie können auch den ternären Operator verwenden.

{{ foo ? "yes" : "no" }}

Bedienerpriorität

Die Spitze hat die höchste Priorität.

Kieselverlängerung

Überblick

Pibble ist flexibel für eine Vielzahl von Projekten konzipiert. Sie können Tags, Funktionen, Operatoren, Filter, Testklassen und globale Variablen auch selbst erstellen und hinzufügen. Diese Implementierungen sind fast einfach und schnell. Lassen Sie uns zunächst eine Klasse erstellen, die die Erweiterungsschnittstelle implementiert. Es gibt einen einfachen Weg, dies zu tun. Es wird eine Klasse erstellt, die AbstractExtension erbt, für die die Erweiterungsschnittstelle bereits implementiert ist. Nach der Implementierung registrieren wir uns bei Pebble Engine, bevor wir die Vorlage kompilieren.

PebbleEngine engine = new PebbleEngine.Builder().extension(new CustomExtension()).build();

Filter

Um einen benutzerdefinierten Filter zu erstellen, implementieren Sie zunächst die Methode getFilters () der zuvor beschriebenen Extension-Klasse. Erstellen Sie diese Methode, um ein Map-Objekt zurückzugeben, das eine Instanz von key = Filtername und value = Filterklasse ist. Nach der Implementierung besteht der nächste Schritt darin, die Filterschnittstelle zu implementieren. Die Filter-Klasse implementiert zwei Methoden, getArgumentNames () und apply (). Die Methode getArgumentNames wird implementiert, um eine Liste zurückzugeben, die die Namen und die Reihenfolge der formalen Argumente definiert. (Es ist wie ein Schlüsselwortargument in einer Skriptsprache.) Ergänzung: Wenn keine Definition erforderlich ist, implementieren Sie sie so, dass sie null zurückgibt.

Die Methode apply implementiert den eigentlichen Filterprozess. Das erste Argument sind die Daten, die Sie filtern möchten. Das zweite Argument ist das Filterargument. (Ergänzung: {{'Mitchell' | Slice (1,3)}} ← Dies ist das Argument von 1,3) Da Pebble dynamisch typisiert wird, wird vom Objekttyp heruntergestuft. Dies ist ein Beispielfilter.

public UpperFilter implements Filter {

  	@Override
	public List<String> getArgumentNames() {
		return null;
	}

	@Override
	public Object apply(Object input, Map<String, Object> args){
		if(input == null){
			return null;
		}
		String str = (String) input;
		return str.toUpperCase();
	}

}

Die Args-Map enthält standardmäßig zwei Elemente.

_self: Eine Instanz von PebbleTemplate. Sie können den Vorlagennamen usw. abrufen. _context: Eine Instanz von EvaluationContext. Sie können das Gebietsschema abrufen und so weiter.

Testklasse

Es kann ähnlich wie ein Filter implementiert werden. Implementieren Sie einfach "getTests ()", das eine Karte des Testnamens und des entsprechenden Testobjekts zurückgibt. Und die Testklasse implementiert die "Test" -Schnittstelle. Test hat eine ähnliche Schnittstelle wie Filter. Die Methode apply von Filter hat ein beliebiges Objekt zurückgegeben, in der Klasse Test jedoch einen Booleschen Wert.

[gerade](http: //) Testimplementierungsbeispiel.

public EvenTest implements Test {

	@Override
	public List<String> getArgumentNames() {
		return null;
	}

	@Override
	public boolean apply(Object input, Map<String,Object> args){
		Integer in = (Integer) input;
		return (in % 2 == 0);
	}

}

Functions Funktionen ähneln auch Filter. Es ist jedoch schwierig zu entscheiden, welche implementiert werden soll. Lassen Sie es uns also richtig verstehen. Im Fall von Filter ist beabsichtigt, den vorhandenen Inhalt zu ändern und neuen Inhalt auszugeben.

Lassen Sie uns Funktionen implementieren. Implementiert "getFunctions ()", das eine Zuordnung des Funktionsnamens und des entsprechenden Funktionsobjekts zurückgibt. Implementieren Sie dann die Funktionsklasse, die die Funktionsschnittstelle implementiert. Ähnlich wie "Filter" und "Test". Hier ist eine Beispielimplementierung der Funktion "fibonacciString" (nicht in der Kieselbibliothek).

public FibonnaciStringFunction implements Function() {

	@Override
	public List<String> getArgumentNames() {
		List<String> names = new ArrayList<>();
		names.put("length");
		return names;
	}

	@Override
	public Object execute(Map<String,Object> args) {
		Integer length = (Integer)args.get("length");
		Integer prev1 = 0;
		Integer prev2 = 1;

		StringBuilder result = new StringBuilder();

		result.append("01");

		for(int i = 2; i < length; i++){
			Integer next = prev1 + prev2;
			result.append(next);
			prev1 = prev2;
			prev2 = next;
		}
		return result.toString();

	}
}

Die Args-Map enthält standardmäßig zwei Elemente.

_self: Eine Instanz von PebbleTemplate. Sie können den Vorlagennamen usw. abrufen. _context: Eine Instanz von EvaluationContext. Sie können das Gebietsschema abrufen und so weiter.

Informationen zu Position und Argumentname

Filter, Tests und Funktionen müssen die Methode "getArgumentNames" implementieren, auch wenn sie null zurückgeben. Durch die Rückgabe einer Liste von Zeichenfolgen können Vorlagenautoren benannte Parameter verwenden. Dies ist ein Beispiel für die frühere Verwendung der Funktion "fibonacciString". Es gibt zwei Möglichkeiten, es zu nennen.

{{ fibonacci(10) }}
{{ fibonacci(length=10) }}

Wenn der Vorlagenersteller den Namen im Parameter weglässt und das Argument an Ort und Stelle schreibt Es wird beim Aufrufen der Funktion dem ursprünglichen Namen (Ergänzung: der in getArgumentNames definierte Name) zugeordnet. Hat der Vorlagenersteller es bei der Implementierung mit einem benannten Parameter aufgerufen? Sie müssen sich keine Sorgen machen, ohne den Namen anzurufen. Kurz gesagt, wenn Filter / Funktion / Test mehrere Parameter hat und der Vorlagenersteller keine benannten Parameter verwendet, Sie müssen die Reihenfolge der Argumente angeben.

minFunction und maxFunction können eine unbegrenzte Anzahl von Argumenten haben. Diese Art von Funktion kann keine benannten Argumente verwenden. Die Implementierung der Methode "getArgumentNames" sollte in diesem Fall eine null oder leere Liste zurückgeben. In diesem Fall wird die Karte mit dem von Pebble automatisch zugewiesenen Schlüssel an die Methode "execute" übergeben. (Ergänzung: Eine Karte wird mit Schlüsseln wie "1", "2" ... erstellt.)

Globale Variablen

Es ist auch einfach, globale Variablen zu erstellen, auf die über alle Vorlagen zugegriffen werden kann. Implementieren Sie einfach die benutzerdefinierte Erweiterung "getGlobalVariables ()", um eine Map <String, Object> zurückzugeben. Beim Zusammenführen mit einer Vorlage (Ergänzung: beim Aufrufen von template.evaluate (Writer, Kontext)) wird diese mit jedem Kontext zusammengeführt.

Operator

Operatoren sind komplexer zu implementieren als Filter und Tests. Implementieren Sie eine oder beide der Methoden "getBinaryOperators ()" und "getUnaryOperators ()" Ihrer benutzerdefinierten Erweiterung. Es sollte List bzw. List zurückgeben.

Um BinaryOperator zu implementieren, benötigen Sie Folgendes:

--Symbol: Das Symbol des tatsächlichen Bedieners. Es ist normalerweise ein Buchstabe, aber es ist okay, wenn es nicht ist.

--Expression-Klasse: Gibt die BinaryExpression-Klasse zurück. Diese Klasse implementiert die Behandlung des tatsächlichen Operators.

Die Implementierung des unären Operators ist dieselbe wie die des binären Operators, außer dass keine Vererbung von "UnaryExpression" und Definition der Assoziativität erforderlich ist.

Eine Liste der Prioritäten.

or: 10
and: 15
is: 20
is not: 20
==: 30
!=: 30
>: 30
<: 30
>=: 30
<=: 30
+: 40
-: 40
not: 50 (Unary)
*: 60
/: 60
%: 60
|: 100
+: 500 (Unary)
-: 500 (Unary)

Dies ist ein Implementierungsbeispiel für den Operator +.

public AdditionOperator implements BinaryOperator {

	public int getPrecedence(){
		return 30;
	}

	public String getSymbol(){
		return "+";
	}

	public Class<? extends BinaryExpression<?>> getNodeClass(){
		return AdditionExpression.class;
	}

	public Associativity getAssociativity(){
		return Associativity.LEFT;
	}

}

Sie müssen auch die BinaryExpression-Klasse implementieren, die die tatsächliche Verarbeitung des Operators beschreibt. Dies ist ein Implementierungsbeispiel für AdditionExpression, auf das der AdditionOperator im obigen Beispiel verweist.

public AdditionExpression extends BinaryExpression<Object> {

	@Override
	public Object evaluate(PebbleTemplateImpl self, EvaluationContext context){
		Integer left = (Integer)getLeftExpression().evaluate(self, context);
		Integer right = (Integer)getRightExpression().evaluate(self, context);

		return left + right;
	}

}

Die obigen Ausnahmen sind "leftExpression" und "rightExpression". Es ist ein Operand (Ergänzung: Im Fall von 5 * 4 sind "5" und "4" die Operanden). Im obigen Beispiel haben wir in Integer umgewandelt, aber die Umwandlung funktioniert nicht immer. Im Fall des ursprünglichen Additionsoperators muss eine andere als Integer angenommen werden, was tatsächlich eine kompliziertere Implementierung ist.

Etikett

Das Erstellen neuer Tags ist eine der leistungsstärksten Funktionen von Pebble. Zunächst müssen Sie die Methode "getTokenParsers ()" implementieren. Stellen Sie sicher, dass die Schnittstelle "com.mitchellbosecke.pebble.tokenParser.TokenParser" den entsprechenden "RenderableNode" zurückgibt. Das "Token" -Argument der "Parse" -Methode enthält Informationen wie Operatoren, Leerzeichen, Variablennamen, Trennzeichen usw. RenderableNode ist ein Typ für die Ausgabe.

Dies ist ein Implementierungsbeispiel für das Tag "set".

public class SetTokenParser extends AbstractTokenParser {

    @Override
    public RenderableNode parse(Token token, Parser parser) throws ParserException {
        TokenStream stream = parser.getStream();
        int lineNumber = token.getLineNumber();

        // skip the 'set' token
        stream.next();

        String name = parser.getExpressionParser().parseNewVariableName();

        stream.expect(Token.Type.PUNCTUATION, "=");

        Expression<?> value = parser.getExpressionParser().parseExpression();

        stream.expect(Token.Type.EXECUTE_END);

        return new SetNode(lineNumber, name, value);
    }

    @Override
    public String getTag() {
        return "set";
    }
}

Die Methode getTag () sollte den Tag-Namen zurückgeben. Der Hauptparser von Pebble delegiert dann die Verarbeitung an einen benutzerdefinierten Parser.

Die "parse" -Methode wird jedes Mal aufgerufen, wenn der primäre Parser von Pebble ein benutzerdefiniertes Tag findet. Diese Methode sollte eine RenderableNode-Instanz zurückgeben, um in das Writer-Objekt zu schreiben. Wenn RenderableNode untergeordnete Elemente enthält, muss dies in der render -Methode in der Knotenklasse behandelt werden. Wir empfehlen, die folgenden Quellen zu lesen, um zu erfahren, wie die Syntax analysiert wird. TokenParser Parser SetTokenParser ForTokenParser IfNode SetNode

Recommended Posts

Template Engine Pebble (Java) - Leitfaden
Hallo Welt mit Java Template Engine Thymeleaf
[Vorlage] MySQL-Verbindung mit Java
Beispielcode mit JMustache, der Moustache-Vorlagen-Engine in Java
Multithreaded passend zur [Java] Vorlage
[Java] Button-Vorlagenklasse von Graphics