Статьи

Пример Spring Boot & Angular 5 & Spring Data & Rest (CRUD)

Это руководство предоставляет полную реализацию Spring Boot, Angular 5 и данных Spring для построения сквозного одностраничного веб-приложения Java с примером. Мы будем использовать Spring Boot 1.5 для предоставления API-интерфейсов REST и Angular5 с маршрутизацией для построения нашего клиента, который будет использовать API-интерфейсы, предоставляемые сервером. Также мы будем интегрировать базу данных MySql с внутренним кодом для работы CRUD. Мы будем использовать угловой CLI для генерации углового проекта и инициализаторы весенней загрузки для генерации проекта весенней загрузки. В этой статье вы сможете создать приложение для управления пользователями с операцией CRUD, которое можно либо развернуть на автономном tomcat, либо развернуть клиент и сервер на разных серверах с запросами разных источников.

В следующей статье мы рассмотрим различные способы упаковки приложений весенней загрузки и angular 5 в один файл war с maven и развертывания в автономном tomcat. Также вас может заинтересовать интеграция этого приложения с Angular5 JWT Authentication и Spring Boot Security.

Угловой 5 Особенности

1. Angular 5 более быстрый, легкий и простой в использовании.

2. Возможности дизайна материалов и улучшенный компилятор с оптимизатором сборки

3. Введен новый HttpClientModule, который полностью переписывает существующий HttpModule.

4. Поддержка TypeScript 2.4.

5. Реактивная поддержка форм

Настройка среды

У нас есть две разные части, клиент и сервер, приложения, которое мы собираемся создать, и, следовательно, настройка среды также специфична для каждой части.

Angular5 Environment SetUp

Angular 5 предоставляет прекрасный инструмент — Angular CLI, чтобы начать работу с Angular. Здесь мы будем использовать тот же инструмент для создания примера углового приложения, а затем изменить его в соответствии с нашими требованиями. Чтобы начать работу с Angular CLI, необходимо установить узел, чтобы мы могли использовать инструмент NPM. Вы можете проверить, установлен ли узел на вашем компьютере или нет, нажав узел -v. На моей машине я получаю следующий результат.

Если он не установлен, сначала посетите официальный веб-сайт NodeJ, чтобы установить его. Теперь, когда это будет сделано, перейдите к местоположению своего рабочего пространства и выполните следующие команды, чтобы установить anglic cli и создать пример углового проекта.

1
2
npm install -g @angular/cli
ng new portal-app

Как только это будет сделано, вы можете перейти к местоположению и увидеть, что создано приложение-портал, содержащее все файлы и папки, сгенерированные командой angular cli для начала работы с angular 5. Теперь вы можете открыть свой любимый редактор для импорта проекта. Я импортировал этот проект в IntellijIdea и получил структуру, как показано ниже:

Здесь нужно проверить одну вещь: если вы установили NodeJ с помощью команды sudo, то при установке angular cli вы можете получить некоторые проблемы с разрешениями, как показано ниже. Чтобы избежать подобных ситуаций, всегда рекомендуется использовать команду brew при установке любых новых программного обеспечения.

Если вы столкнулись с этой проблемой, предоставьте доступ на чтение / запись к папке — / usr / local / lib / node_modules или следуйте инструкциям здесь — Поддержка Mac

Для пользователей Windows вы можете использовать командную строку git или cygwin для установки.

Spring Boot Environment SetUp

Команда Spring boot действительно упростила настройку среды начальной загрузки, предоставив инициализаторы по умолчанию. Откройте URL https://start.spring.io/ и сгенерируйте проект следующим образом.

Теперь разархивируйте user-portal.zip и импортируйте в Java IDE. Ниже будет окончательная структура.

Файлы по умолчанию, созданные командой CLI

Теперь давайте попробуем разобраться в разных сгенерированных файлах.

Модули — Модули разбивают приложение на логические части кода. Каждый фрагмент кода или модуля предназначен для выполнения одной задачи. Все модули загружаются main.ts.

Компонент — Компонент используется для объединения модулей.

