JSP-Vorlagen

Obwohl Webentwicklungstools schnell Fortschritte machen, bleiben sie hinter den meisten Toolkits für grafische Benutzeroberflächen (GUI) wie Swing oder VisualWorks Smalltalk zurück. Beispielsweise bieten herkömmliche GUI-Toolkits Layout-Manager in der einen oder anderen Form, mit denen Layout-Algorithmen gekapselt und wiederverwendet werden können. In diesem Artikel wird ein Vorlagenmechanismus für JavaServer Pages (JSP) erläutert, der wie Layout-Manager das Layout kapselt, damit es wiederverwendet und nicht repliziert werden kann.

Da das Layout im Laufe der Entwicklung viele Änderungen erfährt, ist es wichtig, diese Funktionalität zu kapseln, damit sie mit minimalen Auswirkungen auf den Rest der Anwendung geändert werden kann. In der Tat demonstrieren Layout-Manager ein Beispiel für einen der Grundsätze des objektorientierten Designs: Fassen Sie das unterschiedliche Konzept zusammen, das auch für viele Designmuster ein grundlegendes Thema ist.

JSP bietet keine direkte Unterstützung für die Kapselung von Layouts. Daher replizieren Webseiten mit identischen Formaten normalerweise Layoutcode. Abbildung 1 zeigt beispielsweise eine Webseite mit Kopf-, Fuß-, Seitenleisten- und Hauptinhaltsabschnitten.

Das Layout der in Abbildung 1 gezeigten Seite wird mit HTML-Tabellen-Tags implementiert:

Beispiel 1. Einschließlich Inhalt

JSP-Vorlagen  
   
<% @ include file = "sidebar.html"%>
<% @ include file = "header.html"%>
<% @ include file = "Introduction.html"%>
<% @ include file = "footer.html"%>

In dem oben aufgeführten Beispiel ist der Inhalt in der JSP- includeDirektive enthalten, wodurch der Inhalt der Seite durch Ändern der enthaltenen Dateien geändert werden kann, ohne die Seite selbst zu ändern. Da das Layout jedoch fest codiert ist, erfordern Layoutänderungen Änderungen an der Seite. Wenn eine Website mehrere Seiten mit identischen Formaten hat, was üblich ist, erfordern selbst einfache Layoutänderungen Änderungen an allen Seiten.

Um die Auswirkungen von Layoutänderungen zu minimieren, benötigen wir einen Mechanismus, um neben dem Inhalt auch das Layout einzubeziehen. Auf diese Weise können sowohl Layout als auch Inhalt variieren, ohne die Dateien zu ändern, die sie verwenden. Dieser Mechanismus sind JSP-Vorlagen.

Vorlagen verwenden

Vorlagen sind JSP-Dateien, die parametrisierten Inhalt enthalten. Die Vorlagen in diesem Artikel beschrieben werden , mit einer Reihe von benutzerdefinierten Tags implementiert: template:get, template:put, und template:insert. Das template:getTag greift auf parametrisierten Inhalt zu, wie in Beispiel 2.a dargestellt, wodurch Webseiten mit dem in Abbildung 1 gezeigten Format erstellt werden.

Beispiel 2.a. Eine Vorlage

< template: get name = "title" />
   
< template: get name = "header" />

Beispiel 2.a ist nahezu identisch mit Beispiel 1, außer dass wir template:getanstelle der includeDirektive verwenden. Lassen Sie uns untersuchen, wie es template:getfunktioniert.

template:getRuft eine Java-Bean mit dem angegebenen Namen aus dem Anforderungsbereich ab. Die Bean enthält den URI (Uniform Resource Identifier) ​​einer Webkomponente, die von enthalten ist template:get. In der in Beispiel 2.a aufgelisteten Vorlage wird beispielsweise template:getein URI - header.html- von einer headerim Anforderungsbereich benannten Bean abgerufen . Anschließend template:getenthält header.html.

template:putSetzt die Beans in den Anforderungsbereich, der anschließend von abgerufen wird template:get. Die Vorlage ist im Lieferumfang enthalten template:insert. Beispiel 2.b veranschaulicht die Verwendung der Tags putund insert:

Beispiel 2.b. Verwenden der Vorlage aus Beispiel 2.a.

   
    insert template = "/ articleTemplate.jsp">
    
     put name = "title" content = "Templates" direct = "true" />
     
      put name = "header" content = "/ header.html" />
      
       put name = "sidebar" content = "/ sidebar.jsp" />
       
        put name = "content" content = "/ Introduction.html" />
        
         put name = "footer" content = "/ footer.html" />
        
       
      
     
    
   

Das insertStart-Tag gibt die Vorlage an, die aufgenommen werden soll, in diesem Fall die in Beispiel 2.a. Jedes putTag speichert eine Bean im Anforderungsbereich und das insertEnd-Tag enthält die Vorlage. Die Vorlage greift anschließend wie oben beschrieben auf die Beans zu.

Ein directAttribut kann angegeben werden für template:put; Wenn diese directOption auf gesetzt ist true, wird der mit dem Tag verknüpfte Inhalt nicht von eingeschlossen template:get, sondern direkt in die implizite outVariable gedruckt . In Beispiel 2.b wird beispielsweise der Titelinhalt - JSP-Vorlagen - für den Fenstertitel verwendet.

