יישום פשוט של מסחר אלקטרוני עם אביב

1. סקירה כללית של אפליקציית המסחר האלקטרוני שלנו

במדריך זה אנו ניישם יישום פשוט למסחר אלקטרוני. נפתח API באמצעות Spring Boot ויישום לקוח שיצרוך את ה- API באמצעות Angular.

בעיקרון, המשתמש יוכל להוסיף / להסיר מוצרים מרשימת מוצרים לסל הקניות / לבצע הזמנה.

2. חלק אחורי

כדי לפתח את ה- API, נשתמש בגרסה האחרונה של Spring Boot. אנו משתמשים גם במסד הנתונים JPA ו- H2 לצורך הצד ההתמדה של העניינים.

למידע נוסף על מגף אביב,אתה יכול לבדוק את סדרת המאמרים של Spring Boot ואם תרצו כדי להכיר את בניית ה- REST API, אנא עיין בסדרה אחרת.

2.1. תלות Maven

בואו נכין את הפרויקט שלנו ונייבא את התלות הנדרשת לתוכנו pom.xml.

נצטרך כמה תלות מרכזית באביב אתחול:

 org.springframework.boot spring-boot-starter-data-jpa 2.2.2.RELEASE org.springframework.boot spring-boot-starter-web 2.2.2.RELEASE 

לאחר מכן, מסד הנתונים H2:

 com.h2database h2 1.4.197 זמן ריצה 

ולסיום - ספריית ג'קסון:

 com.fasterxml.jackson.datatype jackson-datatype-jsr310 2.9.6 

השתמשנו באביב Initializr כדי להקים במהירות את הפרויקט עם תלות נדרשת.

2.2. הגדרת מסד הנתונים

למרות שנוכל להשתמש במסד נתונים H2 בזיכרון מהקופסה עם Spring Boot, עדיין נבצע כמה שינויים לפני שנתחיל לפתח את ה- API שלנו.

נו אפשר קונסולת H2 בשלנו application.properties קוֹבֶץ כדי שנוכל לבדוק את מצב מסד הנתונים שלנו ולראות אם הכל מתנהל כפי שציפינו.

כמו כן, יכול להיות שימושי לרשום שאילתות SQL למסוף תוך כדי פיתוח:

spring.datasource.name = ecommercedb spring.jpa.show-sql = true # H2 הגדרות spring.h2.console.enabled = אמיתי spring.h2.console.path = / h2-console

לאחר הוספת הגדרות אלה, נוכל לגשת למסד הנתונים בכתובת // localhost: 8080 / h2-console באמצעות jdbc: h2: mem: ecommercedb ככתובת JDBC ומשתמש sa ללא סיסמה.

2.3. מבנה הפרויקט

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

├───pom.xml ├───src ├─── העיקרי │ ├─── מתמודד │ ├───java │ │ └───com │ │ └───baeldung │ │ └──── מסחר │ │ │ מסחר אלקטרוני אפליקציה.java │ │ ├─── בקר │ │ ├───dto │ │ ├─── חריג │ │ ├─── מודל │ │ ├─── התשובה │ │ └─── שירות │ │ │ └─── מקורות │ │ יישומים. נכסים │ ├─── סטטי │ └─── תבניות └─── בדיקה └───java └───com └───baeldung └─── מסחר אלקטרוני מסחר יישום יישום אינטגרציה. ג'אווה

עלינו לציין כי כל הממשקים בחבילה המאגר הם פשוטים ומרחיבים את CrudRepository של Spring Data, ולכן נשמיט להציג אותם כאן.

2.4. טיפול בחריגים

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

תוכל למצוא פרטים נוספים על הנושא בטיפול בשגיאות עבור REST עם אביב וטיפול בהודעות שגיאה בהתאמה אישית עבור מאמרים ב- REST API..

כאן אנו שומרים על התמקדות ConstraintViolationException והמנהג שלנו ResourceNotFoundException:

@RestControllerAdvice מחלקה ציבורית ApiExceptionHandler {@SuppressWarnings ("rawtypes") @ExceptionHandler (ConstraintViolationException.class) ידית תגובה ציבורית (ConstraintViolationException e) {ErrorResponse שגיאות = שגיאת תגובה חדשה (); עבור (הפרת ConstraintViolation: e.getConstraintViolations ()) {ErrorItem error = ErrorItem new (); error.setCode (viol.getMessageTemplate ()); error.setMessage (violage.getMessage ()); error.addError (שגיאה); } להחזיר ResponseEntity חדש (שגיאות, HttpStatus.BAD_REQUEST); } @SuppressWarnings ("rawtypes") @ExceptionHandler (ResourceNotFoundException.class) ידית ResponseEntity ציבורית (ResourceNotFoundException e) {ErrorItem error = ErrorItem new (); error.setMessage (e.getMessage ()); להחזיר ResponseEntity חדש (שגיאה, HttpStatus.NOT_FOUND); }}

2.5. מוצרים

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

היישום שלנו יתמוך רק לקרוא מוצרים ממאגר המידעאז עלינו להוסיף קצת קודם.

בואו ניצור פשוט מוצר מעמד:

מוצר בכיתה ציבורית @Entity {@Id @GeneratedValue (אסטרטגיה = GenerationType.IDENTITY) פרטי מזהה ארוך; @NotNull (message = "שם מוצר נדרש.") @ Basic (אופציונלי = שקר) שם פרטי מחרוזת; מחיר זוגי פרטי; פרטי מחרוזת pictureUrl; // כל הבורר טיעונים // תקנים וקובעים סטנדרטיים}

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

שירות פשוט יספיק לצרכינו:

@Service @ Transactional public class ProductServiceImpl מיישם את ProductService {// productRepository constructor הזרקת @Override public Iterable getAllProducts () {return productRepository.findAll (); } @Override מוצר ציבורי getProduct (מזהה ארוך) {return productRepository .findById (id) .orElseThrow (() -> ResourceNotFoundException חדש ("המוצר לא נמצא")); } @Override ציבורי שמירת מוצר (מוצר מוצר) {החזר productRepository.save (מוצר); }}

בקר פשוט יטפל בבקשות לאחזור רשימת המוצרים:

@RestController @RequestMapping ("/ api / products") מחלקה ציבורית ProductController {// productService constructor הזרקת @GetMapping (value = {"", "/"}) public @NotNull Iterable getProducts () {return productService.getAllProducts (); }}

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

בדרך זו נכניס מוצרים למסד הנתונים במהלך הפעלת היישום:

רץ @Bean CommandLineRunner (ProductService productService) {retour args -> {productService.save (...); // עוד מוצרים }

אם אנו מתחילים כעת את היישום שלנו, נוכל לאחזר את רשימת המוצרים באמצעות // localhost: 8080 / api / products. כמו כן, אם נלך ל // localhost: 8080 / h2-console ונכנס, נראה שיש טבלה בשם מוצר עם המוצרים שהוספנו זה עתה.

2.6. הזמנות

בצד ה- API, עלינו לאפשר לבקשות POST לשמור את ההזמנות שמשתמש הקצה יבצע.

בואו ניצור תחילה את המודל:

@Entity @Table (name = "orders") מחלקה ציבורית הזמנה {@Id @GeneratedValue (אסטרטגיה = GenerationType.IDENTITY) פרטי מזהה ארוך; @JsonFormat (תבנית = "dd / MM / yyyy") תאריך LocalDate פרטי נוצר; סטטוס מחרוזת פרטי; @JsonManagedReference @OneToMany (mappedBy = "pk.order") @Valid פרטי רשימה orderProducts = ArrayList חדש (); @ Transient ציבורי כפול getTotalOrderPrice () {סכום כפול = 0D; רשימת orderProducts = getOrderProducts (); עבור (OrderProduct op: orderProducts) {sum + = op.getTotalPrice (); } סכום החזר; } @ Transient public int getNumberOfProducts () {להחזיר this.orderProducts.size (); } // גטרים וקובעים סטנדרטיים}

עלינו לציין כמה דברים כאן. אין ספק שאחד הדברים הבולטים ביותר הוא לעשות זאת זכור לשנות את שם ברירת המחדל של הטבלה שלנו. מאז שמנו את הכיתה להזמין, כברירת מחדל הטבלה בשם להזמין צריך ליצור. אבל בגלל שזו מילת SQL שמורה, הוספנו @Table (שם = "הזמנות") כדי למנוע סכסוכים.

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

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

@Party Class בכיתה ציבורית OrderProduct {@EmbeddedId @JsonIgnore OrderProductPK private pk; @Column (nullable = false) כמות שלמה פרטית; // ברירת מחדל של בונה ציבורי OrderProduct (הזמנת הזמנה, מוצר מוצר, כמות שלמה) {pk = OrderProductPK חדש (); pk.setOrder (סדר); pk.setProduct (מוצר); this.quantity = כמות; } @ Transient מוצר ציבורי getProduct () {להחזיר this.pk.getProduct (); } @ Transient public כפול getTotalPrice () {להחזיר getProduct (). GetPrice () * getQuantity (); } // getters וקובעים סטנדרטיים // hashcode () ושיטות שווה ()}

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

@ Embeddable class class OrderProductPK מיישם את הסידור {@JsonBackReference @ManyToOne (אופציונלי = false, fetch = FetchType.LAZY) @JoinColumn (name = "order_id") הזמנת פרטי פרטי; @ManyToOne (אופציונלי = false, fetch = FetchType.LAZY) @JoinColumn (name = "product_id") מוצר מוצר פרטי; // סטרים וקובעים סטנדרטיים // hashcode () ושיטות שווה ()}

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

אנחנו רק צריכים את מוצר להיות מוצג למשתמש, אז בגלל זה יש לנו ארעיים getProduct () שיטה.

הבא מה שאנחנו צריכים זה יישום שירות פשוט:

@Service @Transactional public class OrderServiceImpl מיישם OrderService {// orderRepository constructor הזרקת @Override public Iterable getAllOrders () {להחזיר this.orderRepository.findAll (); } @Override הזמנה ציבורית (סדר הזמנה) {order.setDateCreated (LocalDate.now ()); להחזיר this.orderRepository.save (סדר); } @ עקוב על עדכון הריק הציבורי (סדר הזמנה) {this.orderRepository.save (סדר); }}

ובקר ממופה אליו / api / הזמנות להתמודד להזמין בקשות.

החשוב ביותר הוא לִיצוֹר() שיטה:

@ PostMapping ציבורי ResponseEntity ליצור (@RequestBody OrderForm טופס) {רשימה formDtos = form.getProductOrders (); validateProductsExistence (formDtos); // צור לוגיקת הזמנות // אכלס סדר במוצרים order.setOrderProducts (orderProducts); this.orderService.update (סדר); מחרוזת uri = ServletUriComponentsBuilder .fromCurrentServletMapping () .path ("/ orders / {id}") .buildAndExpand (order.getId ()) .toString (); כותרות HttpHeaders = HttpHeaders חדשות (); headers.add ("מיקום", אורי); להחזיר ResponseEntity חדש (סדר, כותרות, HttpStatus.CREATED); }

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

סוף כל סוף, אנו יוצרים כותרת "מיקום".

היישום המפורט נמצא במאגר - הקישור אליו מוזכר בסוף מאמר זה.

3. חזית

עכשיו שיש לנו את היישום Spring Boot שלנו בנוי, הגיע הזמן לזוז החלק הזוויתי של הפרויקט. לשם כך, ראשית נצטרך להתקין את Node.js עם NPM, ולאחר מכן, CLI Angular, ממשק שורת פקודה עבור Angular.

קל מאוד להתקין את שני אלה כפי שיכולנו לראות בתיעוד הרשמי.

3.1. הגדרת הפרויקט הזוויתי

כפי שציינו, נשתמש CLI זוויתי כדי ליצור את היישום שלנו. כדי לשמור על דברים פשוטים ולקיים את הכל במקום אחד, נשמור את היישום Angular שלנו בתוך ה- / src / main / frontend תיקיה.

כדי ליצור אותו, עלינו לפתוח מסוף (או שורת פקודה) ב- / src / main תיקיה והפעל:

ng חזית חדשה

זה ייצור את כל הקבצים והתיקיות שאנחנו צריכים ליישום Angular שלנו. בתיק pakage.json, אנו יכולים לבדוק אילו גרסאות של התלות שלנו מותקנות. הדרכה זו מבוססת על Angular v6.0.3, אך גרסאות ישנות יותר צריכות לבצע את העבודה, לפחות גרסאות 4.3 ומעלה (HttpClient שאנחנו משתמשים כאן הוצג ב- Angular 4.3).

עלינו לציין זאת נפעיל את כל הפקודות שלנו מה- /חזיתי תיקיה אלא אם כן נאמר אחרת.

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

3.2. הוספת Bootstrap

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

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

התקנת npm - שמור את רצועת האתחול

ו ואז לומר ל- Angular להשתמש בו בפועל. לשם כך עלינו לפתוח קובץ src / main / frontend / angular.json ותוסיף node_modules / bootstrap / dist / css / bootstrap.min.css תַחַת "סגנונות" תכונה. וזה הכל.

3.3. רכיבים ודגמים

לפני שנתחיל ליצור את הרכיבים ליישום שלנו, בואו נבדוק תחילה כיצד האפליקציה שלנו תיראה בפועל:

כעת ניצור רכיב בסיס בשם מסחר אלקטרוני:

ng g c מסחר אלקטרוני

זה ייצור את הרכיב שלנו בתוך ה- / frontend / src / app תיקיה. כדי לטעון אותו בעת אתחול היישום, אנולכלול אותולתוך ה app.component.html:

לאחר מכן ניצור רכיבים אחרים בתוך רכיב בסיס זה:

ng g c / מסחר אלקטרוני / מוצרים ng g c / ecommerce / orders ng g c / ecommerce / shopping-cart

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

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

מחלקת ייצוא מוצר {id: number; שם: מחרוזת; מחיר: מספר; pictureUrl: מחרוזת; // כל בונה הטיעונים}
מחלקת יצוא ProductOrder {product: Product; כמות: מספר; // כל בונה הטיעונים}
מחלקת יצוא ProductOrders {productOrders: ProductOrder [] = []; }

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

3.4. רכיב בסיס

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

 מסחר אלקטרוני של באלדונג 
  • בית (נוכחי)

אנו נטען גם רכיבים אחרים מכאן:

עלינו לזכור שכדי לראות את התוכן מהרכיבים שלנו, מכיוון שאנו משתמשים ב- סרגל בכיתה, עלינו להוסיף קצת CSS למערכת app.component.css:

.container {padding-top: 65px; }

בואו נבדוק את .ts הקובץ לפני שאנחנו מגיבים על החלקים החשובים ביותר:

@Component ({selector: 'app-ecommerce', templateUrl: './ecommerce.component.html', styleUrls: ['./ecommerce.component.css']}) מחלקת הייצוא EcommerceComponent מיישמת את OnInit {פרטית מכווצת = true; orderFinished = false; @ViewChild ('productsC') productsC: ProductsComponent; @ViewChild ('shoppingCartC') shoppingCartC: ShoppingCartComponent; @ViewChild ('ordersC') ordersC: OrdersComponent; toggleCollapsed (): בטל {this.collapsed =! this.collapsed; } finishOrder (orderFinished: בוליאני) {this.orderFinished = orderFinished; } reset () {this.orderFinished = false; this.productsC.reset (); this.shoppingCartC.reset (); this.ordersC.paid = שקר; }}

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

3.5. השירות

על מנת ש רכיבי אחים כדי לתקשר אחד עם השניוכדי לאחזר / לשלוח נתונים מ / אל ה- API שלנונצטרך ליצור שירות:

@Injectable () מחלקת ייצוא של EcommerceService {private productsUrl = "/ api / products"; ordersUrl = "/ api / orders"; מוצר פרטי הזמנה: מוצר הזמנה; הזמנות פרטיות: ProductOrders = הזמנות מוצר חדשות (); מוצר פרטיOrderSubject = נושא חדש (); orders ordersSubject = נושא חדש (); totalSubject פרטי = נושא חדש (); סה"כ פרטי: מספר; ProductOrderChanged = this.productOrderSubject.asObservable (); OrdersChanged = this.ordersSubject.asObservable (); TotalChanged = this.totalSubject.asObservable (); קונסטרוקטור (פרטי http: HttpClient) {} getAllProducts () {להחזיר this.http.get (this.productsUrl); } saveOrder (order: ProductOrders) {להחזיר this.http.post (this.ordersUrl, order); } // גטרים וקובעים לשדות משותפים}

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

עם זאת, עלינו לציין דבר אחד הנוגע לתקשורת עם ה- API. אם נפעיל את היישום כעת, נקבל 404 ולא נאחזר נתונים. הסיבה לכך היא שכיוון שאנחנו משתמשים בכתובות אתרים יחסית, Angular כברירת מחדל תנסה להתקשר אליהן // localhost: 4200 / api / products ויישום ה- backend שלנו פועל מקום אירוח מקומי: 8080.

נוכל לקודד את כתובות האתרים לקודד מקום אירוח מקומי: 8080כמובן, אבל זה לא משהו שאנחנו רוצים לעשות. במקום זאת, כשעובדים עם תחומים שונים, עלינו ליצור קובץ בשם proxy-conf.json בשלנו /חזיתי תיקיה:

{"/ api": {"target": "// localhost: 8080", "secure": false}}

ואז אנחנו צריכים לִפְתוֹחַ package.json ולשנות scripts.start תכונה להתאים:

"scripts": {... "start": "ng serve --proxy-config proxy-conf.json", ...}

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

3.6. מוצרים

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

מחלקת ייצוא ProductsComponent מיישמת OnInit {productOrders: ProductOrder [] = []; מוצרים: מוצר [] = []; selectProductOrder: ProductOrder; קניות פרטיותסדרי הזמנות: הזמנות מוצר; משנה: מנוי; productSelected: בוליאני = false; קונסטרוקטור (מסחר אלקטרוני פרטי: שירות מסחר אלקטרוני) {} ngOnInit () {this.productOrders = []; this.loadProducts (); this.loadOrders (); } loadProducts () {this.ecommerceService.getAllProducts (). subscribe ((products: any []) => {this.products = products; this.products.forEach (product => {this.productOrders.push (הזמנת מוצר חדש ( מוצר, 0));})}, (שגיאה) => console.log (שגיאה)); } loadOrders () {this.sub = this.ecommerceService.OrdersChanged.subscribe (() => {this.shoppingCartOrders = this.ecommerceService.ProductOrders;}); }}

אנו זקוקים גם לאפשרות להוסיף את המוצר לעגלת הקניות או להסיר ממנו אחד:

addToCart (order: ProductOrder) {this.ecommerceService.SelectedProductOrder = order; this.selectedProductOrder = this.ecommerceService.SelectedProductOrder; this.productSelected = נכון; } removeFromCart (productOrder: ProductOrder) {let index = this.getProductIndex (productOrder.product); אם (אינדקס> -1) {this.shoppingCartOrders.productOrders.splice (this.getProductIndex (productOrder.product), 1); } this.ecommerceService.ProductOrders = this.shoppingCartOrders; this.shoppingCartOrders = this.ecommerceService.ProductOrders; this.productSelected = שקר; }

לבסוף, ניצור אִתחוּל() השיטה שהזכרנו בסעיף 3.4:

אפס () {this.productOrders = []; this.loadProducts (); this.ecommerceService.ProductOrders.productOrders = []; this.loadOrders (); this.productSelected = שקר; }

נעבור ברשימת המוצרים בקובץ ה- HTML ונציג אותה בפני המשתמש:

{{order.product.name}}

$ {{order.product.price}}

3.8. הזמנות

נשמור על דברים פשוטים ככל שנוכל וב הזמנות רכיב לדמות תשלום על ידי הגדרת הנכס לאמיתי ושמירת ההזמנה במסד הנתונים. אנחנו יכולים לבדוק שההזמנות נשמרות באמצעות קונסולת h2 או על ידי מכה // localhost: 8080 / api / orders.

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

מחלקה לייצא OrdersComponent מיישם OnInit {orders: ProductOrders; מספר כולל; שילם: בוליאני; משנה: מנוי; קונסטרוקטור (ecommerceService פרטי: EcommerceService) {this.orders = this.ecommerceService.ProductOrders; } ngOnInit () {this.paid = false; this.sub = this.ecommerceService.OrdersChanged.subscribe (() => {this.orders = this.ecommerceService.ProductOrders;}); this.loadTotal (); } שלם () {this.paid = נכון; this.ecommerceService.saveOrder (this.orders). מנוי (); }}

ולבסוף עלינו להציג מידע למשתמש:

להזמין

  • {{order.product.name}} - $ {{order.product.price}} x {{order.quantity}} יח '.

סכום כולל: $ {{total}}

לְשַׁלֵם מזל טוב! ביצעת את ההזמנה בהצלחה.

4. מיזוג מגף קפיץ ויישומים זוויתיים

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

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

כדי לאפשר זאת, עלינו לפתוח 'package.json'הוסף שוב כמה סקריפטים חדשים אחרי תסריטים.לִבנוֹת:

"postbuild": "npm run deploy", "פריסה מוקדמת": "rimraf ../resources/static/ && mkdirp ../resources/static", "deploy": "copyfiles -f dist / ** ../resources/ סטָטִי",

אנו משתמשים בכמה חבילות שלא התקנו, אז בואו נתקין אותן:

npm להתקין - save-dev rimraf npm להתקין - save-dev mkdirp npm להתקין - save-dev העתקי

ה rimraf הפקודה הולכת להסתכל בספרייה וליצור ספרייה חדשה (לנקות אותה למעשה), תוך כדי קובצי העתק מעתיק את הקבצים מתיקיית ההפצה (שבה Angular ממקמת הכל) לתוך שלנו סטָטִי תיקיה.

עכשיו אנחנו רק צריכים לָרוּץ בניית הפעלה npm פקודה וזה אמור להריץ את כל הפקודות האלה והפלט האולטימטיבי יהיה היישום הארוז שלנו בתיקיה הסטטית.

לאחר מכן אנו מריצים את יישום Spring Boot שלנו בנמל 8080, ניגש אליו שם ומשתמש באפליקציית Angular.

5. מסקנה

במאמר זה, יצרנו יישום פשוט למסחר אלקטרוני. יצרנו ממשק API על ה- backend באמצעות Spring Boot ואז צרכנו אותו ביישום הקדמי שלנו המיוצר ב- Angular. הדגמנו כיצד ליצור את הרכיבים הדרושים לנו, לגרום להם לתקשר זה עם זה ולאחזר / לשלוח נתונים מ / אל ה- API.

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

כמו תמיד, הפרויקט השלם שתיארנו במאמר זה נמצא בפרויקט GitHub.


$config[zx-auto] not found$config[zx-overlay] not found