הבנת השלבים המשותפים בהגדרת הפרויקט היא חיונית לפני התעמקות בפרטים הספציפיים של כל טכנולוגיה להגדלת לקוח. הדרישות שלי מהפוסט האחרון היו די פשוטות:
- אניח את נקודת המבט של מפתח אחורי
- ללא שלב בנייה קדמי: ללא TypeScript, ללא מזעור וכו'.
- כל התלות מנוהלות מאפליקציית הקצה האחורי, כלומר , Maven
חשוב לציין שהטכנולוגיה שאפרט, מלבד Vaadin, נוקטת בגישה דומה. ועדין, עם הפרדיגמה הייחודית שלה, באמת בולטת בין הגישות.
WebJars היא טכנולוגיה שתוכננה בשנת 2012 על ידי ג'יימס וורד כדי להתמודד עם הדרישות המדויקות הללו.
WebJars הן ספריות אינטרנט בצד הלקוח (למשל jQuery & Bootstrap) ארוזות בקבצי JAR (Java Archive).
- נהל בצורה מפורשת ובקלות את התלות בצד הלקוח ביישומי אינטרנט מבוססי JVM
- השתמש בכלי בנייה מבוססי JVM (למשל Maven, Gradle, sbt, ...) כדי להוריד את התלות בצד הלקוח שלך
- דע באילו תלות בצד הלקוח אתה משתמש
- תלות טרנזיטיבית נפתרת אוטומטית ונטענת אופציונלית באמצעות RequireJS
- פרוס על Maven Central
- CDN ציבורי, מסופק בנדיבות על ידי JSDelivr
-- אתר Webjars
WebJar הוא JAR רגיל המכיל נכסי אינטרנט. הוספת WebJar לתלות של פרויקט אינה ספציפית:
<dependencies> <dependency> <groupId>org.webjars.npm</groupId> <artifactId>alpinejs</artifactId> <version>3.14.1</version> </dependency> </dependencies>
אחריות המסגרת היא לחשוף את הנכסים תחת כתובת URL. לדוגמה, Spring Boot עושה זאת במחלקה WebMvcAutoConfiguration
:
public void addResourceHandlers(ResourceHandlerRegistry registry) { if (!this.resourceProperties.isAddMappings()) { logger.debug("Default resource handling disabled"); return; } addResourceHandler(registry, this.mvcProperties.getWebjarsPathPattern(), //1 "classpath:/META-INF/resources/webjars/"); addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> { registration.addResourceLocations(this.resourceProperties.getStaticLocations()); if (this.servletContext != null) { ServletContextResource resource = new ServletContextResource(this.servletContext, SERVLET_LOCATION); registration.addResourceLocations(resource); } }); }
"/webjars/**"
בתוך ה-JAR, אתה יכול להגיע לנכסים לפי הנתיב והשם שלהם. המבנה המוסכם הוא לאחסן את הנכסים בתוך resources/webjars/<library>/<version>
. הנה המבנה של alpinejs-3.14.1.jar
:
META-INF |_ MANIFEST.MF |_ maven.org.webjars.npm.alpinejs |_ resources.webjars.alpinejs.3.14.1 |_ builds |_ dist |_ cdn.js |_ cdn.min.js |_ src |_ package.json
בתוך Spring Boot, אתה יכול לגשת לגרסה הלא ממוזערת עם /webjars/alpinejs/3.14.1/dist/cdn.js
.
מפתחים משחררים ספריות בצד הלקוח לעתים קרובות למדי. כאשר אתה משנה גרסת תלות ב-POM, עליך לשנות את הנתיב הקדמי, אולי במספר מיקומים. זה משעמם, אין לו ערך מוסף, ואתה מסתכן בהחמצת שינוי.
פרויקט WebJars Locator נועד למנוע את כל הבעיות הללו על ידי מתן נתיב ללא גרסה, כלומר /webjars/alpinejs/dist/cdn.js
. אתה יכול להשיג זאת על ידי הוספת ה- webjars-locator
JAR לתלות שלך:
<dependencies> <dependency> <groupId>org.webjars.npm</groupId> <artifactId>alpinejs</artifactId> <version>3.14.1</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>webjars-locator</artifactId> <version>0.52</version> </dependency> </dependencies>
אני אשתמש בגישה זו עבור כל טכנולוגיה חזיתית. אוסיף גם את ספריית Bootstrap CSS כדי לספק ממשק משתמש שנראה טוב יותר.
Thymeleaf היא טכנולוגיית עיבוד בצד השרת.
Thymeleaf הוא מנוע תבנית Java צד שרת מודרני עבור סביבות אינטרנט והן בסביבות עצמאיות.
המטרה העיקרית של Thymeleaf היא להביא תבניות טבעיות אלגנטיות לזרימת העבודה בפיתוח שלך - HTML שניתן להציג בצורה נכונה בדפדפנים וגם לעבוד כאב טיפוס סטטי, מה שמאפשר שיתוף פעולה חזק יותר בצוותי פיתוח.
עם מודולים ל-Spring Framework, שלל אינטגרציות עם הכלים המועדפים עליך והיכולת לחבר את הפונקציונליות שלך, Thymeleaf אידיאלית לפיתוח אינטרנט מודרני HTML5 JVM - אם כי יש הרבה יותר שהוא יכול לעשות.
-- קורנית
עדיין הייתי יועץ כשנודע לי לראשונה על Thymeleaf. בזמנו, Java Server Pages היו בסוף חייהם. Java Server Faces ניסו להחליף אותם; IMHO, הם נכשלו.
חשבתי ש-Thymeleaf היא גישה פנטסטית: היא מאפשרת לראות את התוצאות בסביבה סטטית בזמן התכנון ובסביבת שרת בזמן הפיתוח. אפילו טוב יותר, אתה יכול לעבור בצורה חלקה בין אחד לשני באמצעות אותו קובץ. מעולם לא ראיתי שימוש ביכולת הזו.
עם זאת, Spring Boot תומך באופן מלא ב-Tymeleaf. הדובדבן שבקצפת: האחרון זמין דרך מרחב שמות HTML בעמוד. אם לא קניתם ל-JSF (ספויילר: לא עשיתי זאת), Thymeleaf היא שפת התבניות של ה-SSR של היום.
הנה דוגמת ההדגמה מהאתר:
<table> <thead> <tr> <th th:text="#{msgs.headers.name}">Name</th> <th th:text="#{msgs.headers.price}">Price</th> </tr> </thead> <tbody> <tr th:each="prod: ${allProducts}"> <td th:text="${prod.name}">Oranges</td> <td th:text="${#numbers.formatDecimal(prod.price, 1, 2)}">0.99</td> </tr> </tbody> </table>
הנה Thymeleaf 101, למקרה שתצטרכו להכיר את הטכנולוגיה.
Name
Price
. כאשר אתה משתמש בו בשרת, Thymeleaf נכנס ומעבד את הערך המחושב מ- th:text
, #{msgs.headers.name}
ו #{msgs.headers.price}
.$
עבור Spring bean באותו שם הועברו לדגם. ${prod.name}
שווה ערך ל- model.getBean("prod").getName()"
.#
קורא לפונקציה.th:each
מאפשר לולאות.רוב המסגרות החזיתיות, אם לא כולן, עובדות עם מודל בצד הלקוח. אנחנו צריכים לגשר בין המודל בצד השרת לבין המודל בצד הלקוח.
הקוד בצד השרת שבו אני משתמש הוא הבא:
data class Todo(val id: Int, var label: String, var completed: Boolean = false) //1 fun config() = beans { bean { mutableListOf( //2 Todo(1, "Go to the groceries", false), Todo(2, "Walk the dog", false), Todo(3, "Take out the trash", false) ) } bean { router { GET("/") { ok().render( //3 "index", //4 mapOf("title" to "My Title", "todos" to ref<List<Todo>>()) //5 ) } } } }
הגדר את מחלקה Todo
.
הוסף רשימת זיכרון למפעל השעועית. באפליקציה רגילה, תשתמש Repository
כדי לקרוא ממסד הנתונים.
עיבוד תבנית HTML.
התבנית היא src/main/resources/templates/index.html
עם תכונות Thymeleaf.
שימו את הדגם בהקשר של העמוד.
Thymeleaf מציעה תכונה th:inline="javascript"
בתג <script>
. זה מעבד את הנתונים בצד השרת כמשתני JavaScript. התיעוד מסביר את זה הרבה יותר טוב ממה שאי פעם יכולתי:
הדבר הראשון שאנחנו יכולים לעשות עם שילוב תסריט הוא לכתוב את הערך של ביטויים לתוך התסריטים שלנו, כמו:
<script th:inline="javascript"> /*<![CDATA[*/ ... var username = /*[[${session.user.name}]]*/ 'Sebastian'; ... /*]]>*/ </script>
תחביר
/*[[...]]*/
, מורה ל-Thymeleaf להעריך את הביטוי הכלול. אבל יש כאן השלכות נוספות:
בהיותה הערת javascript
(/*...*/)
, הביטוי שלנו יתעלם בעת הצגת הדף באופן סטטי בדפדפן.הקוד שאחרי הביטוי המוטבע (
'Sebastian'
) יבוצע בעת הצגת העמוד באופן סטטי.Thymeleaf יבצע את הביטוי ויכניס את התוצאה, אבל הוא גם יסיר את כל הקוד בשורה שאחרי הביטוי המוטבע עצמו (החלק שמתבצע כאשר מוצג באופן סטטי).
-- תיעוד קורנית
אם נחיל את האמור לעיל על הקוד שלנו, נוכל להעביר את תכונות המודל על ידי Spring כ:
<script th:inline="javascript"> /*<![CDATA[*/ window.title = /*[[${title}]]*/ 'A Title' window.todos = /*[[${todos}]]*/ [{ 'id': 1, 'label': 'Take out the trash', 'completed': false }] /*]]>*/ </script>
כאשר הוא מוצג בצד השרת, התוצאה היא:
<script> /*<![CDATA[*/ window.title = "My title"; window.todos: [{"id":1,"label":"Go to the groceries","completed":false},{"id":2,"label":"Walk the dog","completed":false},{"id":3,"label":"Take out the trash","completed":false}] /*]]>*/ </script>
בפוסט זה, תיארתי שני רכיבים בהם אשתמש במהלך שאר הסדרה:
את קוד המקור המלא לפוסט זה ניתן למצוא ב-GitHub.
לכו רחוק יותר:
פורסם במקור ב- A Java Geek ב-15 בספטמבר 2024