tsconfig.json — Наличие файла tsconfig.json в каталоге указывает, что каталог является корнем проекта машинописного текста. Этот файл определяет корневые файлы и движения компилятора машинописного текста, необходимые для компиляции машинописного текста.

package.json — содержит все зависимости, определенные для углового проекта. Как только мы установим их, эти зависимости загружаются автоматически.

karma.conf.json — файл конфигурации для юнит-тестов кармы.

Файл .angular-cli.json будет иметь все конфигурации приложения, такие как информация о корневом и внешнем каталоге. Приветственный или основной html-файл вместе с основным ts-файлом. Вся остальная информация, связанная с окружающей средой, будет присутствовать здесь.

Теперь пришло время запустить приложение, сгенерированное dfault, и увидеть его в браузере. Если вы используете IntellijIdea, вы можете запустить команду ng serve из Терминала внутри него, а если не нажмете следующую команду в терминале.

1
2
cd portal-app
 ng serve

После этого откройте ваш браузер и нажмите на ссылку — http: // localhost: 4200 /, и угловое приложение будет запущено. Теперь мы можем начать модификацию приложения для создания портала управления пользователями.

API-интерфейсы Spring Boot Rest

Теперь давайте начнем с создания наших API-интерфейсов. У нас есть UerController, в котором представлены все API-интерфейсы для работы CRUD. @CrossOrigin используется для разрешения общего доступа к ресурсам (CORS), так что наше угловое приложение, работающее на другом сервере, может использовать эти API из браузера. Мы также можем настроить прокси с угловой стороны, используя proxy.config.json, который обсуждался в следующем разделе.

UserController.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.devglan.userportal;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
 
import java.util.List;
 
@CrossOrigin(origins = "http://localhost:4200", maxAge = 3600)
@RestController
@RequestMapping({"/api"})
public class UserController {
 
    @Autowired
    private UserService userService;
 
    @PostMapping
    public User create(@RequestBody User user){
        return userService.create(user);
    }
 
    @GetMapping(path = {"/{id}"})
    public User findOne(@PathVariable("id") int id){
        return userService.findById(id);
    }
 
    @PutMapping
    public User update(@RequestBody User user){
        return userService.update(user);
    }
 
    @DeleteMapping(path ={"/{id}"})
    public User delete(@PathVariable("id") int id) {
        return userService.delete(id);
    }
 
    @GetMapping
    public List findAll(){
        return userService.findAll();
    }
}

Внедрение сервиса Spring Boot

Класс обслуживания не имеет здесь никакой дополнительной логики, и это очень простая реализация.

UserServiceImpl.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@Service
public class UserServiceImpl implements UserService {
 
    @Autowired
    private UserRepository repository;
 
    @Override
    public User create(User user) {
        return repository.save(user);
    }
 
    @Override
    public User delete(int id) {
        User user = findById(id);
        if(user != null){
            repository.delete(user);
        }
        return user;
    }
 
    @Override
    public List findAll() {
        return repository.findAll();
    }
 
    @Override
    public User findById(int id) {
        return repository.findOne(id);
    }
 
    @Override
    public User update(User user) {
        return null;
    }
}

Внедрение данных Spring

Мы будем использовать реализацию JPA данных Spring для решения, связанного с ORM. Для ознакомления с реализацией данных Spring вы можете посетить другие мои посты — реализация Spring Boot JPA и Spring Boot Hibernate.

UserRepository.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
package com.devglan.userportal;
 
import org.springframework.data.repository.Repository;
 
import java.util.List;
 
public interface UserRepository extends Repository {
 
    void delete(User user);
 
    List findAll();
 
    User findOne(int id);
 
    User save(User user);
}

Настройка источника данных Spring Boot

application.properties

1
2
3
4
5
6
7
8
server.contextPath=/user-portal
spring.datasource.url=jdbc:mysql://localhost:3306/testdb
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.show-sql=true
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl
spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy

Сценарии по умолчанию

1
CREATE TABLE user(id INT NOT NULL AUTO_INCREMENT,email VARCHAR(255),first_name  VARCHAR(255),last_name VARCHAR(255),PRIMARY KEY (id))ENGINE=InnoDB;

