Application AngularJS CRUD avec Spring Data 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

Afin de créer la prise en charge de la persistance, nous utiliserons la spécification Spring Data REST qui nous permettra d'effectuer des opérations CRUD sur un modèle de données.

Vous pouvez trouver toutes les informations nécessaires sur la configuration des points de terminaison REST dans l'introduction à Spring Data REST. Dans cet article, nous réutiliserons le projet existant que nous avons configuré pour le didacticiel d'introduction.

Pour la persistance, nous utiliserons la base de données H2 en mémoire.

En tant que modèle de données, l'article précédent définit une classe WebsiteUser , avec des propriétés d' id , de nom et d' e - mail et une interface de référentiel appelée UserRepository .

La définition de cette interface demande à 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 disponibles maintenant que nous appellerons plus tard à partir d' AngularJS .

2.1. Les ressources de la collection

Une liste de tous les utilisateurs sera disponible pour nous au niveau du terminal / des utilisateurs . 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" : "//localhost:8080/users/1" }, "User" : { "href" : "//localhost:8080/users/1" } } }, ... ] } }

2.2. Les ressources de l'article

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

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

{ "name" : "Bryan", "email" : "[email protected]", "_links" : { "self" : { "href" : "//localhost:8080/users/1" }, "User" : { "href" : "//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 requête en tant qu'objet JSON:

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

S'il n'y a aucune 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 , nous pouvons appeler l'URL / users / {UserID} avec la méthode DELETE. S'il n'y a pas d'erreurs, cela renvoie le code d'état 204 NO CONTENT.

2.3. Configuration MVC

Nous ajouterons également 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 requêtes cross-origin.

Spring Data REST a ajouté une prise en charge pour cela à partir de la version 1.5.0.RELEASE. Pour autoriser les requêtes d'un domaine différent, il vous suffit d'ajouter l' annotation @CrossOrigin au référentiel:

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

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

3. Création du client AngularJS

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

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

Next, we need to create an Angular module, controller, and service that will call the REST endpoints and display the returned data.

These will be placed in a JavaScript file called app.js that also needs to be included in the users.html page:

3.1. Angular Service

First, let's create an Angular service called UserCRUDService that will make use of the injected AngularJS$http service to make calls to the server. Each call will be placed in a separate method.

Let's take a look at defining the method for retrieving a user by id using the /users/{userID} endpoint:

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

Next, let's define the addUser method which makes a POST request to the /users URL and sends the user values in the data attribute:

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

The updateUser method is similar to the one above, except it will have an id parameter and makes a PATCH request:

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

The method for deleting a WebsiteUser record will make a DELETE request:

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

And finally, let's take a look at the methods for retrieving the entire list of users:

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

All of these service methods will be called by an AngularJS controller.

3.2. Angular Controller

We will create an UserCRUDCtrlAngularJS controller that will have an UserCRUDService injected and will use the service methods to obtain the response from the server, handle the success and error cases, and set $scope variables containing the response data for displaying it in the HTML page.

Let's take a look at the getUser() function that calls the getUser(userId) service function and defines two callback methods in case of success and error. If the server request succeeds, then the response is saved in a user variable; otherwise, error messages are handled:

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!"; } }); }; }]);

The addUser() function will call the corresponding service function and handle the response:

$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 = ''; } }

The updateUser() and deleteUser() functions are similar to the one above:

$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=''; }); }

And finally, let's define the function that retrieves a list of users, and stores it in the users variable:

$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. HTML Page

The users.html page will make use of the controller functions defined in the previous section and the stored variables.

First, in order to use the Angular module, we need to set the ng-app property:

Then, to avoid typing UserCRUDCtrl.getUser() every time we use a function of the controller, we can wrap our HTML elements in a div with a ng-controller property set:

Let's create theform that will input and display the values for the WebiteUser object we want to manipulate. Each of these will have a ng-model attribute set, which binds it to the value of the attribute:


    
ID:
Name:
Age:

Binding the id input to the user.id variable, for example, means that whenever the value of the input is changed, this value is set in the user.id variable and vice versa.

Ensuite, utilisons l' attribut ng-click pour définir les liens qui déclencheront l'appel de chaque fonction de contrôleur CRUD définie:

Get User Update User Add User Delete User

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

Get all Users

{{usr.name}} {{usr.email}}

4. Conclusion

Dans ce didacticiel, nous avons montré comment créer une application CRUD à l'aide d' AngularJS et de 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: exécutez et accédez à l'URL /users.html .