JSP шаблони

Въпреки че инструментите за уеб разработка бързо напредват, те все още изостават от повечето инструменти с графичен потребителски интерфейс (GUI), като Swing или VisualWorks Smalltalk. Например, традиционните GUI набори от инструменти предоставят мениджъри на оформление, под една или друга форма, които позволяват алгоритмите за оформление да бъдат капсулирани и използвани повторно. Тази статия изследва шаблонния механизъм за JavaServer Pages (JSP), който, подобно на мениджърите на оформления, капсулира оформлението, за да може да се използва повторно, вместо да се репликира.

Тъй като оформлението претърпява много промени в хода на разработката, важно е да се капсулира тази функционалност, така че да може да бъде модифицирана с минимално въздействие върху останалата част от приложението. Всъщност мениджърите на оформление демонстрират пример за един от принципите на обектно-ориентирания дизайн: капсулирайте концепцията, която варира, което също е основна тема за много дизайнерски модели.

JSP не осигурява директна поддръжка за капсулиране на оформление, така че уеб страниците с идентични формати обикновено репликират кода на оформлението; например, Фигура 1 показва уеб страница, съдържаща раздели на заглавка, долен колонтитул, странична лента и основно съдържание.

Оформлението на страницата, показано на фигура 1, е изпълнено с HTML тагове на таблицата:

Пример 1. Включване на съдържание

JSP шаблони  
   
<% @ include file = "sidebar.html"%>
<% @ include file = "header.html"%>
<% @ include file = "uvod.html"%>
<% @ include file = "footer.html"%>

В изброения по-горе пример съдържанието е включено в includeдирективата JSP , което позволява на съдържанието на страницата да варира - чрез промяна на включените файлове - без промяна на самата страница. Тъй като обаче оформлението е трудно кодирано, промените в оформлението изискват модификации на страницата. Ако даден уебсайт има множество страници с еднакви формати, което е често срещано, дори простите промени в оформлението изискват модификации на всички страници.

За да сведем до минимум въздействието от промените в оформлението, имаме нужда от механизъм за включване на оформление в допълнение към съдържанието; по този начин и оформлението, и съдържанието могат да варират, без да се променят файлове, които ги използват. Този механизъм са JSP шаблони.

Използване на шаблони

Шаблоните са JSP файлове, които включват параметризирано съдържание. Разглежданите в тази статия шаблоните се изпълняват с набор от потребителски тагове: template:get, template:put, и template:insert. В template:getмаркера достъп параметризиран съдържание, както е показано в Пример 2.а, която произвежда уеб страници с формата, показана на фигура 1.

Пример 2.а. Шаблон

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

Пример 2.a е почти идентичен с пример 1, с изключение на това, че използваме template:getвместо includeдирективата. Нека разгледаме как template:getработи.

template:getизвлича Java боб с посоченото име от обхвата на заявката. Бобът съдържа URI (Uniform Resource Identifier) ​​на уеб компонент, който е включен от template:get. Например в шаблона, изброен в Пример 2.а, template:getполучава URI - header.html- от боб, посочен headerв обхвата на заявката. Впоследствие template:getвключва header.html.

template:putпоставя зърната в обхвата на заявката, които впоследствие се извличат от template:get. Шаблонът е включен в template:insert. Пример 2.b илюстрира използването на putи insertмаркерите:

Пример 2.б. Използване на шаблона от пример 2.а

   
    вмъкнете шаблон = "/ articleTemplate.jsp">
    
     put name = "title" content = "Templates" direct = "true" />
     
      поставете name = "header" content = "/ header.html" />
      
       поставете name = "sidebar" content = "/ sidebar.jsp" />
       
        поставете name = "content" content = "/ uvod.html" />
        
         поставете name = "footer" content = "/ footer.html" />
        
       
      
     
    
   

На insertуточнява началния етикет шаблона, за да бъдат включени в този случай шаблона, изброени в Пример 2.а. Всеки putмаркер съхранява боб в обхвата на заявката, а insertкрайният маркер включва шаблона. Впоследствие шаблонът получава достъп до зърната, както е описано по-горе.

А directатрибут може да бъде определен за template:put; ако directе зададено на true, съдържанието, свързано с маркера, не се включва от template:get, а се отпечатва директно към неявната outпроменлива. В пример 2.b например съдържанието на заглавието - JSP Templates - се използва за заглавието на прозореца.

Уебсайтовете, съдържащи множество страници с еднакви формати, имат един шаблон, като този, изброен в Пример 2.a, и много JSP страници, като Пример 2.b, които използват шаблона. Ако форматът е модифициран, промените са ограничени до шаблона.

Друго предимство на шаблоните и на съдържанието като цяло е модулният дизайн. Например JSP файлът, изброен в Пример 2.b, в крайна сметка включва header.html, изброен в Пример 2.c.

Пример 2.в. header.html

   

Because header.html is included content, it does not have to be replicated among pages that display a header. Also, although header.html is an HTML file, it does not contain the usual preamble of HTML tags such as or because those tags are defined by the template. That is, because the template includes header.html, those tags should not be repeated in header.html.

Note: JSP provides two ways to include content: statically, with the include directive, and dynamically, with the include action. The include directive includes the source of the target page at compile time and is equivalent to C's #include or Java's import. The include action includes the target's response generated at runtime.

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.

Всеки putначален таг създава PageParameterбоб, съхраняван в хеш-таблицата, създадена от заграждащия insertтаг.

endТагът за вмъкване включва шаблона. Шаблонът използва getмаркери за достъп до зърната, създадени от putтагове. След като шаблонът бъде обработен, хеш-таблицата, създадена от insertначалния таг, се изскача от стека.

Фигура 6 показва диаграмата на последователността за template:get.

Списъци с маркери на шаблони

Реализациите на манипулатора на маркери за маркерите на шаблони се оказват ясни. Пример 3.а изброява InsertTagкласа - обработващия етикет за template:insert.

Пример 3.а. InsertTag.java