מה זה JSF? הכירו את פנים JavaServer

JavaServer Faces (JSF) היא הטכנולוגיה הסטנדרטית של Java לבניית ממשקי אינטרנט מבוססי רכיבים ומכוונים לאירועים. כמו JavaServer Pages (JSP), JSF מאפשר גישה לנתונים ולוגיקה בצד השרת. בניגוד ל- JSP, שהוא למעשה דף HTML חדור יכולות בצד השרת, JSF הוא מסמך XML המייצג רכיבים פורמליים בעץ לוגי. רכיבי JSF מגובים על ידי אובייקטים של Java, שאינם תלויים ב- HTML ויש להם את כל היכולות של Java, כולל גישה לממשקי API מרוחקים ולמאגרי מידע.

הרעיון המרכזי למסגרת כמו JSF הוא לצרף (או לעטוף ) טכנולוגיות בצד הלקוח כמו HTML, CSS ו- JavaScript, מה שמאפשר למפתחים לבנות ממשקי אינטרנט ללא אינטראקציה רבה עם טכנולוגיות אלה.

מאמר זה מציג תמונת מצב של גישת JSF לפיתוח ממשק משתמש מבוסס רכיבים עבור יישומי אינטרנט בג'אווה. דוגמאות פשוטות מציגות את ארכיטקטורת ה- MVC של JSF, את מודל האירועים ואת ספריית הרכיבים. דוגמאות כוללות תכונות חדשות ב- JSF 2.3, ואנחנו נשתמש ב- PrimeFaces לספריית הרכיבים שלנו.

JSF מתפתח

זמן רב פופולרי, JSF נתקל לאחרונה בתחרות ממסגרות אינטרנט תואמות Java, כולל מסגרות JavaScript מצד הלקוח. ובכל זאת, JavaServer Faces נשאר תקן Java, במיוחד לפיתוח ארגוני Java בקנה מידה גדול. המפרט של JSF הוליד גם שפע של מסגרות וספריות, אשר עמדו בקצב עם השיפורים האחרונים בצד הלקוח. אחד מהם הוא PrimeFaces, אותו אנו חוקרים במדריך זה.

לוח הזמנים לפיתוח עתידי אינו ברור, אך JSF 2.3 מעניק למפתחים הרבה לעבוד איתו בזמן שאנחנו מחכים. JSF 2.3 שוחרר במרץ 2017 ותוכנן בכוונה לחדש את JSF. בין כמה מאות תיקונים קטנים ועדכונים גדולים יותר, JSF 2.3 מבטל הערות שעועית מנוהלות לטובת CDI, אותם אציג בהמשך הדרכה זו.

JSF 2.3 בג'קרטה EE

בספטמבר 2017 הודיעה אורקל על כוונתה להעביר את Java EE לקרן Eclipse. Java EE הותאם מאז לג'קרטה EE, ו- JSF 2.3 (Eclipse Mojarra) אומץ להמשך. המהדורה הגדולה הבאה של מפרט JSF תהיה Eclipse Mojarra 3.0.

בניית ממשקי אינטרנט מבוססי רכיבים ב- JSF

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

אמנם אתה יכול להשתמש בעמודי JSF בתוך דפי JavaServer, אך נפוץ יותר להשתמש ב- Facelets לבניית דפי JSF עצמאיים. פנים הם עמודי XHTML המיועדים להגדרת ממשקי JSF. באמצעות Facelets, אתה משתמש בתגי XML כדי ליצור עץ רכיב שהופך לפיגום עבור ממשק משתמש JSF.

רישום 1 מציג את החלקים העיקריים של דף JSF פשוט שנכתב באמצעות Facelets. בדוגמה זו אנו ניגשים ליכולות צד השרת של ג'אווה באמצעות שעועית שהונחה בהיקף באמצעות CDI. תראה מידע נוסף על CDI בהמשך.

רישום 1. דף לדוגמא של JSF

    Hello JavaWorld!   #{javaBean.content}  

ברשימה 1 אנו רואים דף XHTML רגיל. תצוגת Facelets בנויה על גבי XHTML. בנוסף למרחב השמות XHTML, מוגדר ומפנה מרחב שמות משני.

hהספרייה מכילה רכיבים סטנדרטיים לשימוש בדפי HTML JSF. //xmlns.jcp.org/jsf/htmlהספרייה מגדירה אוסף של רכיבי JSF, במקרה זה אוסף של רכיבי HTML משותפים. אחד המרכיבים הללו הוא היסוד.

רכיבי HTML ב- JSF

