Modelli JSP

Sebbene gli strumenti di sviluppo Web stiano progredendo rapidamente, sono ancora in ritardo rispetto alla maggior parte dei toolkit dell'interfaccia utente grafica (GUI) come Swing o VisualWorks Smalltalk. Ad esempio, i tradizionali toolkit GUI forniscono gestori di layout, in una forma o nell'altra, che consentono di incapsulare e riutilizzare gli algoritmi di layout. Questo articolo esplora un meccanismo di modelli per JavaServer Pages (JSP) che, come i gestori di layout, incapsula il layout in modo che possa essere riutilizzato anziché replicato.

Poiché il layout subisce molte modifiche nel corso dello sviluppo, è importante incapsulare tale funzionalità in modo che possa essere modificata con un impatto minimo sul resto dell'applicazione. Infatti, i gestori di layout dimostrano un esempio di uno dei principi del design orientato agli oggetti: incapsulare il concetto che varia, che è anche un tema fondamentale per molti modelli di design.

JSP non fornisce supporto diretto per l'incapsulamento del layout, quindi le pagine Web con formati identici di solito replicano il codice del layout; ad esempio, la Figura 1 mostra una pagina Web contenente intestazione, piè di pagina, barra laterale e sezioni di contenuto principale.

Il layout della pagina mostrato nella Figura 1 è implementato con tag di tabella HTML:

Esempio 1. Contenuto incluso

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

Nell'esempio sopra elencato, il contenuto è incluso con la includedirettiva JSP , che consente al contenuto della pagina di variare, modificando i file inclusi, senza modificare la pagina stessa. Tuttavia, poiché il layout è hardcoded, le modifiche al layout richiedono modifiche alla pagina. Se un sito Web ha più pagine con formati identici, il che è comune, anche le semplici modifiche al layout richiedono modifiche a tutte le pagine.

Per ridurre al minimo l'impatto delle modifiche al layout, abbiamo bisogno di un meccanismo per includere il layout oltre al contenuto; in questo modo, sia il layout che il contenuto possono variare senza modificare i file che li utilizzano. Questo meccanismo sono i modelli JSP.

Utilizzo di modelli

I modelli sono file JSP che includono contenuto parametrizzato. I modelli descritti in questo articolo sono implementati con un insieme di tag personalizzati: template:get, template:put, e template:insert. Il template:gettag accede al contenuto parametrizzato, come illustrato nell'Esempio 2.a, che produce pagine Web con il formato mostrato nella Figura 1.

Esempio 2.a. Un modello

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

L'Esempio 2.a è quasi identico all'Esempio 1, eccetto che usiamo al template:getposto della includedirettiva. Esaminiamo come template:getfunziona.

template:getrichiama un bean Java con il nome specificato dall'ambito della richiesta. Il bean contiene l'URI (Uniform Resource Identifier) ​​di un componente Web incluso da template:get. Ad esempio, nel modello elencato nell'Esempio 2.a, template:getottiene un URI - header.html- da un bean denominato headernell'ambito della richiesta. Successivamente, template:getinclude header.html.

template:putinserisce i bean nell'ambito della richiesta che vengono successivamente recuperati da template:get. Il modello è incluso con template:insert. L'esempio 2.b illustra l'uso dei tag pute insert:

Esempio 2.b. Utilizzando il modello dell'Esempio 2.a

   
    inserire 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" />
        
       
      
     
    
   

Il inserttag di inizio specifica il modello da includere, in questo caso il modello elencato nell'Esempio 2.a. Ogni puttag memorizza un bean nell'ambito della richiesta e il inserttag di fine include il modello. Il modello successivamente accede ai bean come descritto sopra.

È directpossibile specificare un attributo per template:put; se directè impostato a true, il contenuto associato al tag non viene incluso da template:get, ma viene stampato direttamente sulla outvariabile implicita . Nell'Esempio 2.b, ad esempio, il contenuto del titolo - JSP Templates - viene utilizzato per il titolo della finestra.

I siti web che contengono più pagine con formati identici hanno un modello, come quello elencato nell'Esempio 2.a, e molte pagine JSP, come l'Esempio 2.b, che utilizzano il modello. Se il formato viene modificato, le modifiche sono limitate al modello.

Un altro vantaggio dei modelli e dell'inclusione del contenuto in generale è il design modulare. Ad esempio, il file JSP elencato nell'Esempio 2.b alla fine include header.html, elencato nell'Esempio 2.c.

Esempio 2.c. header.html

   

Poiché header.htmlè contenuto incluso, non deve essere replicato tra le pagine che visualizzano un'intestazione. Inoltre, sebbene header.htmlsia un file HTML, non contiene il solito preambolo dei tag HTML come o perché quei tag sono definiti dal modello. Cioè, poiché il modello include header.html, quei tag non dovrebbero essere ripetuti in header.html.

Nota: JSP fornisce due modi per includere il contenuto: staticamente, con la includedirettiva e dinamicamente, con l' includeazione. La includedirettiva include l'origine della pagina di destinazione in fase di compilazione ed è equivalente a C #includeo Java import. L' includeazione include la risposta del target generata in fase di esecuzione.

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.

Ogni puttag iniziale crea un PageParameterbean, memorizzato nella tabella hash creata dal inserttag che lo racchiude .

Il endtag di inserimento include il modello. Il modello utilizza i gettag per accedere ai bean creati dai puttag. Dopo che il modello è stato elaborato, la tabella hash creata dal inserttag di inizio viene estratta dallo stack.

La Figura 6 mostra il diagramma di sequenza per template:get.

Elenchi di tag modello

Le implementazioni del gestore di tag per i tag del modello si dimostrano semplici. L'esempio 3.a elenca la InsertTagclasse - il gestore di tag per template:insert.

Esempio 3.a. InsertTag.java