[JAVA] Erweitern Sie Thymeleaf, um eindeutige Tags zu implementieren (Teil 1).

Dieses Mal werde ich zusammenfassen, wie ein Prozessor erstellt und Thymeleaf erweitert wird. Der Prozessor verfügt über verschiedene Erweiterungsmethoden, daher werde ich dieses Mal zusammenfassen, wie Sie Ihre eigenen Tags erstellen. (Es ist wie ein \ <th: block > -Tag.)

Im Folgenden erfahren Sie, wie Sie ein UtilityObject selbst erstellen und erweitern. Thymeleaf erweitern (UtilityObject)

Umgebung

Verhalten von selbst erstellten Tags

Erstellen wir eine vereinfachte Version des T: messagesPanel-Tags des TERASOLUNA Framework. Das detaillierte Verhalten ist wie folgt.

<ul>
  <li>Nachricht 1</li>
  <li>Nachricht 2</li>
</ul>
<sample:messagesPanel outerElement="div" innerElement="span" />
↓
<div>
  <span>Nachricht 1</span>
  <span>Nachricht 1</span>
</div>

Erstellen Sie eine Prozessorklasse

Lassen Sie uns zunächst die Kernklasse Processor erstellen. Da wir dieses Mal ein Tag erstellen möchten, erstellen wir eine Klasse, die AbstractElementTagProcessor erbt. (Erstellt mit Bezug auf StandardBlockTagProcessor.)

Zunächst der Konstruktor

public class MessagesPanelTagProcessor extends AbstractElementTagProcessor {

  public MessagesPanelTagProcessor(String dialectPrefix){
    super(TemplateMode.HTML, dialectPrefix, "messagesPanel", dialectPrefix != null, null, false, 100000);
  }

  //~ Ausgelassen ~

}

Rufen Sie den Konstruktor der übergeordneten Klasse auf. Die Argumente haben folgende Bedeutung.

Dann doProcess-Methode

Verwenden Sie diese Methode für eine bestimmte Verarbeitung.

public class MessagesPanelTagProcessor extends AbstractElementTagProcessor {

  //~ Ausgelassen ~

  protected void doProcess(ITemplateContext context, IProcessableElementTag tag, IElementTagStructureHandler structureHandler) {

    // (1)
    RequestContext requestContext =
                (RequestContext) context
                        .getVariable(SpringContextVariableNames.SPRING_REQUEST_CONTEXT);

    Map<String, Object> model = requestContext.getModel();
    Object messages = model.get("messageList");
    
    if (messages == null) {
      // (2)
      structureHandler.removeElement();
      return;
    }

    // (3)
    List<String> messageList = (List<String>) model.get("messageList");
    String outerElement =
          tag.getAttributeValue("outerElement") == null ? "ul" : tag
                    .getAttributeValue("outerElement");
    String innerElement =
            tag.getAttributeValue("innerElement") == null ? "li" : tag
                    .getAttributeValue("innerElement");
    
    // (4)
    IModelFactory modelFactory = context.getModelFactory();
    IModel iModel = modelFactory.createModel();
    iModel.add(modelFactory.createOpenElementTag(outerElement));
    for (String message : messageList) {
        iModel.add(modelFactory.createOpenElementTag(innerElement));
        iModel.add(modelFactory.createText(HtmlEscape.escapeHtml4Xml(message)));
        iModel.add(modelFactory.createCloseElementTag(innerElement));
    }
    iModel.add(modelFactory.createCloseElementTag(outerElement));

    // (5)
    structureHandler.replaceWith(iModel, false);
  }
}
Artikelnummer Erläuterung
(1) Indem Sie den RequestContext abrufen, können Sie das Modell daraus abrufen.
(2) Verwenden Sie zum Entfernen des Tags die removeElement-Methode des Arguments IElementTagStructureHandler.
(3) Verwenden Sie die Methode getAttributeValue des Arguments IProcessableElementTag, um den für das Attribut des Tags angegebenen Wert abzurufen.
(4) Erstellen Sie ein Element mit IModelFactory und fügen Sie es IModel hinzu. Es gibt verschiedene Arten von createOpenElementTag-Methoden. Sie können Tags auch erstellen, indem Sie Attribute angeben. Wenn Sie eine beliebige Klasse usw. angeben möchten, können Sie diese damit erstellen.
(5) Ursprünglich mit der Methode replaceWith geschrieben<sample:messagesPanel />Ersetzen Sie das Tag durch das Element, das Sie bisher erstellt haben.