Создать угловой компонент

В Angular CLI есть команда generate для создания компонента. Нажмите на команду ng generate user user, и она создаст папку пользователя внутри папки приложения. В этой папке пользователя будут все необходимые файлы для пользовательского модуля.

Сначала мы изменим app.component.html, включив в него 2 ссылки для списка пользователей и добавления пользователей. Все наши представления будут загружены в роутер-розетку.

app.component.html

01
02
03
04
05
06
07
08
09
10
11
12
<div class="container-fluid">
<div class="col-md-offset-1">
  <h1>
    Welcome to {{title}}!
  </h1>
</div>
 
<a routerLink="/users"> List Users</a>
<a style="margin-left:10px" routerLink="/add">Add User</a>
<br/>
<router-outlet></router-outlet>
</div>

Поскольку у нас есть два определенных выше маршрута, нам требуется два разных представления (user.component.html, add-user.component.html) и компоненты (user.component.ts, add-user.component.ts) для рендеринга на каждом click.Now позволяет нам реализовать код для user.component.ts.Here, метод ngOnInit () будет вызываться при загрузке этого компонента и извлекать все пользовательские записи и заполнять html-страницу.

user.compnent.ts

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
 
import { User } from '../models/user.model';
import { UserService } from './user.service';
 
@Component({
  selector: 'app-user',
  templateUrl: './user.component.html',
  styles: []
})
export class UserComponent implements OnInit {
 
  users: User[];
 
  constructor(private router: Router, private userService: UserService) {
 
  }
 
  ngOnInit() {
    this.userService.getUsers()
      .subscribe( data => {
        this.users = data;
      });
  };
 
  deleteUser(user: User): void {
    this.userService.deleteUser(user)
      .subscribe( data => {
        this.users = this.users.filter(u => u !== user);
      })
  };
 
}

Точно так же у нас есть add-user.component.ts

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import { Component } from '@angular/core';
import { Router } from '@angular/router';
 
import { User } from '../models/user.model';
import { UserService } from './user.service';
 
@Component({
  templateUrl: './add-user.component.html'
})
export class AddUserComponent {
 
  user: User = new User();
 
  constructor(private router: Router, private userService: UserService) {
 
  }
 
  createUser(): void {
    this.userService.createUser(this.user)
        .subscribe( data => {
          alert("User created successfully.");
        });
 
  };
 
}

user.model.ts

1
2
3
4
5
6
7
export class User {
 
  id: string;
  firstName: string;
  lastName: string;
  email: string;
}

user.service.ts

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import {Injectable} from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
 
