תבניות JSP

למרות שכלי פיתוח אתרים מתקדמים במהירות, הם עדיין פיגור מאחורי ערכות הכלים הגרפיות של ממשק המשתמש (GUI) כגון Swing או VisualWorks Smalltalk. לדוגמה, ערכות כלים GUI מסורתיות מספקות מנהלי פריסות, בצורה כזו או אחרת, המאפשרים לכמוס ולהשתמש בהם מחדש באלגוריתמים של פריסה. מאמר זה בוחן מנגנון תבנית עבור דפי JavaServer (JSP) שכמו מנהלי פריסות, מקפל את הפריסה כך שניתן יהיה לעשות בה שימוש חוזר במקום לשכפל.

מכיוון שהפריסה עוברת שינויים רבים במהלך הפיתוח, חשוב לתמצת את הפונקציונליות הזו כדי שניתן יהיה לשנות אותה עם השפעה מינימלית על שאר היישום. למעשה, מנהלי פריסות מדגימים דוגמה לאחד מעקרונות העיצוב מונחה האובייקטים: סוגרים את הרעיון המשתנה, שהוא גם נושא בסיסי לדפוסי עיצוב רבים.

JSP אינו מספק תמיכה ישירה בהכמסת פריסה, ולכן דפי אינטרנט עם פורמטים זהים בדרך כלל משכפלים את קוד הפריסה; לדוגמא, איור 1 מציג דף אינטרנט המכיל קטעי כותרת עליונה, תחתונה, סרגל צד ותוכן ראשי.

הפריסה של העמוד שמוצג באיור 1 מיושמת עם תגי טבלת HTML:

דוגמא 1. כולל תוכן

תבניות JSP  
   
<% @ include file = "sidebar.html"%>
<% @ include file = "header.html"%>
<% @ include file = "הקדמה.html"%>
<% @ include file = "footer.html"%>

בדוגמה המפורטת לעיל, התוכן נכלל includeבהוראת JSP , המאפשרת לשנות את תוכן הדף - על ידי שינוי הקבצים הכלולים - מבלי לשנות את הדף עצמו. עם זאת, מכיוון שהפריסה מקודדת קשה, שינויי פריסה דורשים שינויים בדף. אם באתר יש מספר עמודים עם פורמטים זהים, דבר שכיח, אפילו שינויים פשוטים בפריסה דורשים שינויים בכל הדפים.

כדי למזער את ההשפעה של שינויים בפריסה, אנו זקוקים למנגנון הכללת פריסה בנוסף לתוכן; בדרך זו, הן הפריסה והן התוכן יכולים להשתנות מבלי לשנות קבצים המשתמשים בהם. מנגנון זה הוא תבניות JSP.

שימוש בתבניות

תבניות הן קבצי JSP הכוללים תוכן פרמטרי. התבניות שנדונו במאמר זה מיושמות עם סט של תגים מותאמים אישית: template:get, template:put, ו template:insert. template:getתג גישה לתוכן פרמטרים, כפי שמודגם 2.א דוגמה, המייצר דפי אינטרנט עם הפורמט שמוצג באיור 1.

דוגמה 2.a. תקיה

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

דוגמה 2. א כמעט זהה לדוגמא 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.ב הדוגמה ממחיש את השימוש putואת insertהתגים:

דוגמה 2. ב. שימוש בתבנית מדוגמה 2. א

   
    הכנס תבנית = "/ articleTemplate.jsp">
    
     put name = "title" content = "תבניות" direct = "true" />
     
      שם שם = "כותרת" content = "/ header.html" />
      
       שם שם = "סרגל צד" content = "/ sidebar.jsp" />
       
        לשים שם = "תוכן" תוכן = "/ הקדמה.html" />
        
         שם שם = "כותרת תחתונה" תוכן = "/ כותרת תחתונה.html" />
        
       
      
     
    
   

insertתג ההתחלה מציינת את התבנית להיכלל, במקרה זה את התבנית מפורטת דוגמא 2.a. כל putתג מאחסן שעועית בהיקף הבקשה insertותג הקצה כולל את התבנית. לאחר מכן התבנית ניגשת לשעועית כמתואר לעיל.

directתכונה ניתן להגדיר עבור template:put; אם directמוגדר כ- true, התוכן המשויך לתג אינו נכלל על ידי template:get, אלא מודפס ישירות outלמשתנה הגלום . בדוגמה 2.b, למשל, תוכן הכותרת - תבניות JSP - משמש לכותרת החלון.

אתרים המכילים מספר עמודים עם פורמטים זהים כוללים תבנית אחת, כמו זו המופיעה בדוגמה 2. א, ודפי JSP רבים, כגון דוגמה 2. ב ', המשתמשים בתבנית. אם הפורמט משתנה, השינויים מוגבלים לתבנית.

יתרון נוסף של תבניות וכולל תוכן באופן כללי הוא עיצוב מודולרי. לדוגמה, קובץ JSP המופיע בדוגמה 2.b כולל בסופו של דבר את header.htmlהרשימה בדוגמה 2.c.

דוגמה 2.c. header.html

   

מכיוון header.htmlשתוכן כלול, אין צורך לשכפל אותו בין דפים המציגים כותרת. כמו כן, למרות header.htmlשמדובר בקובץ HTML, הוא אינו מכיל את ההקדמה הרגילה של תגי HTML כגון או משום שתגים אלה מוגדרים על ידי התבנית. כלומר מכיוון שהתבנית כוללת header.html, אין לחזור על התגים הללו header.html.

הערה: JSP מספק שתי דרכים לכלול תוכן: באופן סטטי, עם includeההנחיה, ודינמית, עם includeהפעולה. includeההוראה כוללת את המקור של דף היעד בזמן ההידור, והיא זהה C של #includeאו ג'אווה של import. includeהפעולה כוללת את תשובת היעד שנוצרה בזמן ריצה.

כמו includeפעולת JSP , גם תבניות כוללות תוכן באופן דינמי. לכן, למרות שעמודי JSP בדוגמה 1 ובדוגמה 2.b זהים מבחינה פונקציונלית, הראשון כולל באופן סטטי תוכן, ואילו האחרונים כוללים אותו באופן דינמי.

תוכן אופציונלי

כל תוכן התבנית הוא אופציונלי, מה שהופך תבנית אחת שימושית לדפי אינטרנט רבים יותר. לדוגמה, איור 2. א 'ואיור 2. ב' מציגים שני עמודים - כניסה ומלאי - המשתמשים באותה תבנית. בשני העמודים יש כותרת עליונה, כותרת תחתונה ותוכן ראשי. בדף המלאי יש לוח עריכה (שדף הכניסה חסר) לביצוע שינויים במלאי.

להלן תמצא את התבנית המשותפת לדפי הכניסה והמלאי:

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

דף המלאי משתמש בתבנית המפורטת לעיל ומציין תוכן עבור לוח העריכה:

   ... 
    ...  

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שעועית, המאוחסנת בטבלה hasht שנוצרה על ידי insertהתג הסוגר .

endתגית ההוספה כוללת את התבנית. התבנית משתמשת getבתגים כדי לגשת לשעועית שנוצרה על ידי putתגים. לאחר עיבוד התבנית, ה- hashtable שנוצר על ידי insertתג ההתחלה מוצג מעל הערימה.

איור 6 מציג את תרשים הרצף עבור template:get.

רישומי תגי תבניות

יישומי מטפלות תגים עבור תגי התבנית מוכיחים את עצמם בצורה פשוטה. רשימות 3.א למשל InsertTagבכיתה - מטפל התג עבור template:insert.

דוגמה 3.a. InsertTag.java