** * Zugabe *** Anscheinend zeigt die IModelFactory.createText-Methode das HTML-Tag so an, wie es ist, wenn die als Argument angegebene Zeichenfolge ein HTML-Tag enthält. In StandardTextTagProcessor, der dem Text von Thymeleaf entspricht, wird die Escape-Verarbeitung mit einer Bibliothek namens unbescape ausgeführt. Daher sollte die Escape-Verarbeitung mit einer ähnlichen Bibliothek durchgeführt werden. Das obige Beispiel wurde geändert.

Erstellen Sie eine Dialektklasse

Sie müssen die Dialogklasse so erstellen, wie Sie es beim Erstellen des UtilityObject selbst getan haben. Wenn Sie die Dialog-Klasse bereits erstellt haben, können Sie sie hinzufügen.

Wenn Sie einen Prozessor hinzufügen, müssen Sie die IProcessorDialect-Schnittstelle implementieren. Da es jedoch eine abstrakte Klasse namens AbstractProcessorDialect gibt, die sie implementiert, erben wir sie diesmal.

public class SampleDialect extends AbstractProcessorDialect {

    public SampleDialect() {
        super("sample", "sample", 1000);
    }

    @Override
    public Set<IProcessor> getProcessors(String dialectPrefix) {
        Set<IProcessor> processors = new HashSet<>();
        processors.add(new MessagesPanelTagProcessor(dialectPrefix));
        return processors;
    }
}

Dialekt registrieren

Dies macht auch das Gleiche wie mit dem Utility-Objekt. Bitte beachten Sie Folgendes. https://qiita.com/d-yosh/items/edf6ac4e19a7f967a058#dialect%E3%82%92%E7%99%BB%E9%8C%B2%E3%81%99%E3%82%8B

Versuche dich zu bewegen

Ich habe den folgenden Controller und HTML erstellt und den Vorgang bestätigt.

@Controller
public class HelloController {

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String home(Model model) {

        model.addAttribute("messageList", Arrays.asList("Nachricht 1","Nachricht 2"));
        return "home";
    }
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Home</title>
</head>
<body>
  <h1>Hello world!</h1>
  <hoge:messagesPanel />
  <hoge:messagesPanel outerElement="div" innerElement="span"/>
</body>
</html>

Die Ausgabe sollte folgendermaßen aussehen:

<html><head>
<meta charset="utf-8">
<title>Home</title>
</head>
<body>
  <h1>Hello world!</h1>
  <ul>
    <li>Nachricht 1</li>
    <li>Nachricht 2</li>
  </ul>
  <div>
    <span>Nachricht 1</span>
    <span>Nachricht 2</span>
  </div>
</body>
</html>

Wo ich süchtig war

Ich wusste nicht, wie ich das Modell bekommen sollte.

Wenn ich vorerst den Inhalt des Arguments debuggte und überprüfte, schien es, als könnte ich den RequestContext abrufen, also versuchte ich, ihn von dort abzurufen. Vielleicht gibt es noch einen anderen guten Weg ...

Nach setBody blieb das erste Tag erhalten

IElementTagStructureHandler hat eine Methode namens setBody, daher habe ich mich gefragt, ob ich diese verwenden soll. Dann wurde auch das Tag \ <sample: messagesPanel / > angezeigt. Als ich das überprüfte, gab es eine Methode namens removeTags, daher dachte ich, dass \ <sample: messagesPanel / > verschwinden sollte, wenn ich dies verwendete, aber diesmal wurden die in Body festgelegten Inhalte nicht angezeigt. Als ich ihre Implementierungsklassen überprüfte, rief fast jede Methode eine Methode namens resetAllButVariablesOrAttributes auf, und diese brachte die Einstellungsinformationen in den Ausgangszustand zurück. Wenn Sie das erste Tag am Leben erhalten möchten, verwenden Sie setBody, und wenn Sie das erste Tag löschen möchten, verwenden Sie replaceWith.

Recommended Posts

Erweitern Sie Thymeleaf, um eindeutige Tags zu implementieren (Teil 1).
Thymeleaf erweitern (UtilityObject)
Einführung in Ratpack (9) - Thymeleaf
Ich möchte eine Produktinformationsbearbeitungsfunktion ~ part1 ~ implementieren