Szablony JSP

Chociaż narzędzia do tworzenia aplikacji internetowych szybko się rozwijają, nadal pozostają w tyle za większością zestawów narzędzi graficznego interfejsu użytkownika (GUI), takich jak Swing czy VisualWorks Smalltalk. Na przykład tradycyjne zestawy narzędzi GUI zapewniają menedżerów układu, w takiej czy innej formie, które pozwalają na hermetyzację i ponowne wykorzystanie algorytmów układu. W tym artykule omówiono mechanizm szablonów dla stron JavaServer (JSP), który podobnie jak menedżerowie układu hermetyzuje układ, dzięki czemu można go ponownie wykorzystać zamiast replikować.

Ponieważ układ podlega wielu zmianom w trakcie programowania, ważne jest, aby hermetyzować tę funkcjonalność, aby można ją było modyfikować przy minimalnym wpływie na pozostałą część aplikacji. W rzeczywistości menedżerowie układu przedstawiają przykład jednej z zasad projektowania zorientowanego obiektowo: ujmują koncepcję, która jest zmienna, co jest również podstawowym tematem wielu wzorców projektowych.

JSP nie zapewnia bezpośredniej obsługi hermetyzacji układu, więc strony internetowe o identycznych formatach zwykle replikują kod układu; na przykład Rysunek 1 przedstawia stronę internetową zawierającą sekcje nagłówka, stopki, paska bocznego i głównej treści.

Układ strony pokazany na rysunku 1 jest zaimplementowany za pomocą znaczników tabeli HTML:

Przykład 1. Włączanie treści

Szablony JSP  
   
<% @ include file = "sidebar.html"%>
<% @ include file = "header.html"%>
<% @ include file = "wprowadzenie.html"%>
<% @ include file = "footer.html"%>

W powyższym przykładzie zawartość jest uwzględniona w includedyrektywie JSP , która umożliwia zmianę zawartości strony - poprzez zmianę dołączonych plików - bez modyfikowania samej strony. Jednak ponieważ układ jest zakodowany na stałe, zmiany układu wymagają modyfikacji strony. Jeśli witryna ma wiele stron o identycznych formatach, co jest powszechne, nawet proste zmiany układu wymagają modyfikacji wszystkich stron.

Aby zminimalizować wpływ zmian układu, potrzebujemy mechanizmu dołączania układu oprócz treści; w ten sposób zarówno układ, jak i zawartość mogą się różnić bez modyfikowania plików, które ich używają. Tym mechanizmem są szablony JSP.

Korzystanie z szablonów

Szablony to pliki JSP zawierające sparametryzowaną zawartość. Szablony omówione w tym artykule są realizowane z zestawem niestandardowych tagach: template:get, template:put, i template:insert. template:getZnacznik dostęp sparametryzowanego treści, jak to pokazano w przykładzie 2.a, który wytwarza Strony WWW o formacie przedstawionym na fig. 1.

Przykład 2.a. Szablon

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

Przykład 2.a jest prawie identyczny z przykładem 1, z wyjątkiem tego, że używamy template:getzamiast includedyrektywy. Przyjrzyjmy się, jak to template:getdziała.

template:getpobiera komponent bean Java o określonej nazwie z zakresu żądania. Komponent bean zawiera URI (Uniform Resource Identifier) ​​składnika sieci Web, który jest uwzględniony w template:get. Na przykład w szablonie wymienionym w przykładzie 2.a template:getuzyskuje identyfikator URI - header.html- z komponentu bean nazwanego headerw zakresie żądania. Następnie template:getobejmuje header.html.

template:putumieszcza ziarna w zakresie żądania, które są następnie pobierane przez template:get. Szablon jest dołączony do template:insert. Przykład 2.b ilustruje użycie tagów puti insert:

Przykład 2.b. Korzystając z szablonu z przykładu 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" />
        
       
      
     
    
   

Znacznik insertpoczątkowy określa szablon, który ma zostać uwzględniony, w tym przypadku szablon wymieniony w przykładzie 2.a. Każdy puttag przechowuje komponent bean w zakresie żądania, a inserttag końcowy zawiera szablon. Szablon następnie uzyskuje dostęp do ziaren, jak opisano powyżej.

directAtrybut może być określony template:put; jeśli directjest ustawiona na true, zawartość powiązana ze znacznikiem nie jest uwzględniana przez template:get, ale jest drukowana bezpośrednio w niejawnej outzmiennej. Na przykład w przykładzie 2.b treść tytułu - Szablony JSP - jest używana jako tytuł okna.

Witryny zawierające wiele stron o identycznych formatach mają jeden szablon, taki jak ten wymieniony w przykładzie 2.a, i wiele stron JSP, takich jak przykład 2.b, które korzystają z tego szablonu. Jeśli format zostanie zmodyfikowany, zmiany są ograniczone do szablonu.

Kolejną zaletą szablonów i ogólnie włączania treści jest konstrukcja modułowa. Na przykład plik JSP wymieniony w przykładzie 2.b ostatecznie zawiera elementy header.htmlwymienione w przykładzie 2.c.

Przykład 2.c. header.html

   

Ponieważ header.htmljest zawartością, nie musi być replikowana między stronami wyświetlającymi nagłówek. Ponadto, chociaż header.htmljest to plik HTML, nie zawiera zwykłej preambuły znaczników HTML, takich jak lub ponieważ te tagi są zdefiniowane przez szablon. To znaczy, ponieważ szablon zawiera header.html, te tagi nie powinny być powtarzane w header.html.

Uwaga: JSP umożliwia dołączanie treści na dwa sposoby: statycznie za pomocą includedyrektywy i dynamicznie za pomocą includeakcji. includeDyrektywa zawiera źródło strony docelowej w czasie kompilacji i odpowiada na C #includelub Java import. includeAkcja obejmuje reakcję przez cel generowane w czasie wykonywania.

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.

Każdy puttag początkowy tworzy PageParameterfasolę, przechowywaną w tablicy hashy utworzonej przez otaczający inserttag.

Znacznik wstawiania endzawiera szablon. Szablon używa gettagów, aby uzyskać dostęp do komponentów bean utworzonych za pomocą puttagów. Po przetworzeniu szablonu tablica hashy utworzona przez inserttag startowy jest zdejmowana ze stosu.

Rysunek 6 przedstawia diagram sekwencji dla template:get.

Lista tagów szablonów

Implementacje obsługi tagów dla tagów szablonu okazują się proste. Przykład 3. a wymienia InsertTagklasę - procedurę obsługi znacznika dla template:insert.

Przykład 3.a. InsertTag.java