בנה יישום אינטרנט MVC עם Grails

1. סקירה כללית

במדריך זה נלמד כיצד ליצור יישום אינטרנט פשוט באמצעות Grails.

Grails (ליתר דיוק זו הגרסה העיקרית האחרונה) היא מסגרת שנבנתה על גבי פרויקט Spring Boot ומשתמשת בשפת Apache Groovy לפיתוח אפליקציות אינטרנט.

זה בהשראת מסגרת המסילה עבור רובי ו בנוי סביב הפילוסופיה של קונבנציונליות-על-תצורה המאפשרת הפחתת קוד הדוד.

2. התקנה

קודם כל, בואו נעבור לדף הרשמי להכנת הסביבה. בזמן הדרכה זו, הגרסה האחרונה היא 3.3.3.

במילים פשוטות, ישנן שתי דרכים להתקנת Grails: באמצעות SDKMAN או על ידי הורדת ההפצה והוספת קבצים בינאריים למשתנה הסביבה PATH.

לא נסקור את ההתקנה שלב אחר שלב מכיוון שהיא מתועדת היטב במסמכי הגריילס.

3. אנטומיה של אפליקציית הגביע

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

  • נכסים - מקום בו אנו מאחסנים קבצי נכסים סטטיים כמו סגנונות, קבצי JavaScript או תמונות
  • conf - מכיל קבצי תצורת פרויקט:
    • application.yml מכיל הגדרות אפליקציית אינטרנט סטנדרטיות כמו מקור נתונים, סוגי פנטמה והגדרות אחרות של Grails או Spring
    • resources.groovy מכיל הגדרות שעועית אביבית
    • logback.groovy מכיל תצורת רישום
  • בקרים - אחראי על טיפול בבקשות והפקת תגובות או האצלתן לתצוגות. לפי האמנה, כאשר שם קובץ מסתיים ב- *בקרהמסגרת יוצרת מיפוי ברירת מחדל של כתובות אתרים לכל פעולה המוגדרת במחלקת הבקר
  • תְחוּם - מכיל את המודל העסקי של יישום הגריילים. כל כיתה המתגוררת כאן תמופה לטבלאות מסדי נתונים על ידי GORM
  • i18n - משמש לתמיכה בינלאומית
  • init - נקודת כניסה ליישום
  • שירותים - ההיגיון העסקי של האפליקציה יחיה כאן. על פי האמנה, גריילס תיצור שעועית אביבית לכל שירות
  • תגליב - המקום לספריות תגים מותאמות אישית
  • נופים - מכיל תצוגות ותבניות

4. יישום אינטרנט פשוט

בפרק זה ניצור אפליקציית אינטרנט פשוטה לניהול סטודנטים. נתחיל בהפעלת פקודת CLI ליצירת שלד יישום:

אפליקציית הגביעים

כאשר נוצר המבנה הבסיסי של הפרויקט, נעבור ליישום רכיבי אפליקציות אינטרנט בפועל.

4.1. שכבת תחום

כאשר אנו מיישמים יישום אינטרנט לטיפול בסטודנטים, נתחיל ביצירת כיתת תחום הנקראת סטוּדֶנט:

grails create-domain-class com.baeldung.grails.Student

ולסיום, בואו נוסיף את שם פרטי ו שם משפחה מאפיינים אליו:

כיתה תלמיד {String firstName מחרוזת שם משפחה}

גריילס מיישם את המוסכמות שלו ויקבע מיפוי התייחסותי לאובייקטים לכל הכיתות שנמצאות ב grails-app / domain מַדרִיך.

יתר על כן, בזכות תכונת GormEntity, לכל מחלקות התחום תהיה גישה לכל פעולות ה- CRUD, שבו נשתמש בחלק הבא להטמעת שירותים.

4.2. שכבת שירות

היישום שלנו יטפל במקרי השימוש הבאים:

  • צופה ברשימת תלמידים
  • יצירת תלמידים חדשים
  • הסרת תלמידים קיימים

בואו נשתמש במקרי שימוש אלה. נתחיל בהפקת מחלקת שירות:

grails create-service com.baeldung.grails.Student

בואו ניגש אל ה- grails-app / services בספרייה, מצא את השירות החדש שנוצר בחבילה המתאימה והוסף את כל השיטות הדרושות:

@Transactional class StudentService {def get (id) {Student.get (id)} def list () {Student.list ()} def save (student) {student.save ()} def delete (id) {Student.get (id). מחק ()}}

שים לב ששירותים אינם תומכים בעסקאות כברירת מחדל. אנו יכולים להפעיל תכונה זו על ידי הוספת ה- @ Transactional ביאור לכיתה.

4.3. שכבת בקר

על מנת להפוך את ההיגיון העסקי לרשות ממשק המשתמש, בואו ליצור StudentController על ידי הפעלת הפקודה הבאה:

grails create-controller com.baeldung.grails.Student

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

כעת אנו יכולים להגדיר פעולות לקריאה, יצירה ומחיקה של תלמידים.

