Trucchi JSP per semplificare i templating?

Al lavoro ho avuto il compito di trasformare un sacco di file HTML in un semplice progetto JSP . È davvero tutto statico, nessuna logica serveride da programmare. Dovrei menzionare che sono completamente nuovo in Java. I file JSP sembrano facilitare il lavoro con le inclusioni e le variabili comuni, proprio come PHP , ma mi piacerebbe sapere un modo semplice per ottenere qualcosa come l’ereditarietà dei template (stile Django ) o almeno essere in grado di avere un base.jsp file contenente l’intestazione e il piè di pagina, così posso inserire il contenuto più tardi.

Ben Lings sembra offrire qualche speranza nella sua risposta qui: ereditarietà del modello JSP Qualcuno può spiegare come ottenere questo risultato?

Dato che non ho molto tempo, penso che il routing dinamico sia un po ‘troppo, quindi sono contento di avere gli URL direttamente su file .jsp , ma sono aperto a suggerimenti.

Grazie.

modifica: non voglio utilizzare alcuna libreria esterna, perché aumenterebbe la curva di apprendimento per me stesso e per gli altri che lavorano al progetto e l’azienda per cui lavoro è stata contattata per farlo.

Un’altra modifica: non sono sicuro che i JSP tags saranno utili perché il mio contenuto non ha realmente alcuna variabile di modello. Quello di cui ho bisogno è un modo per essere in grado di farlo:

base.html:

  { content.body }  

somepage.html

  

Welcome

con l’output che è:

  

Welcome

Penso che questo mi darebbe abbastanza versatilità per fare tutto ciò di cui ho bisogno. Potrebbe essere realizzato con includes ma poi avrei bisogno di una parte superiore e una inferiore per ogni wrapper, che è un po ‘disordinato.

Come suggerito da skaffman , i file tag JSP 2.0 sono le ginocchia delle api.

Prendiamo il tuo semplice esempio.

Inserisci quanto segue in WEB-INF/tags/wrapper.tag

 <%@tag description="Simple Wrapper Tag" pageEncoding="UTF-8"%>    

Ora nella tua pagina example.jsp :

 <%@page contentType="text/html" pageEncoding="UTF-8"%> <%@taglib prefix="t" tagdir="/WEB-INF/tags" %>  

Welcome

Questo fa esattamente quello che pensi che faccia.


Quindi, lasciamolo espandere su qualcosa di più generale. WEB-INF/tags/genericpage.tag

 <%@tag description="Overall Page template" pageEncoding="UTF-8"%> <%@attribute name="header" fragment="true" %> <%@attribute name="footer" fragment="true" %>    

Per usare questo:

 <%@page contentType="text/html" pageEncoding="UTF-8"%> <%@taglib prefix="t" tagdir="/WEB-INF/tags" %>   

Welcome

Hi I'm the heart of the message

Cosa ti compra? Molto, ma migliora ancora …


WEB-INF/tags/userpage.tag

 <%@tag description="User Page template" pageEncoding="UTF-8"%> <%@taglib prefix="t" tagdir="/WEB-INF/tags" %> <%@attribute name="userName" required="true"%>   

Welcome ${userName}

Per usare questo: (supponiamo di avere una variabile utente nella richiesta)

 <%@page contentType="text/html" pageEncoding="UTF-8"%> <%@taglib prefix="t" tagdir="/WEB-INF/tags" %>  

First Name: ${user.firstName}
Last Name: ${user.lastName}
Phone: ${user.phone}


Ma ti fa piacere usare quel blocco di dettagli utente in altri posti. Quindi, lo rifatteremo. WEB-INF/tags/userdetail.tag

 <%@tag description="User Page template" pageEncoding="UTF-8"%> <%@tag import="com.example.User" %> <%@attribute name="user" required="true" type="com.example.User"%> First Name: ${user.firstName} 
Last Name: ${user.lastName}
Phone: ${user.phone}

Ora l’esempio precedente diventa:

 <%@page contentType="text/html" pageEncoding="UTF-8"%> <%@taglib prefix="t" tagdir="/WEB-INF/tags" %>  


La bellezza dei file Tag JSP è che ti permette fondamentalmente di taggare il markup generico e quindi di rifarlo a vostro piacimento.

JSP Tag Files hanno praticamente usurpato cose come Tiles ecc., Almeno per me. Li trovo molto più facili da usare in quanto l’unica struttura è ciò che gli dai, niente preconcetto. Inoltre è ansible utilizzare i file di tag JSP per altre cose (come il frammento di dettaglio dell’utente sopra).

Ecco un esempio simile a DisplayTag che ho fatto, ma questo è tutto fatto con Tag Files (e il framework Stripes , ovvero s: tags ..). Ciò si traduce in una tabella di righe, alternando colors, navigazione della pagina, ecc:

          Edit      

Ovviamente i tag funzionano con i JSTL tags (come c:if , ecc.). L’unica cosa che non puoi fare all’interno del corpo di un tag del tag è aggiungere il codice scriptlet Java, ma non è una limitazione come potresti pensare. Se ho bisogno di materiale scriptlet, inserisco la logica in un tag e rilasciamo il tag. Facile.

Quindi, taggare i file può essere praticamente quello che vuoi che siano. Al livello più elementare, è semplice refactoring di taglia e incolla. Prendi una porzione di layout, tagliala, esegui una semplice parametrizzazione e sostituiscila con una chiamata di tag.

