Ćwiczenie — tworzenie podstawowej aplikacji internetowej
Do tej pory na maszynie wirtualnej z systemem Ubuntu zainstalowano bazę danych MongoDB i Node.js. Teraz utworzysz podstawową aplikację internetową, aby zobaczyć, jak to działa. Po drodze zobaczysz, jak AngularJS i Express się uzupełniają.
Najlepiej uczymy się na przykładach. Utworzona aplikacja internetowa implementuje podstawową bazę danych książek. Aplikacja internetowa umożliwia wyświetlanie listy informacji o książkach, dodawanie nowych książek i usuwanie istniejących książek.
Uwaga
To ćwiczenie jest opcjonalne. Jeśli chcesz wykonać to ćwiczenie, przed rozpoczęciem musisz utworzyć subskrypcję platformy Azure. Jeśli nie masz konta platformy Azure lub nie chcesz go tworzyć w tej chwili, możesz zapoznać się z instrukcjami, aby zrozumieć prezentowane informacje.
Wyświetlona tutaj aplikacja internetowa demonstruje wiele pojęć, które mają zastosowanie do większości aplikacji internetowych stosu MEAN. W zależności od swoich potrzeb lub zainteresowań możesz zapoznać się z funkcjami, których potrzebujesz do tworzenia własnych aplikacji opartych na stosie MEAN.
Oto jak wygląda aplikacja internetowa Books.
Poniżej przedstawiono rolę, jaką odgrywają poszczególne składniki stosu MEAN.
- Bazy danych MongoDB przechowuje informacje o książkach.
- Express.js kieruje każde żądanie HTTP do odpowiedniej procedury obsługi.
- Rozwiązanie AngularJS łączy interfejs użytkownika z logiką biznesową programu.
- Środowisko Node.js hostuje aplikację po stronie serwera.
Ważne
Utworzysz teraz podstawową aplikację internetową dla celów szkoleniowych. Umożliwia ona przetestowanie stosu MEAN i zapoznanie się ze sposobem jego działania. Aplikacja nie jest wystarczająco bezpieczna ani gotowa do użycia w środowisku produkcyjnym.
Co z Express?
Do tej pory zainstalowano MongoDB i Node.js na maszynie wirtualnej. A co z Express.js, E w akronimie MEAN?
Express.js to struktura serwera internetowego utworzona na potrzeby Node.js, która upraszcza proces tworzenia aplikacji internetowych.
Głównym celem Express jest obsługa trasowania żądań.
Kierowanie żądań oznacza sposób, w jaki aplikacja odpowiada na żądania przesłane do określonego punktu końcowego. Punkt końcowy składa się ze ścieżki lub identyfikatora URI oraz metody żądania, takiej jak GET lub POST. Na przykład w odpowiedzi na żądanie GET do punktu końcowego /book może być zwracana lista wszystkich książek w bazie danych. Możesz odpowiedzieć na żądanie POST do punktu końcowego /book , dodając wpis do bazy danych na podstawie pól wprowadzonych przez użytkownika w formularzu internetowym.
W utworzonej wkrótce aplikacji internetowej usługa Express służy do kierowania żądań HTTP i zwracania zawartości internetowej do użytkownika. Rozwiązanie Express może również ułatwić korzystanie z plików cookie HTTP i przetwarzanie ciągów zapytań w aplikacjach internetowych.
Rozwiązanie Express jest pakietem środowiska Node.js. Narzędzie npm dostarczane wraz ze środowiskiem Node.js umożliwia instalowanie pakietów Node.js i zarządzanie nimi. W dalszej części tej lekcji utworzysz plik o nazwie package.json, aby zdefiniować Express i inne zależności, a następnie uruchom polecenie npm install, aby zainstalować te zależności.
Co z rozwiązaniem AngularJS?
Podobnie jak Express, AngularJS, czyli A w akronimie MEAN, nie jest jeszcze zainstalowany.
Usługa AngularJS ułatwia pisanie i testowanie aplikacji internetowych, ponieważ umożliwia lepsze oddzielenie wyglądu strony internetowej — kodu HTML — od sposobu zachowania strony internetowej. Jeśli znasz wzorzec MVC (model-view-controller) lub pojęcie powiązania danych, usługa AngularJS powinna być ci znana.
AngularJS to frontendowy framework JavaScript, co oznacza, że musi być dostępna tylko na kliencie, który ma dostęp do aplikacji. Innymi słowy rozwiązanie AngularJS działa w przeglądarce internetowej użytkownika, a nie na Twoim serwerze internetowym. Ponieważ rozwiązanie AngularJS bazuje na języku JavaScript, możesz za jego pomocą łatwo pobierać z serwera internetowego dane do wyświetlenia na stronie.
Tak naprawdę nie trzeba instalować platformy AngularJS. Wystarczy dodać odwołanie do pliku JavaScript na stronie HTML, tak samo jak w przypadku innych bibliotek języka JavaScript. Istnieje kilka sposobów na dodanie rozwiązania AngularJS do stron internetowych. W tym miejscu załadujesz usługę AngularJS z sieci dostarczania zawartości (CDN). Sieci CDN umożliwiają rozproszenie geograficzne obrazów, klipów wideo i innych treści w celu przyspieszenia ich pobierania.
Nie dodawaj jeszcze tego kodu, ale oto przykład, który ładuje usługę AngularJS z sieci CDN. Zazwyczaj ten kod jest dodany do <head> sekcji strony HTML.
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular.min.js"></script>
Uwaga
Nie należy mylić rozwiązania AngularJS z usługą Angular. Choć używane są w nich podobne koncepcje, rozwiązanie AngularJS jest wcześniejszą wersją usługi Angular. Rozwiązanie AngularJS jest nadal powszechnie używane do tworzenia aplikacji internetowych. Rozwiązanie AngularJS bazuje na języku JavaScript, natomiast usługa Angular — na języku TypeScript, który ułatwia tworzenie programów w języku JavaScript.
Jak mogę skompilować aplikację?
W tym miejscu użyjesz podstawowego procesu. Napiszesz kod aplikacji z usługi Cloud Shell, a następnie użyjesz protokołu secure copy (SCP), aby skopiować pliki do maszyny wirtualnej. Następnie uruchomisz aplikację Node.js i zobaczysz wyniki w przeglądarce.
W praktyce zazwyczaj napiszesz i przetestujesz aplikację internetową w bardziej lokalnym środowisku, na przykład z laptopa lub z maszyny wirtualnej uruchamianej lokalnie. Kod można przechowywać w systemie kontroli wersji, takim jak Git. Następnie użyj systemu ciągłej integracji i ciągłego dostarczania (CI/CD), takiego jak Azure DevOps, aby przetestować zmiany i przekazać je do maszyny wirtualnej. Wskazujemy na więcej zasobów na końcu tego modułu.
Utwórz aplikację internetową Books
W tym miejscu utworzysz cały kod, skrypt i pliki HTML tworzące aplikację internetową. Aby uzyskać zwięzłość, wyróżniamy ważne części każdego pliku, ale nie przechodzimy do pełnych szczegółów.
Jeśli nadal masz połączenie SSH z maszyną wirtualną, uruchom polecenie exit, aby zakończyć sesję SSH i powrócić do usługi Cloud Shell.
exit
Wrócisz w ten sposób do sesji usługi Cloud Shell.
Tworzenie plików
W usłudze Cloud Shell uruchom następujące polecenia, aby utworzyć foldery i pliki dla aplikacji internetowej:
cd ~ mkdir Books touch Books/server.js touch Books/package.json mkdir Books/app touch Books/app/model.js touch Books/app/routes.js mkdir Books/public touch Books/public/script.js touch Books/public/index.htmlAplikacja internetowa zawiera następujące foldery i pliki:
-
Booksto katalog główny projektu.- Plik
server.jsdefiniuje punkt wejścia do aplikacji internetowej. Ładuje wymagane pakiety Node.js, określa port nasłuchiwania i rozpoczyna nasłuchiwanie przychodzącego ruchu HTTP. - Plik
package.jsonzawiera informacje o aplikacji, w tym jej nazwę, opis oraz pakiety Node.js, których aplikacja potrzebuje do działania.
- Plik
-
Books/app— zawiera kod, który działa na serwerze.- Plik
model.jsdefiniuje połączenie z bazą danych i schemat. Można traktować go jako model danych dla aplikacji. - Plik
routes.jsobsługuje kierowanie żądań. Na przykład definiuje żądania GET do punktu końcowego/bookpoprzez podanie listy wszystkich książek w bazie danych.
- Plik
-
Books/public— zawiera pliki, które są dostarczane bezpośrednio do przeglądarki klienta.- Plik
index.htmlzawiera stronę indeksu. Na tej stronie znajduje się formularz internetowy umożliwiający użytkownikowi przesyłanie informacji o książkach. Pozwala także wyświetlać wszystkie książki w bazie danych i usuwać wpisy z bazy. - Plik
script.jszawiera kod JavaScript, który działa w przeglądarce użytkownika. Umożliwia wysyłanie żądań do serwera, aby wyświetlić listę książek, dodać książki do bazy danych i usunąć książki z bazy danych.
- Plik
-
Uruchom polecenie
code, aby otworzyć pliki za pomocą edytora usługi Cloud Shell.code Books
Tworzenie modelu danych
W edytorze otwórz
app/model.jsplik i dodaj następujący kod:var mongoose = require('mongoose'); var dbHost = 'mongodb://localhost:27017/Books'; mongoose.connect(dbHost, { useNewUrlParser: true } ); mongoose.connection; mongoose.set('debug', true); var bookSchema = mongoose.Schema( { name: String, isbn: {type: String, index: true}, author: String, pages: Number }); var Book = mongoose.model('Book', bookSchema); module.exports = Book;Ważne
Zawsze, gdy wklejasz lub zmieniasz kod w pliku w edytorze, pamiętaj o zapisaniu go później przy użyciu menu „...” lub klawisza skrótu (Ctrl+S w systemach Windows i Linux, Command+S w systemie macOS).
W tym kodzie użyto platformy Mongoose w celu uproszczenia procesu przesyłania danych do i z usługi MongoDB. Mongoose to oparty na schemacie system do modelowania danych. Kod definiuje dokument bazy danych o nazwie „Book” z podanym schematem. W schemacie zdefiniowano cztery pola, które opisują każdą książkę:
- Nazwa, czyli tytuł książki.
- Jego międzynarodowy numer książki standardowej (ISBN), który jednoznacznie identyfikuje książkę
- Jego autor
- Liczba stron.
Następnie utworzysz programy obsługi HTTP mapujące żądania GET, POST i DELETE na operacje bazy danych.
Tworzenie tras Express.js obsługujących żądania HTTP
W edytorze otwórz
app/routes.jsplik i dodaj następujący kod:var path = require('path'); var Book = require('./model'); var routes = function(app) { app.get('/book', function(req, res) { Book.find({}, function(err, result) { if ( err ) throw err; res.json(result); }); }); app.post('/book', function(req, res) { var book = new Book( { name:req.body.name, isbn:req.body.isbn, author:req.body.author, pages:req.body.pages }); book.save(function(err, result) { if ( err ) throw err; res.json( { message:"Successfully added book", book:result }); }); }); app.delete("/book/:isbn", function(req, res) { Book.findOneAndRemove(req.query, function(err, result) { if ( err ) throw err; res.json( { message: "Successfully deleted the book", book: result }); }); }); app.get('*', function(req, res) { res.sendFile(path.join(__dirname + '/public', 'index.html')); }); }; module.exports = routes;Ten kod tworzy cztery trasy dla aplikacji. Poniżej przedstawiono krótkie omówienie każdej z nich.
czasownik HTTP Punkt końcowy opis GET /bookPobiera wszystkie książki z bazy danych. POST /bookTworzy obiekt Bookna podstawie informacji wprowadzonych przez użytkownika w polach formularza internetowego i zapisuje ten obiekt w bazie danych.USUŃ /book/:isbnUsuwa z bazy danych książkę o podanym numerze ISBN. GET *Zwraca stronę indeksu, jeśli nie dopasowano żadnej innej trasy. Express.js może obsługiwać odpowiedzi HTTP bezpośrednio w kodzie obsługi tras lub obsługiwać zawartość statyczną z plików. W tym kodzie przedstawiono obie możliwości. Pierwsze trzy trasy zwracają dane JSON w odpowiedzi na żądania dotyczące książek z interfejsu API. Czwarta trasa (przypadek domyślny) zwraca zawartość pliku indeksu
index.html.
Tworzenie aplikacji klienckiej JavaScript
W edytorze otwórz plik
public/script.jsi dodaj następujący kod:var app = angular.module('myApp', []); app.controller('myCtrl', function($scope, $http) { var getData = function() { return $http( { method: 'GET', url: '/book' }).then(function successCallback(response) { $scope.books = response.data; }, function errorCallback(response) { console.log('Error: ' + response); }); }; getData(); $scope.del_book = function(book) { $http( { method: 'DELETE', url: '/book/:isbn', params: {'isbn': book.isbn} }).then(function successCallback(response) { console.log(response); return getData(); }, function errorCallback(response) { console.log('Error: ' + response); }); }; $scope.add_book = function() { var body = '{ "name": "' + $scope.Name + '", "isbn": "' + $scope.Isbn + '", "author": "' + $scope.Author + '", "pages": "' + $scope.Pages + '" }'; $http({ method: 'POST', url: '/book', data: body }).then(function successCallback(response) { console.log(response); return getData(); }, function errorCallback(response) { console.log('Error: ' + response); }); }; });Zwróć uwagę, że ten kod definiuje moduł o nazwie
myAppi kontroler o nazwiemyCtrl. Nie zostaną tutaj omówione wszystkie szczegóły związane z działaniem modułów i kontrolerów, ale te nazwy będą używane w kolejnym kroku do powiązania interfejsu użytkownika (kodu HTML) z logiką biznesową aplikacji.Wcześniej utworzono cztery trasy do obsługi różnych operacji typu GET, POST i DELETE na serwerze. Ten kod dotyczy podobnych operacji, ale po stronie klienta (w przeglądarce internetowej użytkownika).
Na przykład funkcja
getDatawysyła żądanie GET do punktu końcowego/book. Pamiętaj, że serwer obsługuje to żądanie, pobierając informacje o wszystkich książkach z bazy danych i zwracając te informacje jako dane JSON w odpowiedzi. Zwróć uwagę, że dane JSON w odpowiedzi są przypisywane do zmiennej$scope.books. Dowiesz się, jak ten kod wpływa na to, co użytkownik widzi na stronie internetowej w następnym kroku.Ten kod wywołuje funkcję
getDatapodczas ładowania strony. Możesz zapoznać się z funkcjamidel_bookiadd_book, aby poznać sposób ich działania. Do dopasowania domyślnego programu obsługi serwera nie jest potrzebny kod po stronie klienta, ponieważ domyślna procedura obsługi zwraca stronę indeksu, a nie dane JSON.
Tworzenie interfejsu użytkownika
W edytorze otwórz plik
public/index.htmli dodaj następujący kod:<!doctype html> <html ng-app="myApp" ng-controller="myCtrl"> <head> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular.min.js"></script> <script src="script.js"></script> </head> <body> <div> <table> <tr> <td>Name:</td> <td><input type="text" ng-model="Name"></td> </tr> <tr> <td>Isbn:</td> <td><input type="text" ng-model="Isbn"></td> </tr> <tr> <td>Author:</td> <td><input type="text" ng-model="Author"></td> </tr> <tr> <td>Pages:</td> <td><input type="number" ng-model="Pages"></td> </tr> </table> <button ng-click="add_book()">Add</button> </div> <hr> <div> <table> <tr> <th>Name</th> <th>Isbn</th> <th>Author</th> <th>Pages</th> </tr> <tr ng-repeat="book in books"> <td><input type="button" value="Delete" data-ng-click="del_book(book)"></td> <td>{{book.name}}</td> <td>{{book.isbn}}</td> <td>{{book.author}}</td> <td>{{book.pages}}</td> </tr> </table> </div> </body> </html>Ten kod tworzy podstawowy formularz HTML z czterema polami do przesyłania danych książki i tabelą, w której są wyświetlane wszystkie książki przechowywane w bazie danych.
Mimo że ten kod HTML jest standardowy,
ng-atrybuty HTML mogą być dla Ciebie nieznane. Te atrybuty HTML łączą kod rozwiązania AngularJS z interfejsem użytkownika. Na przykład po wybraniu przycisku Dodaj, rozwiązanie AngularJS wywoła funkcjęadd_book, co spowoduje wysłanie danych z formularza na serwer.W tym miejscu możesz sprawdzić kod, aby dowiedzieć się, jak każdy z atrybutów
ng-odnosi się do logiki biznesowej aplikacji.
Tworzenie serwera Express.js na potrzeby hostowania aplikacji
W edytorze otwórz plik
server.jsi dodaj następujący kod:var express = require('express'); var bodyParser = require('body-parser'); var app = express(); app.use(express.static(__dirname + '/public')); app.use(bodyParser.json()); require('./app/routes')(app); app.set('port', 80); app.listen(app.get('port'), function() { console.log('Server up: http://localhost:' + app.get('port')); });Ten kod służy do utworzenia aplikacji internetowej. Obsługuje pliki statyczne z
publickatalogu i używa tras zdefiniowanych wcześniej do obsługi żądań.
Definiowanie informacji o pakietach oraz zależności
Jak możesz pamiętać, plik package.json zawiera informacje o aplikacji, w tym jej nazwę, opis oraz pakiety Node.js, których aplikacja potrzebuje do działania.
W edytorze otwórz plik
package.jsoni dodaj następujący kod:{ "name": "books", "description": "Sample web app that manages book information.", "license": "MIT", "repository": { "type": "git", "url": "https://github.com/MicrosoftDocs/mslearn-build-a-web-app-with-mean-on-a-linux-vm" }, "main": "server.js", "dependencies": { "express": "~4.16", "mongoose": "~5.3", "body-parser": "~1.18" } }
Zobaczysz informacje o aplikacji, czyli jej metadane, w tym jej nazwę, opis i licencję.
Pole repository określa lokalizację, w której przechowywany jest kod. Możesz później zapoznać się z tym kodem w witrynie GitHub pod podanym tu adresem URL.
Pole main definiuje punkt wejścia aplikacji. Udostępniamy go tutaj, aby zapewnić kompletność. Jednak punkt wejścia jest ważny tylko wtedy, gdy planujesz opublikować aplikację jako pakiet Node.js dla innych osób do pobrania i użycia.
Pole dependencies jest ważne. Definiuje pakiety Node.js wymagane przez aplikację. Wkrótce połączysz się z maszyną wirtualną po raz drugi i uruchomisz polecenie npm install, aby zainstalować te pakiety.
Pakiety Node na ogół korzystają ze schematu wersjonowania semantycznego. Numer wersji składa się z trzech elementów: wersji głównej, wersji pomocniczej i numeru poprawki. Zapis z tyldą (~) wskazuje, że narzędzie npm powinno zainstalować najnowszą wersję poprawki w ramach wskazanej wersji głównej i pomocniczej. Wyświetlone tutaj wersje to najnowsze wersje, z którymi przetestowano ten moduł. W praktyce możesz z czasem zwiększać wersję, aktualizując i testując aplikację w celu korzystania z najnowszych funkcji poszczególnych pakietów zależności.
Kopiowanie plików na maszynę wirtualną
Przed kontynuowaniem upewnij się, że masz pod ręką adres IP maszyny wirtualnej. Jeśli go nie masz, uruchom następujące polecenia z usługi Cloud Shell, aby je pobrać:
ipaddress=$(az vm show \
--name MeanStack \
--resource-group "myResourceGroupName" \
--show-details \
--query [publicIps] \
--output tsv)
echo $ipaddress
Edycja plików została zakończona. Upewnij się, że zapisano zmiany w każdym pliku, a następnie zamknij edytor.
Aby zamknąć edytor, wybierz wielokropek w prawym górnym rogu, a następnie wybierz pozycję Zamknij edytor.
Uruchom następujące
scppolecenie, aby skopiować zawartość~/Bookskatalogu w sesji usługi Cloud Shell do tej samej nazwy katalogu na maszynie wirtualnej:scp -r ~/Books azureuser@$ipaddress:~/Books
Instalowanie większej liczby pakietów Node
Załóżmy, że podczas procesu programowania zidentyfikowano więcej pakietów node, których chcesz użyć. Możesz na przykład pamiętać, że plik app/model.js zaczyna się od takiego wiersza.
var mongoose = require('mongoose');
Pamiętaj, że w aplikacji używana jest platforma Mongoose, ułatwiająca przesyłanie danych do i z bazy MongoDB.
Aplikacja wymaga również Express.js i pakietów analizatora treści. Body-parser to wtyczka umożliwiająca platformie Express pracę z danymi z formularza internetowego wysyłanego przez klienta.
Nawiąż połączenie z maszyną wirtualną i zainstaluj pakiety określone w pliku package.json.
Przed nawiązaniem połączenia z maszyną wirtualną upewnij się, że masz przygotowany jej adres IP. Jeśli go nie masz, uruchom polecenia usługi Cloud Shell w poprzedniej sekcji, aby je pobrać.
Utwórz połączenie SSH z maszyną wirtualną, tak jak wcześniej:
ssh azureuser@$ipaddressPrzejdź do katalogu
Booksznajdującego się w katalogu głównym:cd ~/BooksUruchom polecenie
npm install, aby zainstalować pakiety zależne:sudo apt install npm -y && npm install
Pozostaw otwarte połączenie SSH dla następnej sekcji.
Testowanie aplikacji
Możesz teraz przystąpić do testowania aplikacji internetowej Node.js.
~/BooksW katalogu uruchom następujące polecenie, aby uruchomić aplikację internetową:sudo nodejs server.jsTo polecenie uruchamia aplikację, nasłuchując przychodzących żądań HTTP na porcie 80.
W nowej karcie przeglądarki przejdź do publicznego adresu IP maszyny wirtualnej.
Zostanie wyświetlona strona indeksu zawierająca formularz internetowy.
Spróbuj dodać kilka książek do bazy danych. Po dodaniu każdej książki pełna lista książek na stronie zostanie zaktualizowana.
Aby usunąć książkę z bazy danych, możesz również wybrać pozycję Usuń.