class StudentController {def studentService def index () {respond studentService.list ()} def show (Long id) {respond studentService.get (id)} def create () {respond new Student (params)} def save (סטודנט) פעולת הפניה מחדש של {studentService.save (סטודנט): "אינדקס", שיטה: "GET"} def delete (מזהה ארוך) {studentService.delete (id) פעולת הפניה מחדש: "אינדקס", שיטה: "GET"}}

לפי המוסכמה, ה אינדקס() פעולה מבקר זה תמופה ל- URI / סטודנט / אינדקס, ה הופעה() פעולה ל / סטודנט / מופע וכולי.

4.4. צפה בשכבה

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

על פי האמנה, גריילס יציג תצוגה המבוססת על שם הבקר והפעולה שלו. לדוגמה,האינדקס () פעולה מ StudentController יפתור ל /grails-app/views/student/index.gsp

נתחיל ביישום התצוגה / grails-app /צפיות / סטודנט / אינדקס.gsp, שתציג רשימת תלמידים. נשתמש בתגית כדי ליצור טבלת HTML המציגה את כל התלמידים שחזרו מה- אינדקס() פעולה בבקר שלנו.

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

  • לִיצוֹר

כעת נמשיך לתצוגה / grails-app /תצוגות /סטודנט / create.gsp, המאפשר למשתמש ליצור סטודנטים חדשים. נשתמש במובנה תג, המציג טופס לכל המאפיינים של שעועית נתונה:

לבסוף, בואו ניצור את התצוגה / grails-app /תצוגות /סטודנט / show.gsp לצפייה ולבסוף מחיקת תלמידים.

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

  • רשימת סטודנטים

4.5. בדיקות יחידה

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

נתחיל בבדיקת יחידות אינדקס() פעולה שלנו StudentController.

נלעוג ל רשימה() שיטה מ StudentService ולבדוק אם אינדקס() מחזיר את המודל הצפוי:

בטל "בדוק את פעולת האינדקס מחזירה את המודל הנכון" () {given: controller.studentService = Mock (StudentService) {list () >> [Student new (firstName: 'John', lastName: 'Doe')]} when: "פעולת האינדקס מבוצעת" controller.index () ואז: "המודל נכון" model.studentList.size () == 1 model.studentList [0] .firstName == 'John' model.studentList [0]. lastName == 'Doe'}

עכשיו, בואו נבדוק את לִמְחוֹק() פעולה. אנו נוודא אם לִמְחוֹק() הופעל מ StudentService ואמת הפניה לדף האינדקס:

בטל "בדוק את פעולת המחיקה עם מופע" () {given: controller.studentService = Mock (StudentService) {1 * delete (2)} when: "מופע הדומיין מועבר לפעולת המחיקה" request.contentType = FORM_CONTENT_TYPE בקשה .method = 'DELETE' controller.delete (2) ואז: "המשתמש מנותב לאינדקס" response.redirectedUrl == '/ student / index'}

4.6. מבחני שילוב

לאחר מכן, בואו נסתכל כיצד ליצור מבחני אינטגרציה לשכבת השירות. בעיקר נבדוק שילוב עם מסד נתונים שהוגדר ב grails-app / conf / application.yml.

כברירת מחדל, Grails משתמש במסד הנתונים H2 בזיכרון למטרה זו.

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

פרטי Long setupData () {תלמיד חדש (firstname: 'John', lastName: 'Doe'). save (flush: true, failOnError: true) new Student (firstName: 'Max', lastName: 'Foo'). save ( flush: true, failOnError: true) סטודנט סטודנט = סטודנט חדש (firstname: 'Alex', lastName: 'Bar'). save (flush: true, failOnError: true) student.id}

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

בדוק כיצד יישמנו את מבחן האינטגרציה עבורנו רשימה() שיטה:

בטל "רשימת בדיקות" () {setupData () כאשר: רשימת studentList = studentService.list () ואז: studentList.size () == 3 studentList [0] .lastName == 'Doe' studentList [1]. lastName == StudentList 'Foo' [2] .lastName == 'Bar'}

בנוסף, בואו לבדוק את לִמְחוֹק() שיטה ותקף אם המספר הכולל של התלמידים מצטמצם באחד:

בטל "מחק מבחן" () {Long id = setupData () מצפה: studentService.list (). גודל () == 3 כאשר: studentService.delete (id) sessionFactory.currentSession.flush () ואז: studentService.list () גודל () == 2}

5. ריצה ופריסה

הפעלה ופריסה של אפליקציות יכולה להיעשות על ידי הפעלת פקודה אחת באמצעות Grails CLI.

להפעלת האפליקציה השתמש:

אפליקציית run grails

כברירת מחדל, גריילס יגדיר את Tomcat ביציאה 8080.

בוא ננווט אל // localhost: 8080 / סטודנט / אינדקס כדי לראות כיצד נראית אפליקציית האינטרנט שלנו:

אם ברצונך לפרוס את היישום שלך למיכל סרוולט, השתמש ב:

מלחמת הגביעים

ליצור חפץ מלחמה מוכן לפריסה.

6. מסקנה

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

כמו תמיד, ניתן למצוא את כל הקוד המשמש כאן ב- GitHub.