Application AngularJS CRUD avec REST Spring Data

Les données]

  • lien:/tag/spring-data-rest/[Ressource de données REST]

1. Vue d’ensemble

Dans ce didacticiel, nous allons créer un exemple d’application CRUD simple utilisant AngularJS pour le front-end et Spring Data REST pour le back-end.

2. Création du service de données REST

Pour créer la prise en charge de la persistance, nous allons utiliser la spécification Spring Data REST qui nous permettra d’exécuter des opérations CRUD sur un modèle de données.

Vous trouverez toutes les informations nécessaires sur la configuration des noeuds finaux REST dans le lien:/spring-data-rest-intro[introduction à Spring Data REST]. Dans cet article, nous allons réutiliser le projet existant que nous avons configuré pour le didacticiel d’introduction.

Pour la persistance, nous utiliserons la base de données H2 in memory.

En tant que modèle de données, l’article précédent définit une classe WebsiteUser , avec les propriétés id , name et email et une interface de référentiel appelée UserRepository .

La définition de cette interface indique à Spring de créer la prise en charge de l’exposition des ressources de collection REST et des ressources d’élément. Examinons de plus près les points de terminaison dont nous disposons maintenant que nous appellerons plus tard de AngularJS .

2.1. Les ressources de la collection

Une liste de tous les utilisateurs sera disponible sur le noeud final /users . Cette URL peut être appelée à l’aide de la méthode GET et renverra des objets JSON de la forme:

{
  "__embedded" : {
    "users" :[{
      "name" : "Bryan",
      "age" : 20,
      "__links" : {
        "self" : {
          "href" : "http://localhost:8080/users/1"
        },
        "User" : {
          "href" : "http://localhost:8080/users/1"
        }
      }
    },
...
   ]  }
}

2.2. Les ressources d’item

Un seul objet WebsiteUser peut être manipulé en accédant à des URL de la forme /users/\ {userID} avec différentes méthodes HTTP et requêtes.

Pour récupérer un objet WebsiteUser , nous pouvons accéder à /users/\ {userID} avec la méthode GET. Ceci retourne un objet JSON de la forme:

{
  "name" : "Bryan",
  "email" : "[email protected]",
  "__links" : {
    "self" : {
      "href" : "http://localhost:8080/users/1"
    },
    "User" : {
      "href" : "http://localhost:8080/users/1"
    }
  }
}

Pour ajouter un nouveau WebsiteUser , nous devrons appeler /users avec la méthode POST. Les attributs du nouvel enregistrement WebsiteUser seront ajoutés dans le corps de la demande en tant qu’objet JSON:

{name: "Bryan", email: "br[email protected]"}

S’il n’y a pas d’erreur, cette URL renvoie un code d’état 201 CREATED.

Si nous voulons mettre à jour les attributs de l’enregistrement WebsiteUser , nous devons appeler l’URL /users/\ {UserID} avec la méthode PATCH et un corps de requête contenant les nouvelles valeurs:

{name: "Bryan", email: "[email protected]"}

Pour supprimer un enregistrement WebsiteUser , vous pouvez appeler l’URL /users/\ {UserID} avec la méthode DELETE. S’il n’y a pas d’erreur, cela retourne le code d’état 204 AUCUN CONTENU.

2.3. Configuration MVC

Nous allons également ajouter une configuration MVC de base pour afficher les fichiers HTML dans notre application:

