Skip to content

4. Korzystanie z aplikacji

Chcemy teraz uruchomić aplikację poza środowiskami IDE i STS (dla serwera) oraz Webstorm (dla klienta).

4.1. Wdrożenie serwisu internetowego na serwerze Tomcat

W punkcie 2.11.9 omówiliśmy, jak utworzyć archiwum WAR dla serwera Tomcat. Powtórzymy tę operację w tym miejscu. Po pierwsze, aby zachować dotychczasowe dane, duplikujemy projekt Eclipse o nazwie [rdvmedecins-webapi-v3], tworząc kopię o nazwie [rdvmedecins-webapi-v4].

  

Plik [pom.xml] zostaje zmodyfikowany w następujący sposób:


    <modelVersion>4.0.0</modelVersion>
    <groupId>istia.st.spring4.mvc</groupId>
    <artifactId>rdvmedecins-webapi-v4</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>rdvmedecins-webapi-v3</name>
    <description>Gestion de RV Médecins</description>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.0.0.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>istia.st.spring4.rdvmedecins</groupId>
            <artifactId>rdvmedecins-metier-dao-v2</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
</dependencies>

Zmiany należy wprowadzić w dwóch miejscach:

  • wiersz 5: należy wskazać, że zostanie wygenerowany plik archiwum WAR (Web ARchive);
  • wiersze 23–27: należy dodać zależność od artefaktu [spring-boot-starter-tomcat]. Artefakt ten wprowadza wszystkie klasy Tomcata do zależności projektu;
  • wiersz 26: artefaktem tym jest [provided], co oznacza, że odpowiednie archiwa nie zostaną umieszczone w wygenerowanym pliku WAR. Archiwa te będą bowiem dostępne na serwerze Tomcat, na którym będzie działać aplikacja;

Należy ponadto skonfigurować aplikację internetową. W przypadku braku pliku [web.xml] odbywa się to za pomocą klasy dziedziczącej po [SpringBootServletInitializer]:

  

Klasa [ApplicationInitializer] ma następującą postać:


package rdvmedecins.web.config;

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;

public class ApplicationInitializer extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(AppConfig.class);
    }

}
  • wiersz 6: klasa [ApplicationInitializer] rozszerza klasę [SpringBootServletInitializer];
  • wiersz 8: metoda [configure] została ponownie zdefiniowana (wiersz 7);
  • wiersz 9: podano klasę [AppConfig], która konfiguruje projekt;

Po wykonaniu tej czynności może zaistnieć konieczność aktualizacji projektu Maven (ja musiałem to zrobić): [clic droit sur projet / Maven / Update project] lub [Alt-F5].

Aby uruchomić projekt, można postępować w następujący sposób:

  • w przypadku [1] uruchamia się projekt na jednym z serwerów zarejestrowanych w Eclipse;
  • w [2] wybiera się [tc Server Developer], który jest domyślnie dostępny. Jest to wariant serwera Tomcat;

Otrzymujemy następujący wynik:

 

To normalne. Przypomnijmy, że usługa internetowa nie posiada w swoich metodach URL ani [/]. Gdy wypróbujemy URL lub [/getAllMedecins], otrzymujemy następującą odpowiedź:

 

To normalne. Usługa internetowa jest zabezpieczona.

Teraz uruchommy klienta [rdvmedecins-angular-v2] w Webstormie:

