Приложение AngularJS CRUD с Spring Data REST

Данные]

  • ссылка:/tag/spring-data-rest/[Spring Data REST]

1. Обзор

В этом уроке мы собираемся создать пример простого приложения CRUD, использующего AngularJS для внешнего интерфейса и Spring Data REST для внутреннего.

2. Создание службы данных REST

Чтобы создать поддержку персистентности, мы будем использовать спецификацию Spring Data REST, которая позволит нам выполнять операции CRUD над моделью данных.

Вы можете найти всю необходимую информацию о том, как настроить конечные точки REST, по ссылке:/spring-data-rest-intro[введение в Spring Data REST]. В этой статье мы повторно используем существующий проект, который мы настроили для вводного руководства.

Для сохранения мы будем использовать H2 в базе данных памяти.

В качестве модели данных в предыдущей статье определен класс WebsiteUser со свойствами id , name и email и интерфейсом хранилища с именем UserRepository .

Определение этого интерфейса указывает Spring на создание поддержки для предоставления ресурсов коллекции REST и ресурсов элементов. Давайте внимательнее посмотрим на конечные точки, доступные нам сейчас, когда мы позже позвоним из AngularJS .

2.1. Коллекционные ресурсы

Список всех пользователей будет доступен нам в конечной точке /users . Этот URL может быть вызван с использованием метода GET и будет возвращать объекты JSON в форме:

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

2.2. Ресурсы предмета

Один объект WebsiteUser может управляться путем обращения к URL-адресам формы /users/\ {userID} с различными методами HTTP и запросом полезных данных.

Для получения объекта WebsiteUser мы можем получить доступ к /users/\ {userID} с помощью метода GET. Это возвращает объект JSON формы:

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

Чтобы добавить нового WebsiteUser , нам нужно вызвать /users с методом POST. Атрибуты новой записи WebsiteUser будут добавлены в тело запроса в виде объекта JSON:

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

Если ошибок нет, этот URL возвращает код состояния 201 CREATED.

Если мы хотим обновить атрибуты записи WebsiteUser , нам нужно вызвать URL /users/\ {UserID} с помощью метода PATCH и тела запроса, содержащего новые значения:

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

Чтобы удалить запись WebsiteUser , мы можем вызвать URL /users/\ {UserID} с помощью метода DELETE. Если ошибок нет, возвращается код состояния 204 НЕТ КОНТЕНТА.

2.3. Конфигурация MVC

Мы также добавим базовую конфигурацию MVC для отображения html-файлов в нашем приложении:

@Configuration
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {

    public MvcConfig(){
        super();
    }

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

2.4. Разрешение запросов перекрестного происхождения

Если мы хотим развернуть интерфейсное приложение AngularJS отдельно от REST API - нам нужно включить запросы между источниками.

Spring Data REST добавил поддержку для этого, начиная с версии 1.5.0.RELEASE. Чтобы разрешить запросы из другого домена, все, что вам нужно сделать, это добавить аннотацию @ CrossOrigin в репозиторий:

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

В результате к каждому ответу от конечных точек REST будет добавлен заголовок Access-Control-Allow-Origin .

3. Создание клиента AngularJS

Для создания внешнего интерфейса нашего приложения CRUD мы будем использовать AngularJS - хорошо известную инфраструктуру JavaScript, которая упрощает создание внешних приложений.

Чтобы использовать AngularJS , нам сначала нужно включить файл angular.min.js в нашу html-страницу, которая будет называться users.html :

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

Далее нам нужно создать модуль, контроллер и службу Angular, которые будут вызывать конечные точки REST и отображать возвращаемые данные.

Они будут помещены в файл JavaScript с именем app.js , который также должен быть включен на страницу users.html :

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

3.1. Угловой Сервис

Во-первых, давайте создадим службу Angular под названием UserCRUDService , которая будет использовать внедренную службу AngularJS $ http для выполнения вызовов на сервер. Каждый вызов будет размещен в отдельном методе.

Давайте рассмотрим определение метода для получения пользователя по идентификатору с использованием конечной точки /users/\ {userID} :

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

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

Далее, давайте определим метод addUser , который отправляет запрос POST на URL /users и отправляет пользовательские значения в атрибуте data

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

Метод updateUser похож на описанный выше, за исключением того, что он будет иметь параметр id и сделает запрос PATCH:

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

Метод удаления записи WebsiteUser сделает запрос DELETE:

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

И, наконец, давайте рассмотрим методы получения всего списка пользователей:

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

Все эти сервисные методы будут вызываться контроллером AngularJS .

3.2. Угловой контроллер

Мы создадим контроллер UserCRUDCtrl AngularJS , в который будет вставлен UserCRUDService , и будем использовать методы службы для получения ответа от сервера, обработки случаев success и error и установки переменных $ scope , содержащих данные ответа, для отображения его в HTML стр.

Давайте посмотрим на функцию getUser () , которая вызывает сервисную функцию getUser (userId) и определяет два метода обратного вызова в случае успеха и ошибки. Если запрос к серверу выполнен успешно, ответ сохраняется в переменной user ; в противном случае сообщения об ошибках обрабатываются:

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

Функция addUser () вызовет соответствующую сервисную функцию и обработает ответ:

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

Функции updateUser () и deleteUser () аналогичны приведенным выше:

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

И, наконец, давайте определим функцию, которая получает список пользователей и сохраняет его в переменной 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. HTML-страница

На странице users.html будут использоваться функции контроллера, определенные в предыдущем разделе, и сохраненные переменные.

Во-первых, чтобы использовать модуль Angular, нам нужно установить свойство ng-app :

<html ng-app="app">

Затем, чтобы избежать ввода UserCRUDCtrl.getUser () каждый раз, когда мы используем функцию контроллера, мы можем обернуть наши HTML-элементы в div с установленным свойством ng-controller :

<div ng-controller="UserCRUDCtrl">

Давайте создадим форму _, которая будет вводить и отображать значения для объекта WebiteUser , которым мы хотим манипулировать. Каждый из них будет иметь набор атрибутов ng-model_ , который связывает его со значением атрибута:

<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>

Например, привязка ввода id к переменной user.id означает, что при каждом изменении значения ввода это значение устанавливается в переменной user.id и наоборот.

Далее, давайте используем атрибут ng-click для определения ссылок, которые будут запускать каждую определенную функцию контроллера CRUD:

<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>

Наконец, давайте отобразим список пользователей целиком и по имени:

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

4. Заключение

В этом руководстве мы показали, как можно создать приложение CRUD, используя AngularJS и спецификацию Spring Data REST .

Полный код для приведенного выше примера можно найти в проекте GitHub .

Для запуска приложения вы можете использовать команду mvn spring-boot: run и получить доступ к URL-адресу /users.html .