@Configuration
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {

    public MvcConfig(){
        super();
    }

    @Override
    public void configureDefaultServletHandling(
      DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
}

2.4. Autoriser les demandes d’origine croisée

Si nous voulons déployer l’application frontale AngularJS séparément de l’API REST, nous devons activer les demandes d’origine croisée.

Spring Data REST a pris en charge cette fonctionnalité à partir de la version 1.5.0.RELEASE. Pour autoriser les demandes provenant d’un domaine différent, il suffit d’ajouter l’annotation @ CrossOrigin au référentiel:

@CrossOrigin
@RepositoryRestResource(collectionResourceRel = "users", path = "users")
public interface UserRepository extends CrudRepository<WebsiteUser, Long> {}

En conséquence, à chaque réponse des noeuds finaux REST, un en-tête de Access-Control-Allow-Origin sera ajouté.

3. Création du client AngularJS

Pour créer le frontal de notre application CRUD, nous allons utiliser AngularJS - un framework JavaScript bien connu qui facilite la création d’applications frontales.

Afin d’utiliser AngularJS , nous devons d’abord inclure le fichier angular.min.js dans notre page HTML qui s’appellera users.html :

<script
  src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js">
</script>

Ensuite, nous devons créer un module angulaire, un contrôleur et un service qui appellent les points de terminaison REST et affichent les données renvoyées.

Ceux-ci seront placés dans un fichier JavaScript appelé app.js qui doit également être inclus dans la page users.html :

<script src="view/app.js"></script>

3.1. Service angulaire

Commençons par créer un service angulaire appelé UserCRUDService qui utilisera le service injecté AngularJS $ http pour appeler le serveur. Chaque appel sera placé dans une méthode distincte.

Voyons maintenant comment définir la méthode de récupération d’un utilisateur par identifiant à l’aide du noeud final /users/\ {userID} :

app.service('UserCRUDService',['$http', function($http) {

    this.getUser = function getUser(userId) {
        return $http({
            method : 'GET',
            url : 'users/' + userId
        });
    }
}]);

Définissons ensuite la méthode addUser qui envoie une demande POST à ​​l’URL /users et envoie les valeurs utilisateur dans l’attribut data :

this.addUser = function addUser(name, email) {
    return $http({
        method : 'POST',
        url : 'users',
        data : {
            name : name,
            email: email
        }
    });
}

La méthode updateUser est similaire à la précédente, à la différence qu’elle aura un paramètre id et fera une requête PATCH:

this.updateUser = function updateUser(id, name, email) {
    return $http({
        method : 'PATCH',
        url : 'users/' + id,
        data : {
            name : name,
            email: email
        }
    });
}

La méthode pour supprimer un enregistrement WebsiteUser fera une demande DELETE:

this.deleteUser = function deleteUser(id) {
    return $http({
        method : 'DELETE',
        url : 'users/' + id
    })
}

Enfin, examinons les méthodes permettant de récupérer la liste complète des utilisateurs:

this.getAllUsers = function getAllUsers() {
    return $http({
        method : 'GET',
        url : 'users'
    });
}

Toutes ces méthodes de service seront appelées par un contrôleur AngularJS .

3.2. Contrôleur angulaire

Nous allons créer un contrôleur UserCRUDCtrl AngularJS qui aura un UserCRUDService injecté et utiliser les méthodes de service pour obtenir la réponse du serveur, gérer les observations success et error et définir $ scope variables contenant les données de réponse pour les afficher en HTML. page.

Jetons un coup d’œil à la fonction getUser () qui appelle la fonction de service getUser (userId) et définit deux méthodes de rappel en cas de succès et d’erreur. Si la demande du serveur aboutit, la réponse est alors enregistrée dans une variable user . sinon, les messages d’erreur sont traités:

app.controller('UserCRUDCtrl',['$scope','UserCRUDService',
  function ($scope,UserCRUDService) {
      $scope.getUser = function () {
          var id = $scope.user.id;
          UserCRUDService.getUser($scope.user.id)
            .then(function success(response) {
                $scope.user = response.data;
                $scope.user.id = id;
                $scope.message='';
                $scope.errorMessage = '';
            },
            function error (response) {
                $scope.message = '';
                if (response.status === 404){
                    $scope.errorMessage = 'User not found!';
                }
                else {
                    $scope.errorMessage = "Error getting user!";
                }
            });
      };
}]);

La fonction addUser () appelle la fonction de service correspondante et gère la réponse:

$scope.addUser = function () {
    if ($scope.user != null && $scope.user.name) {
        UserCRUDService.addUser($scope.user.name, $scope.user.email)
          .then (function success(response){
              $scope.message = 'User added!';
              $scope.errorMessage = '';
          },
          function error(response){
              $scope.errorMessage = 'Error adding user!';
              $scope.message = '';
        });
    }
    else {
        $scope.errorMessage = 'Please enter a name!';
        $scope.message = '';
    }
}

Les fonctions updateUser () et deleteUser () sont similaires à celles ci-dessus:

$scope.updateUser = function () {
    UserCRUDService.updateUser($scope.user.id,
      $scope.user.name, $scope.user.email)
      .then(function success(response) {
          $scope.message = 'User data updated!';
          $scope.errorMessage = '';
      },
      function error(response) {
          $scope.errorMessage = 'Error updating user!';
          $scope.message = '';
      });
}

$scope.deleteUser = function () {
    UserCRUDService.deleteUser($scope.user.id)
      .then (function success(response) {
          $scope.message = 'User deleted!';
          $scope.User = null;
          $scope.errorMessage='';
      },
      function error(response) {
          $scope.errorMessage = 'Error deleting user!';
          $scope.message='';
      });
}

Enfin, définissons la fonction qui extrait une liste d’utilisateurs et la stocke dans la variable users :

$scope.getAllUsers = function () {
    UserCRUDService.getAllUsers()
      .then(function success(response) {
          $scope.users = response.data.__embedded.users;
          $scope.message='';
          $scope.errorMessage = '';
      },
      function error (response) {
          $scope.message='';
          $scope.errorMessage = 'Error getting users!';
      });
}

3.3. Page HTML

La page users.html utilisera les fonctions de contrôleur définies dans la section précédente et les variables stockées.

Tout d’abord, pour utiliser le module Angular, nous devons définir la propriété ng-app :

<html ng-app="app">

Ensuite, pour éviter de taper UserCRUDCtrl.getUser () à chaque fois que nous utilisons une fonction du contrôleur, nous pouvons envelopper nos éléments HTML dans un div avec un jeu de propriétés ng-controller :

<div ng-controller="UserCRUDCtrl">

Créons le formulaire _ qui entrera et affichera les valeurs de l’objet WebiteUser que nous voulons manipuler. Chacun de ceux-ci aura un ensemble d’attributs ng-model_ , qui le lie à la valeur de l’attribut:

<table>
    <tr>
        <td width="100">ID:</td>
        <td><input type="text" id="id" ng-model="user.id"/></td>
    </tr>
    <tr>
        <td width="100">Name:</td>
        <td><input type="text" id="name" ng-model="user.name"/></td>
    </tr>
    <tr>
        <td width="100">Age:</td>
        <td><input type="text" id="age" ng-model="user.email"/></td>
    </tr>
</table>

La liaison de l’entrée id à la variable user.id , par exemple, signifie que chaque fois que la valeur de l’entrée est modifiée, cette valeur est définie dans la variable user.id et inversement.

Utilisons ensuite l’attribut ng-click pour définir les liens qui déclencheront l’appel de chaque fonction du contrôleur CRUD définie:

<a ng-click="getUser(user.id)">Get User</a>
<a ng-click="updateUser(user.id,user.name,user.email)">Update User</a>
<a ng-click="addUser(user.name,user.email)">Add User</a>
<a ng-click="deleteUser(user.id)">Delete User</a>

Enfin, affichons la liste des utilisateurs entièrement et par nom:

<a ng-click="getAllUsers()">Get all Users</a><br/><br/>
<div ng-repeat="usr in users">
{{usr.name}} {{usr.email}}

4. Conclusion

Dans ce tutoriel, nous avons montré comment créer une application CRUD en utilisant AngularJS et la spécification Spring Data REST .

Le code complet de l’exemple ci-dessus se trouve dans le projet GitHub

Pour exécuter l’application, vous pouvez utiliser la commande mvn spring-boot: run et accéder à l’URL /users.html .