import { User } from '../models/user.model';
 
 
const httpOptions = {
  headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
 
@Injectable()
export class UserService {
 
  constructor(private http:HttpClient) {}
 
  private userUrl = 'http://localhost:8080/user-portal/api';
 
  public getUsers() {
    return this.http.get(this.userUrl);
  }
 
  public deleteUser(user) {
    return this.http.delete(this.userUrl + "/"+ user.id);
  }
 
  public createUser(user) {
    return this.http.post(this.userUrl, user);
  }
 
}

Создать угловые виды

Как уже говорилось, у нас есть два представления — user.component.html и add-user.component.html.

user.component.html

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<div class="col-md-6">
<h2> User Details</h2>
 
<table class="table table-striped">
  <thead>
  <tr>
    <th class="hidden">Id</th>
    <th>FirstName</th>
    <th>LastName</th>
    <th>Email</th>
    <th>Action</th>
  </tr>
  </theadv
  <tbody>
  <tr *ngFor="let user of users">
    <td class="hidden">{{user.id}}</td>
    <td>{{user.firstName}}</td>
    <td>{{user.lastName}}</td>
    <td>{{user.email}}</td>
    <td><button class="btn btn-danger" (click)="deleteUser(user)"> Delete User</button></td>
  </tr>
  </tbody>
</table>
</div>

надстройку user.component.html

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
<div class="col-md-6">
  <h2 class="text-center">Add User</h2>
<form>
  <div class="form-group">
    <label for="email">Email address:</label>
    <input type="email" [(ngModel)]="user.email" placeholder="Email" name="email" class="form-control" id="email">
  </div>
 
  <div class="form-group">
    <label for="firstName">First Name:</label>
    <input [(ngModel)]="user.firstName" placeholder="First Name" name="firstName" class="form-control" id="firstName">
  </div>
 
  <div class="form-group">
    <label for="lastName">Last Name:</label>
   <input [(ngModel)]="user.lastName" placeholder="Last name" name="lastName" class="form-control" id="lastName">
  </div>
 
  <button class="btn btn-success" (click)="createUser()">Create</button>
</form>
</div>

Угловая маршрутизация

Теперь пришло время настроить маршрутизацию в angular. В этой конфигурации мы настроим путь и соответствующий компонент для загрузки, который, в свою очередь, загрузит соответствующее представление. Следующей является наша конфигурация маршрутизации.

app.routing.module.ts

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
 
import { UserComponent } from './user/user.component';
import {AddUserComponent} from './user/add-user.component';
 
const routes: Routes = [
  { path: 'users', component: UserComponent },
  { path: 'add', component: AddUserComponent }
];
 
@NgModule({
  imports: [
    RouterModule.forRoot(routes)
  ],
  exports: [
    RouterModule
  ],
  declarations: []
})
export class AppRoutingModule { }

Угловой модуль

Теперь мы почти закончили с нашим приложением. Нам нужно только включить все вышеперечисленные реализации в наш основной модуль.

app.module.ts

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
 
import { AppComponent } from './app.component';
import { UserComponent } from './user/user.component';
import { AppRoutingModule } from './app.routing.module';
import {UserService} from './user/user.service';
import {HttpClientModule} from "@angular/common/http";
import {AddUserComponent} from './user/add-user.component';
 
@NgModule({
  declarations: [
    AppComponent,
    UserComponent,
    AddUserComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    FormsModule
  ],
  providers: [UserService],
  bootstrap: [AppComponent]
})
export class AppModule { }

Конфигурация углового CLI-прокси

Чтобы настроить прокси в угловом CLI, нам нужно создать файл proxy.config.json в корне углового проекта и отредактировать стартовый скрипт в package.json.

proxy.config.json

1
2
3
4
5
6
{
  "/api/*": {
    "secure": false
  }
}

Значение target здесь является корневым контекстом приложения, а api является конечной точкой для пользовательского API.

package.json

1
"start": "ng serve --proxy-config proxy.config.json",

Теперь убедитесь, что измените значение userUrl на ‘/ api’ в файле user.service.ts и прокомментируйте @CrossOrigin в UserController.java. После этого используйте ng serve –proxy-config proxy.config.json или npm start для запуска угловое приложение.

Окончательная структура приложения

Запуск Spring Boot Application

Для развертывания приложения мы будем использовать встроенную в tomcat функцию весенней загрузки.

UserPortalApplication.java

01
02
03
04
05
06
07
08
09
10
11
12
package com.devglan.userportal;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
@SpringBootApplication
public class UserPortalApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(UserPortalApplication.class, args);
    }
}

Запустите приложение Angular

Теперь сервер включен. Он служит для развертывания углового приложения и давайте протестируем приложение.

Нажмите на ссылку — http: // localhost: 4200 /, и вы увидите следующий результат.

Теперь нажмите на ссылку Добавить пользователя, и появится следующая форма, чтобы добавить пользователя.

Теперь нажмите на список пользователей после добавления нескольких пользователей.

Вывод

Это в значительной степени касается учебника по весенней загрузке и интеграции с angular 5. В следующей статье мы рассмотрим развертывание этого приложения в одном файле war с maven и tomcat. Вы можете скачать исходный код здесь. Если позволяет время, мы постараемся интегрировать Spring Security с ним. Пожалуйста, дайте мне знать ваши комментарии ниже.

См. Оригинальную статью здесь: Spring Boot + Angular 5 + Spring Data + Rest Example (CRUD)

Мнения, высказанные участниками Java Code Geeks, являются их собственными.