Перейти к основному содержимому

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

· 8 мин. чтения

Задача: Сумма двух чисел

Напишите функцию twoSum. Которая получает массив целых чисел nums и целую сумму target, а возвращает индексы двух чисел, сумма которых равна target. Любой набор входных данных имеет ровно одно решение, и вы не можете использовать один и тот же элемент дважды. Ответ можно возвращать в любом порядке...

ANDROMEDA

1. Обзор

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

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

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

Вы можете найти всю необходимую информацию о том, как настроить конечные точки REST во введении к 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" : "bryan@yahoo.com",
"_links" : {
"self" : {
"href" : "http://localhost:8080/users/1"
},
"User" : {
"href" : "http://localhost:8080/users/1"
}
}
}

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

{name: "Bryan", email: "bryan@yahoo.com"}

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

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

{name: "Bryan", email: "bryan@gmail.com"}

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

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

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

@Configuration
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {

public MvcConfig(){
super();
}

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

@Bean
WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> enableDefaultServlet() {
return (factory) -> factory.setRegisterDefaultServlet(true);
}
}

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 и отправляет пользовательские значения в атрибуте данных :

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 и который будет использовать методы службы для получения ответа от сервера, обработки случаев успеха и ошибок и установки переменных $scope , содержащих данные ответа, для их отображения на странице HTML. .

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

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 .