W [1] wpisujemy URL nowej usługi internetowej [http://localhost:8080/rdvmedecins-webapi-v4]. Otrzymujemy następujący wynik:

Image

Aby uruchomić aplikację poza środowiskiem IDE STS, istnieje kilka rozwiązań. Oto jedno z nich.

Pobierz wersję Tomcat [http://tomcat.apache.org/download-80.cgi] (lipiec 2014 r.):

Wybieramy w [1] wersję w formacie ZIP, którą rozpakowujemy do [2]. Wracamy do STS:

  • w zakładce [Servers] klikamy prawym przyciskiem myszy na aplikację [rdvmedecins-webapi-v4] i wybieramy opcję [Browse Deployment Location];
  • w [4]: skopiować folder [rdvmedecins-webapi-v4];
  • w [5] wklejamy folder [rdvmedecins-webapi-v4] do folderu [webapps] serwera Tomcat;
  • w [6] uruchamia się plik poleceń [startup.bat] (serwer Tomcat zintegrowany z STS musi być w tym momencie wyłączony). Otworzy się okno DOS, w którym wyświetlane są logi serwera Tomcat. Powinny one wskazywać, że aplikacja [rdvmedecins-webapi-v4] została uruchomiona.

Aby to sprawdzić, należy ponownie uruchomić klienta Angular [rdvmedecins-angular-v2] w Webstormie:

W [1] podajemy URL nowej usługi internetowej [http://localhost:8080/rdvmedecins-webapi-v4]. Otrzymujemy następujący wynik:

Image

4.2. Wdrożenie klienta Angular na serwerze Tomcat

Teraz, gdy usługa internetowa została wdrożona na serwerze Tomcat, wdrożymy również klienta Angular na serwerze. Może to być ten sam serwer, na którym już znajduje się usługa internetowa. Wybieramy tę opcję.

Najpierw duplikujemy klienta [rdvmedecins-angular-v2], tworząc kopię o nazwie [rdvmedecins-angular-v3], a następnie wprowadzamy następujące zmiany:

  • w [1] – całość została przeniesiona do folderu [app] ;
  • w pliku [1] usunięto folder [bower-components], który zawierał różne biblioteki CSS i JS niezbędne dla projektu. Wszystkie te elementy zostały skopiowane do folderu [lib] [2];
  • w folderze [1] plik [app.html] został przemianowany na [index.html];

Plik [index.html] został zmodyfikowany w celu uwzględnienia zmian ścieżek dostępu do wykorzystywanych zasobów:


<!DOCTYPE html>
<html ng-app="rdvmedecins">
<head>
  <title>RdvMedecins</title>
...
  <!-- CSS -->
  ...
  <link href="lib/bootstrap-theme.min.css" rel="stylesheet"/>
  <link href="lib/bootstrap-select.min.css" rel="stylesheet"/>
</head>
<!-- kontroler [appCtrl], szablon [app] -->
<body ng-controller="appCtrl">
<div class="container">
  ...
</div>
<!-- Bootstrap core JavaScript ================================================== -->
<script type="text/javascript" src="lib/jquery.min.js"></script>
<script type="text/javascript" src="lib/bootstrap.min.js"></script>
<script type="text/javascript" src="lib/bootstrap-select.min.js"></script>
<script type="text/javascript" src="lib/footable.js"></script>
<!-- AngularJS -->
<script type="text/javascript" src="lib/angular.min.js"></script>
<script type="text/javascript" src="lib/ui-bootstrap-tpls.min.js"></script>
<script type="text/javascript" src="lib/angular-route.min.js"></script>
<script type="text/javascript" src="lib/angular-translate.min.js"></script>
<script type="text/javascript" src="lib/angular-base64.min.js"></script>
<!-- moduły -->
...
<!-- usługi -->
...
<!-- dyrektywy -->
...
<!-- kontrolery -->
....
</body>
</html>

Ponadto kontroler [loginCtrl] został zmodyfikowany tak, aby wskazywał właściwy serwer, co pozwala uniknąć konieczności wpisywania przez użytkownika adresu URL:


// poświadczenia
app.serverUrl = "http://localhost:8080/rdvmedecins-webapi-v4";
app.username = "admin";
app.password = "admin";

Po wykonaniu tych czynności uruchommy plik [index.html]:

Następnie zalogujmy się do serwisu internetowego. Powinno działać. Po sprawdzeniu tego zatrzymajmy serwer Tomcat. Wykorzystamy ponownie wbudowany serwer z pliku STS.

W STS skopiujmy całą zawartość folderu [rdvmedecins-angular-v3/app] do folderu [webapp] w projekcie [rdvmedecins-webapi-v4] (zakładka Navigator) [1]:

Po wykonaniu tych czynności uruchomimy [2], serwer VMware z STS, a następnie zażądamy URL [http://localhost:8080/rdvmedecins-webapi-v4/app/index.html]:

Wystąpił problem z uprawnieniami w pliku [3]. Nie jest to zaskakujące, ponieważ usługa internetowa została zabezpieczona. Należy określić, że dostęp do pliku [/app/index.html] jest swobodny. Wróćmy do programu Eclipse:

  

Pamiętamy, że uprawnienia dostępu zostały zadeklarowane w klasie [SecurityConfig]. Zmodyfikujmy ją w następujący sposób:


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // CSRF
        http.csrf().disable();
        // hasło jest przekazywane w nagłówku Authorization: Basic xxxx
        http.httpBasic();
        // metoda HTTP OPTIONS musi być autoryzowana dla wszystkich
        http.authorizeRequests() //
                .antMatchers(HttpMethod.OPTIONS, "/", "/**").permitAll();
        // folder [app] jest dostępny dla wszystkich
        http.authorizeRequests() //
                .antMatchers(HttpMethod.GET, "/app", "/app/**").permitAll();
        // tylko rola ADMIN może korzystać z aplikacji
        http.authorizeRequests() //
                .antMatchers("/", "/**") // wszystkie URL
                .hasRole("ADMIN");
}
  • wiersze 11–12: zezwalamy wszystkim na odczyt folderu [app] i jego zawartości. W tym celu wzorujemy się na poprzednich wierszach.

Teraz uruchommy ponownie serwer Tomcat dla pliku STS, a następnie ponownie wywołajmy plik URL [http://localhost:8080/rdvmedecins-webapi-v4/app/index.html]:

Image

Tym razem wszystko działa poprawnie.

4.3. Nagłówki CORS

Być może pamiętacie, że mieliśmy spore trudności z obsługą nagłówków CORS. W poprzednim przykładzie:

  • serwis internetowy znajduje się pod adresem URL [http://localhost:8080/rdvmedecins-webapi-v4];
  • klient HTML znajduje się na serwerze URL [http://localhost:8080/rdvmedecins-webapi-v4/app];

Klient HTML i usługa internetowa znajdują się zatem na tym samym serwerze [http://localhost:8080]. Nie ma więc żadnych konfliktów CORS, ponieważ występują one tylko wtedy, gdy klient i serwer nie znajdują się w tej samej domenie. Powinno się to dać sprawdzić. Wracamy do STS:

  

To, czy generowane są nagłówki CORS, jest kontrolowane przez zmienną logiczną zdefiniowaną w klasie [ApplicationModel]:


    // dane konfiguracyjne
    private boolean CORSneeded = true;

Ustawiamy powyższą wartość logiczną na „false”, ponownie uruchamiamy usługę internetową i ponownie wysyłamy żądanie dotyczące URL [http://localhost:8080/rdvmedecins-webapi-v4/app/index.html]. Okazuje się, że aplikacja działa.

4.4. Wdrożenie klienta Angular na tablecie z systemem Android

Narzędzie [Phonegap] [http://phonegap.com/] umożliwia wygenerowanie pliku wykonywalnego dla urządzeń mobilnych (Android, IoS, Windows 8, ...) na podstawie aplikacji HTML / JS / CSS. Istnieje kilka sposobów osiągnięcia tego celu. Korzystamy z najprostszego: narzędzia dostępnego online na stronie Phonegap [http://build.phonegap.com/apps].

  • przed [1] może być konieczne utworzenie konta;
  • w [1] rozpoczynamy;
  • w [2] wybieramy bezpłatny plan, który pozwala na stworzenie tylko jednej aplikacji Phonegap;
  • w [3] pobieramy spakowaną aplikację [4] (folder [app] utworzony w punkcie 4.2 jest spakowany);
  • w pliku [5] nadajemy nazwę aplikacji;
  • w pliku [6] tworzymy aplikację. Operacja ta może potrwać 1 minutę. Należy poczekać, aż ikony poszczególnych platform mobilnych wskażą, że tworzenie aplikacji zostało zakończone;
  • wygenerowano jedynie pliki binarne dla systemu Android ([7]) i systemu Windows ([8]);
  • należy kliknąć [7], aby pobrać plik binarny dla systemu Android;
  • w [9] pobrany plik binarny [apk];

Uruchom emulator [GenyMotion] dla tabletu z systemem Android (patrz punkt 6.4):

 

Powyżej uruchamiamy emulator tabletu z systemem Android w wersji 16 (API). Po uruchomieniu emulatora

  • odblokuj go, przesuwając suwak (jeśli jest) w bok, a następnie zwalniając go;
  • za pomocą myszki przeciągnij pobrany plik [PGBuildApp-debug.apk] i upuść go na emulatorze. Zostanie on wówczas zainstalowany i uruchomiony;

Należy zmienić nazwę pliku z URL na [1]. W tym celu w oknie poleceń wpisz polecenie [ipconfig] (wiersz 1 poniżej), które wyświetli różne adresy IP na Twoim komputerze:


C:\Users\Serge Tahé>ipconfig

Configuration IP de Windows


Carte réseau sans fil Connexion au réseau local* 15 :

   Statut du média. . . . . . . . . . . . : Média déconnecté
   Suffixe DNS propre à la connexion. . . :

Carte Ethernet Connexion au réseau local :

   Suffixe DNS propre à la connexion. . . : ad.univ-angers.fr
   Adresse IPv6 de liaison locale. . . . .: fe80::698b:455a:925:6b13%4
   Adresse IPv4. . . . . . . . . . . . . .: 172.19.81.34
   Masque de sous-réseau. . . . . . . . . : 255.255.0.0
   Passerelle par défaut. . . . . . . . . : 172.19.0.254

Carte réseau sans fil Wi-Fi :

   Statut du média. . . . . . . . . . . . : Média déconnecté
   Suffixe DNS propre à la connexion. . . :

...

Zapisz albo adres Wi-Fi IP (wiersze 6–9), albo adres w sieci lokalnej IP (wiersze 11–17). Następnie użyj tego adresu IP w polu URL serwera WWW:

 

Po wykonaniu tych czynności należy połączyć się z usługą internetową:

Przetestuj aplikację na emulatorze. Powinna działać. Po stronie serwera można zezwolić lub nie na nagłówki CORS w klasie [ApplicationModel]:


    // dane konfiguracyjne
    private boolean CORSneeded = false;

Nie ma to znaczenia dla aplikacji na Androida. Nie jest ona uruchamiana w przeglądarce. Wymóg dotyczący nagłówków CORS wynika z przeglądarki, a nie z serwera.

4.5. Wdrożenie klienta Angular na emulatorze smartfona z systemem Android

Powtarzamy poprzednią operację na emulatorze smartfona. Chcemy sprawdzić, jak nasz klient zachowuje się na małych ekranach:

  • w [1] uruchamiamy emulator smartfona;
  • w [2] i [3] pasek nawigacyjny został schowany w menu;
  • w [4] następuje logowanie;
  • w [5] lista i kalendarz znajdują się jeden pod drugim zamiast obok siebie;
  • w [6] wyświetla się kalendarz;
  • w [7] ekran jest zbyt mały, przez co część przedziałów czasowych jest ukryta. Zadanie to wykonała biblioteka [footable];
  • w [8] ten sam widok co poprzednio, tym razem z zaplanowanym spotkaniem.

Ostatecznie nasza aplikacja całkiem dobrze dostosowuje się do smartfonów. Z pewnością mogłoby być lepiej, ale nadal jest użyteczna.