Ad un livello più alto, puoi fare cose sofisticate come questo tag table che ho qui.

Ho fatto abbastanza facile, libreria di tag di ereditarietà del modello JSP in stile Django. https://github.com/kwon37xi/jsp-template-inheritance

Penso che sia facile gestire i layout senza una curva di apprendimento.

codice di esempio:

base.jsp: layout

 <%@page contentType="text/html; charset=UTF-8" %> <%@ taglib uri="http://kwonnam.pe.kr/jsp/template-inheritance" prefix="layout"%>    JSP Template Inheritance  

Head

header

Contents

Contents will be placed under this h2

view.jsp: contenuti

 <%@page contentType="text/html; charset=UTF-8" %> <%@ taglib uri="http://kwonnam.pe.kr/jsp/template-inheritance" prefix="layout"%>   

This is an example about layout management with JSP Template Inheritance

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin porta, augue ut ornare sagittis, diam libero facilisis augue, quis accumsan enim velit a mauris.

Basato sulla stessa idea di base della risposta di @Will Hartung , ecco il mio motore di template estensibile magic one tag. Include anche la documentazione e un esempio 🙂

WEB-INF / tags / block.tag:

 <%-- The block tag implements a basic but useful extensible template system. A base template consists of a block tag without a 'template' attribute. The template body is specified in a standard jsp:body tag, which can contain EL, JSTL tags, nested block tags and other custom tags, but cannot contain scriptlets (scriptlets are allowed in the template file, but only outside of the body and attribute tags). Templates can be full-page templates, or smaller blocks of markup included within a page. The template is customizable by referencing named attributes within the body (via EL). Attribute values can then be set either as attributes of the block tag element itself (convenient for short values), or by using nested jsp:attribute elements (better for entire blocks of markup). Rendering a template block or extending it in a child template is then just a matter of invoking the block tag with the 'template' attribute set to the desired template name, and overriding template-specific attributes as necessary to customize it. Attribute values set when rendering a tag override those set in the template definition, which override those set in its parent template definition, etc. The attributes that are set in the base template are thus effectively used as defaults. Attributes that are not set anywhere are treated as empty. Internally, attributes are passed from child to parent via request-scope attributes, which are removed when rendering is complete. Here's a contrived example: ====== WEB-INF/tags/block.tag (the template engine tag)  ====== WEB-INF/templates/base.jsp (base template) <%@ page trimDirectiveWhitespaces="true" %> <%@ taglib prefix="t" tagdir="/WEB-INF/tags" %>  Template Page  .footer { font-size: smaller; color: #aaa; } .content { margin: 2em; color: #009; } ${moreStyle}        ${title}    

${title}

${content}
${footer}
====== WEB-INF/templates/history.jsp (child template) <%@ page trimDirectiveWhitespaces="true" %> <%@ taglib prefix="t" tagdir="/WEB-INF/tags" %>

${shooter} shot first!

====== history-1977.jsp (a page using child template) <%@ page trimDirectiveWhitespaces="true" %> <%@ taglib prefix="t" tagdir="/WEB-INF/tags" %> ====== history-1997.jsp (a page using child template) <%@ page trimDirectiveWhitespaces="true" %> <%@ taglib prefix="t" tagdir="/WEB-INF/tags" %> .revised { font-style: italic; } Greedo --%> <%@ tag trimDirectiveWhitespaces="true" %> <%@ tag import="java.util.HashSet, java.util.Map, java.util.Map.Entry" %> <%@ tag dynamic-attributes="dynattributes" %> <%@ attribute name="template" %> <% // get template name (adding default .jsp extension if it does not contain // any '.', and /WEB-INF/templates/ prefix if it does not start with a '/') String template = (String)jspContext.getAttribute("template"); if (template != null) { if (!template.contains(".")) template += ".jsp"; if (!template.startsWith("/")) template = "/WEB-INF/templates/" + template; } // copy dynamic attributes into request scope so they can be accessed from included template page // (child is processed before parent template, so only set previously undefined attributes) Map dynattributes = (Map)jspContext.getAttribute("dynattributes"); HashSet addedAttributes = new HashSet(); for (Map.Entry e : dynattributes.entrySet()) { if (jspContext.getAttribute(e.getKey(), PageContext.REQUEST_SCOPE) == null) { jspContext.setAttribute(e.getKey(), e.getValue(), PageContext.REQUEST_SCOPE); addedAttributes.add(e.getKey()); } } %> <% if (template == null) { // this is the base template itself, so render it %> <% } else { // this is a page using the template, so include the template instead %> <% } %> <% // clean up the added attributes to prevent side effect outside the current tag for (String key : addedAttributes) { jspContext.removeAttribute(key, PageContext.REQUEST_SCOPE); } %>

Usa le tessere . Mi ha salvato la vita.

Ma se non puoi, c’è il tag include , che lo rende simile a php.

Il body tag potrebbe non fare effettivamente ciò che ti serve, a meno che tu non abbia un contenuto super semplice. Il tag body viene utilizzato per definire il corpo di un elemento specificato. Dai un’occhiata a questo esempio :

  ${content.lang} ${content.body}  

Si specifica il nome dell’elemento, eventuali attributi che l’elemento potrebbe avere (“lang” in questo caso) e quindi il testo che vi entra – il corpo. Quindi se

  • content.headerName = h1 ,
  • content.lang = fr , e
  • content.body = Heading in French

Quindi l’output sarebbe

 

Heading in French