Websites mit mehreren Seiten mit identischen Formaten haben eine Vorlage, wie die in Beispiel 2.a aufgeführte, und viele JSP-Seiten, wie beispielsweise Beispiel 2.b, die die Vorlage verwenden. Wenn das Format geändert wird, sind die Änderungen auf die Vorlage beschränkt.

Ein weiterer Vorteil von Vorlagen und Inhalten im Allgemeinen ist der modulare Aufbau. Zum Beispiel enthält header.htmldie in Beispiel 2.b aufgeführte JSP-Datei letztendlich das in Beispiel 2.c aufgeführte.

Beispiel 2.c. header.html

   

Da header.htmlder Inhalt enthalten ist, muss er nicht auf Seiten repliziert werden, auf denen eine Kopfzeile angezeigt wird. Obwohl header.htmles sich um eine HTML-Datei handelt, enthält sie nicht die übliche Präambel von HTML-Tags, z. B. oder weil diese Tags von der Vorlage definiert werden. Das heißt, da die Vorlage enthält header.html, sollten diese Tags nicht wiederholt werden header.html.

Hinweis: JSP bietet zwei Möglichkeiten, Inhalte einzuschließen: statisch, mit der includeDirektive und dynamisch mit der includeAktion. Die includeDirektive enthält die Quelle der Zielseite zur Kompilierungszeit und entspricht C #includeoder Java import. Die includeAktion enthält die zur Laufzeit generierte Antwort des Ziels.

Like the JSP include action, templates include content dynamically. So, although the JSP pages in Example 1 and Example 2.b are functionally identical, the former statically includes content, whereas the latter dynamically includes it.

Optional content

All template content is optional, which makes a single template useful to more Webpages. For example, Figure 2.a and Figure 2.b show two pages -- login and inventory -- that use the same template. Both pages have a header, footer, and main content. The inventory page has an edit panel (which the login page lacks) for making inventory changes.

Below, you'll find the template shared by the login and inventory pages:

 ... 
   
name='editPanel'/>
...

The inventory page uses the template listed above and specifies content for the edit panel:

   ... 
    ...  

In contrast, the login page does not specify content for the edit panel:


  

Because the login page does not specify content for the edit panel, it's not included.

Role-based content

Web applications often discriminate content based on a user's role. For example, the same JSP template, which includes the edit panel only when the user's role is curator, produces the two pages shown in Figures 3.a and 3.b.

The template used in Figures 3.a and 3.b uses template:get's role attribute:

 ... 
   
     ... 
     ... 
    
role='curator'/>
...

The get tag includes content only if the user's role matches the role attribute. Let's look at how the tag handler for template:get uses the role attribute:

public class GetTag extends TagSupport { private String name = null, role = null; ... public void setRole(String role) { this.role = role; } ... public int doStartTag() throws JspException { ... if(param != null) { if(roleIsValid()) { // include or print content ... } } ... } private boolean roleIsValid()  } 

Implementing templates

The templates discussed in this article are implemented with three custom tags:

  • template:insert
  • template:put
  • template:get

The insert tag includes a template, but before it does, put tags store information -- a name, URI, and Boolean value specifying whether content should be included or printed directly -- about the content the template includes. template:get, which includes (or prints) the specified content, subsequently accesses the information.

template:put stores beans in request scope but not directly because if two templates use the same content names, a nested template could overwrite the enclosing template's content.

To ensure that each template has access only to its own information, template:insert maintains a stack of hashtables. Each insert start tag creates a hashtable and pushes it on the stack. The enclosed put tags create beans and store them in the newly created hashtable. Subsequently, get tags in the included template access the beans in the hashtable. Figure 4 shows how the stack is maintained for nested templates.

Each template in Figure 4 accesses the correct footer; footer.html for template_1.jsp and footer_2.html for template_2.jsp. If the beans were stored directly in request scope, step 5 in Figure 4 would overwrite the footer bean specified in step 2.

Template tag implementations

The remainder of this article examines the implementation of the three template tags: insert, put, and get. We begin with sequence diagrams, starting with Figure 5. It illustrates the sequence of events for the insert and put tags when a template is used.

If a template stack does not already exist, the insert start tag creates one and places it in request scope. A hashtable is subsequently created and pushed on the stack.

Jedes putStart-Tag erstellt eine PageParameterBean, die in der vom umschließenden insertTag erstellten Hashtabelle gespeichert ist .

Das Insert- endTag enthält die Vorlage. Die Vorlage verwendet getTags, um auf die von putTags erstellten Beans zuzugreifen . Nachdem die Vorlage verarbeitet wurde, wird die vom insertStart-Tag erstellte Hashtabelle vom Stapel entfernt.

Abbildung 6 zeigt das Sequenzdiagramm für template:get.

Vorlagen-Tag-Listen

Tag-Handler-Implementierungen für die Vorlagen-Tags sind unkompliziert. Beispiel 3.a listet die InsertTagKlasse auf - den Tag-Handler für template:insert.

Beispiel 3.a. InsertTag.java