מבחינת תחביר, רכיב רישום 1 מפנה jsf/htmlלספריה עם hהקידומת. לאחר מכן הוא מפנה לרכיב הספציפי בספרייה, שהוא headהרכיב.

רכיב תפוקות אלמנט ראש HTML. (כל התחביר הזה יכול להיראות כמו מיצוי יתר למטרה כל כך פשוטה, אבל יש לכך סיבה טובה, כפי שתראה בקרוב.)

רכיבי קינון

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

בגוף המסמך, ביטוי JSF מכיל את #{}התחביר. זה מקביל בדיוק לביטוי JSP עם ${}הפורמט: זה מאפשר גישה של אובייקטים של Java בהיקף, ופונקציות פשוטות.

הדפוס הבסיסי עבור JSF הוא פשוט: השתמש ב- Facelets לבניית עץ XML המפנה לספריית רכיבים או לספריות, ואז השתמש ברכיבים בתוך הספרייה כדי לעבד אובייקטים של Java כ- HTML.

שימוש באובייקטים של Java ב- JSF

אם נחזור לרישום 1, שים לב שבתוך ביטוי JSF ( ${javaBean.content) javaBeanהאובייקט נמצא בהיקף כאשר הסימון הזה מבוצע. ה- XHTML של Facelets ניגש .contentלמאפיין javaBeanשבאובייקט. הפלט הסופי הוא ממשק אינטרנט שממזג את מבנה תצוגת Facelets עם יכולות הנתונים והלוגיקה של צד השרת של Java.

שימוש בביטוי JSF הוא רק דרך אחת לגשת לנתוני יישומי Java מממשק משתמש JSF. בסופו של דבר, תרצה לבחון דרכים אחרות שרכיב JSF יכול לקיים אינטראקציה עם ה- Java backend - דברים כמו רשימות נתונים ורשתות ומגוון פקדי קלט. לעת עתה, זה מספיק כדי לספוג את האופן שבו JSF משתמש בתגי XML (או ביאורים) כדי ליצור עץ רכיבים המפיק HTML על בסיס הנתונים הכלולים באובייקטים של Java.

הערות לעומת XML

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

מבנה יישום JSF

כמו דפי JavaServer ו- Servlet API, JavaServer Faces דורש מבנה ספריות סטנדרטי ומטא נתונים. אלה נפרסים כקבצי .war .

המבנה של קובץ .war דומה ליישום Servlet או JSP. הוא מכיל /web-appספריה המכילה את קבצי הסימון של היישום (במקרה זה HTML, JSP ו- Facelets), וכן /WEB-INFספריה המציגה את המטא נתונים לתיאור היישום.

משרת JSF

בזמן שאתה יכול להריץ JSF במיכל Java EE כמו Glassfish, מיכל servlet פשוט הוא כל מה שאתה באמת צריך. Tomcat הוא מיכל פופולרי עבור JSF וטכנולוגיות Java אחרות בצד השרת.

JSF 2.3: מפרט ומימושים

אחת מהעוצמות של ג'אווה היא שהיא מבוססת על סטנדרטים, וסטנדרטים אלה נשלטים על ידי תהליך קהילתי בעל קוד פתוח. מאז הקמתו, תהליך הקהילה של Java (JCP) פיקח על פיתוח טכנולוגיית Java. לאחר שפותח מפרט או שיפור מפרט ואושר על ידי JCP, הוא זמין ליישום על ידי מספר גורמים. עד לאחרונה, Servlets, JSP ו- JSF פותחו באמצעות תהליך מפרט הקוד הפתוח של JCP.

המפרט האחרון של JSF נכון לכתיבת שורות אלה הוא JSF 2.3, שיצא כחלק מ- Java EE 8 בשנת 2017. Mojarra של אורקל (כיום Eclipse) הוא יישום ההפניה של JSF, ו- MyFaces ו- PrimeFaces הם יישומים פופולריים של צד שלישי.

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

MVC ב- JSF 2.3

JSF is an MVC framework, implementing the model-view-controller pattern. In the MVC pattern, the idea is to separate the three concerns of a UI into discreet parts, so they're easier to manage. In general, the view is responsible for displaying data in the model, and the controller is responsible for setting up the model and routing the user to the correct view.

In a JSF implementation, the view is the Facelets page with its set of XML tags. These define the layout of the user interface. The other half of using JSF is the server-side, where Java classes back those UI components.

Managed beans deprecated in JSF 2.3

Managed bean annotations have been deprecated in JSF 2.3, and replaced by CDI (Contexts and Dependency Injection). With CDI, developers define a context and inject objects to that context. Those familiar with managed beans will find the annotation syntax slightly different, but the semantics remain exactly the same.

Controller beans

In JSF 2.3, controller beans provide the controller part of the MVC equation. Normal Java objects (often called POJOs, or plain old Java objects) provide the model.

In terms of process flow, controller beans:

  1. Decide where to direct user requests
  2. Set up POJOs for the model
  3. Use the model to render the Facelets view

JSF then folds together the component tree and model to render the output HTML.

רישום 2 מראה כיצד היית מגדיר את javaBeanהאובייקט מרישום 1 באמצעות CDI. רישום זה מניח שליישום יש את cdi-api-1.2.jar בתלות שלו.

רישום 2. JavaBean המוגדר באמצעות CDI

 import javax.inject.Named; import javax.enterprise.context.SessionScoped; @Named @ViewScoped public class JavaBean implements Serializable { private String content = ìWelcome to JSF!î // getters/setters } 

JSF 2.3 עם PrimeFaces

בחלקים הבאים אשתמש ב- PrimeFaces כדי להראות לך כיצד JSF מיישם את דפוס ה- MVC, הודעות מונעות אירועים ורכיבים לשימוש חוזר. כדי להתחיל, פתח את חלון הראווה של PrimeFaces, לחץ על קישור הנתונים בעמודה השמאלית ובחר DataList . זה יביא את קוד ההדגמה של DataList ל- PrimeFaces.

איור 1 מראה היכן ניתן למצוא דוגמאות אלה.

מתיו טייסון

איור 2 מציג את הפלט של טבלת נתונים פשוטה, אשר לקוחה מהדגמת הדייטליסט של PrimeFaces.

מתיו טייסון

PrimeFaces DataList: גישה למודל הנתונים

Listing 3 presents the markup for this dataList display. If you scroll to the bottom of the PrimeFaces showcase, you can see the markup in the dataList.xhtml tab.

Listing 3. Facelet for PrimeFaces DataList

   Basic  #{car.brand}, #{car.year}  

In Listing 3, notice the value property of the dataList component. You can see that this references a dataListView object, and accesses the .cars1 property on it. The component is going to use the model object returned by that field. JSF tokens use conventional accessors to reference object properties, so .cars1 will refer to the getCars() getter on the object.

Next, notice the var="car" property. This tells the dataList component what variable to use when it iterates over the list of cars returned by the value field. These properties are specific to the dataList component, but the value property is very common. The var attribute is also conventional for components that iterate over lists.

In the body of the component in Listing 3, you can see the car variable is accessed via JSF expressions like #{car.brand}. Each iteration of the dataListView.cars1 instance will output the car.brand field.

Notice that the tag demonstrates the ability to customize components for how they will display. In this case, the header is defined as Basic.

You can see how the Facelets XML will drive this output by combining the data with the markup. Now let's look at the Java code behind it.

DataList's server-side components

Listing 4 shows DataListView, the Java class that is used by the markup in Listing 3. You'll see shortly how the dataListView instance is associated with the DataListView class.

Listing 4. DataListView class

 package org.primefaces.showcase.view.data; import java.io.Serializable; import java.util.List; import javax.annotation.PostConstruct; import javax.inject.Named; // Pre JSF 2.3, this was: // import javax.faces.bean.ManagedBean; import javax.inject.Inject; import javax.faces.bean.ViewScoped; import org.primefaces.showcase.domain.Car; import org.primefaces.showcase.service.CarService; @Named @ViewScoped public class DataListView implements Serializable { private List cars1; private Car selectedCar; @Inject("#{carService}") private CarService service; @PostConstruct public void init() { cars1 = service.createCars(10); } public List getCars1() { return cars1; } public void setService(CarService service) { this.service = service; } } 

Listing 4 has a few other important elements, which we'll consider piece by piece.

Dependency injection and annotations

First, notice that the DataListView class is annotated with @Named, which you can see from the import import javax.inject.Named; is part of JSF. The @Named annotation tells JSF this bean is part of the app. The @ViewScoped annotation informs JSF that the bean will live for just the life of the view.

לאחר מכן, שים לב כי CarServiceהנכס כולל את @Injectההערה (המכונה @ManagedPropertyהקודם ל- JSF 2.3). זוהי תכונה נוספת של JSF המאפשרת "לחווט יחד שעועית", טכניקה פופולארית על ידי מסגרת האביב וכלי הזרקת תלות אחרים. למעשה, JSF ימצא את carServiceהאובייקט בהיקף וישייך אותו אוטומטית serviceלשדה על DataListViewהאובייקט.