Spring BootとAngularを使用したWebアプリケーションの構築

1. 概要

link:/spring-boot[Spring Boot]とhttps://angular.io/[Angular]は、最小限のフットプリントでWebアプリケーションを開発するのに最適な強力なタンデムを形成します。
このチュートリアルでは、RESTfulバックエンドの実装にlink:/spring-boot[Spring Boot]を使用し、JavaScriptベースの作成にhttps://angular.io/[Angular]を使用します。フロントエンド。*

参考文献:

Springのインターフェース駆動型コントローラ

JavaインターフェイスでSpring MVCリクエストアノテーションを使用してコントローラーを作成する方法を学びます。
link:/spring-interface-driven-controllers [詳細]→

Spring REST API OAuth2 Angular

Spring REST API用にOAuth2を設定する方法と、Angularクライアントからそれを使用する方法を学びます。
link:/rest-api-spring-oauth2-angular [詳細]↠’

2. Spring Bootアプリケーション

デモWebアプリケーションの機能は、実際には非常に単純化されています。 これは、メモリ内のlink:/java-in-memory-databases[H2データベース]からJPAエンティティの_List_を取得して表示し、プレーンなHTMLフォームを介して新しいエンティティを永続化することに絞られます。 。

* 2.1。 Mavenの依存関係*

Spring Bootプロジェクトの依存関係は次のとおりです。
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>
_https://search.maven.org/search?q = g:org.springframework.boot%20AND%20a:spring-boot-starter-web [spring-boot-starter-web] _を含めたことに注意してください。 RESTサービスの作成に使用し、_https://search.maven.org/search?q = g:org.springframework.boot%20AND%20a:spring-boot-starter-data-jpa [spring-boot- starter-jpa] _永続層を実装するため。
https://search.maven.org/search?q=g:com.h2database%20AND%20a:h2[H2 database]バージョンも、Spring Boot親によって管理されます。

* 2.2。 JPAエンティティクラス*

アプリケーションのドメインレイヤーをすばやくプロトタイプ化するために、単純なJPAエンティティクラスを定義して、ユーザーのモデリングを担当します。
@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    private final String name;
    private final String email;

    // standard constructors / setters / getters / toString
}

* 2.3。 _UserRepository_インターフェイス*

_User_エンティティには基本的なCRUD機能が必要なので、_UserRepository_インターフェイスも定義する必要があります。
@Repository
public interface UserRepository extends CrudRepository<User, Long>{}

* 2.4。 RESTコントローラー*

それでは、REST APIを実装しましょう。 この場合、単純なRESTコントローラーです。
@RestController
@CrossOrigin(origins = "http://localhost:4200")
public class UserController {

    // standard constructors

    private final UserRepository userRepository;

    @GetMapping("/users")
    public List<User> getUsers() {
        return (List<User>) userRepository.findAll();
    }

    @PostMapping("/users")
    void addUser(@RequestBody User user) {
        userRepository.save(user);
    }
}
_UserController_クラスの定義には本質的に複雑なものはありません。
もちろん、ここで注目に値する唯一の実装の詳細は、https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/CrossOriginの使用です。 html [_ @ CrossOrigin_]アノテーション*。 名前が示すように、注釈はサーバー上でlink:/spring-cors[Cross-Origin Resource Sharing](CORS)を有効にします。
*この手順は必ずしも必要ではありません。* Angularフロントエンドをhttp:// localhost:4200 [_http:// localhost:4200_]に展開し、ブートバックエンドをhttp:// localhost:8080 [_http:/に展開しているため/ localhost:8080 _]、*ブラウザは一方から他方へのリクエストを拒否します。*
コントローラのメソッドに関して、_getUser()_はデータベースからすべての_User_エンティティを取得します。 同様に、_addUser()_メソッドは新しいエンティティをデータベースに保持し、https://www.baeldung.com/spring-request-response-body [request body]で渡されます。
物事を単純にするために、エンティティを永続化する前にlink:/spring-boot-bean-validation[Spring Boot validation]をトリガーするコントローラー実装から意図的に除外しました。 ただし、実稼働環境では、ユーザー入力を信頼できないため、サーバー側の検証は必須の機能である必要があります。

* 2.5。 Spring Bootアプリケーションのブートストラップ*

最後に、標準のSpring Bootブートストラップクラスを作成し、データベースにいくつかの_User_エンティティを追加します。
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    CommandLineRunner init(UserRepository userRepository) {
        return args -> {
            Stream.of("John", "Julie", "Jennifer", "Helen", "Rachel").forEach(name -> {
                User user = new User(name, name.toLowerCase() + "@domain.com");
                userRepository.save(user);
            });
            userRepository.findAll().forEach(System.out::println);
        };
    }
}
それでは、アプリケーションを実行しましょう。 予想どおり、起動時に_User_エンティティのリストがコンソールに出力されます:
User{id=1, name=John, [email protected]}
User{id=2, name=Julie, [email protected]}
User{id=3, name=Jennifer, [email protected]}
User{id=4, name=Helen, emai[email protected]}
User{id=5, name=Rachel, [email protected]}

3. 角度アプリケーション

デモのSpring Bootアプリケーションを起動して実行したら、RESTコントローラーAPIを使用できるシンプルなAngularアプリケーションを作成しましょう。

* 3.1。 Angular CLIのインストール*

強力なコマンドラインユーティリティであるhttps://cli.angular.io/[Angular CLI]を使用して、Angularアプリケーションを作成します。
Angular CLIは非常に貴重なツールです。* Angularプロジェクト全体をゼロから作成し、わずかなコマンドでコンポーネント、サービス、クラス、インターフェースを生成できるためです*。
https://www.npmjs.com/[npm](Node Package Manager)をインストールしたら、コマンドコンソールを開いて次のコマンドを入力します。
npm install -g @angular/[email protected]
それでおしまい。 上記のコマンドは、Angular CLIの最新バージョンをインストールします。

3.2. Angular CLIを使用したプロジェクトの足場

実際のところ、Angularアプリケーション構造を一から生成することができます。 しかし、正直なところ、これはエラーが発生しやすく時間のかかるタスクであり、すべての場合に回避する必要があります。
代わりに、Angular CLIにハードワークを任せます。 コマンドコンソールを開き、アプリケーションを作成するフォルダーに移動して、コマンドを入力します。
ng new angularclient
_new_コマンドは、_angularclient_ディレクトリ内にアプリケーション構造全体を生成します。

* 3.3。 Angularアプリケーションのエントリポイント*

_angularclient_ folderの内部を見ると、Angular CLIがプロジェクト全体を効果的に作成していることがわかります。
  • Angularのアプリケーションファイルはhttps://www.typescriptlang.org/ [TypeScript] https://www.typescriptlang.org/ [、]を使用して、プレーンJavaScriptにコンパイルされるJavaScriptの型付きスーパーセットを使用します。*ただし、角度アプリケーションは、単純な古い_index.html_ファイルです。

    このファイルを次のように編集しましょう。
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Spring Boot - Angular Application</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <link rel="stylesheet"
    href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
    integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
    crossorigin="anonymous">
</head>
<body>
  <app-root></app-root>
</body>
</html>
上記を見るとわかるように、https://getbootstrap.com/ [Bootstrap 4]が含まれているため、アプリケーションUIコンポーネントをより洗練された外観にすることができます。 もちろん、そこにある束から別のUIキットを選択することもできます。
_ <body> _セクション内のカスタム_ <app-root> </ app-root> _タグに注意してください。 _ <app-root> _は標準のHTML 5要素ではないため、一見するとかなり奇妙に見えます。
  • _ <app-root> _は、Angularがアプリケーションのルートコンポーネント*をレンダリングするために使用するルートセレクターであるため、そのままにしておきましょう。

* 3.4。 _app.component.ts_ルートコンポーネント*

AngularがHTMLテンプレートをコンポーネントにバインドする方法をよりよく理解するために、_src / app_ディレクトリに移動し、_app.component.ts_ TypeScriptファイルを編集します–ルートコンポーネント:
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  title: string;

  constructor() {
    this.title = 'Spring Boot - Angular Application';
  }
}
明らかな理由から、TypeScriptの学習には深く入りません。 それでも、ファイルが_AppComponent_クラスを定義し、_string_(小文字)型のフィールド_title_を宣言していることに注目してください。 間違いなく、JavaScriptと入力されています。
さらに、コンストラクターは_string_値を使用してフィールドを初期化します。これは、Javaで行うのとほぼ同じです。
最も関連性の高い部分は、3つの要素を定義する_ @ Component_メタデータマーカーまたはデコレータ*です。
  1. selector –コンポーネントをHTMLにバインドするために使用されるHTMLセレクター
    テンプレートファイル

  2. templateUrl –コンポーネントに関連付けられたHTMLテンプレートファイル

  3. styleUrls –コンポーネントに関連付けられた1つ以上のCSSファイル

    予想どおり、_app.component.html_および_app.component.css_ファイルを使用して、ルートコンポーネントのHTMLテンプレートとCSSスタイルを定義できます。
    最後に、_selector_要素はコンポーネント全体を_index.html_ファイルに含まれる_ <app-root> _セレクターにバインドします。

* 3.5。 _app.component.html_ファイル*

app.component.htmlファイルを使用すると、*ルートコンポーネントのHTMLテンプレートを定義する* _AppComponent_クラスを作成できるため、2つのボタンを持つ基本的なナビゲーションバーを作成するために使用します。
最初のボタンをクリックすると、Angularはデータベースに保存されている_User_エンティティのリストを含むテーブルを表示します。 同様に、2番目のボタンをクリックすると、HTMLフォームがレンダリングされ、データベースに新しいエンティティを追加するために使用できます。
<div class="container">
  <div class="row">
    <div class="col-md-12">
      <div class="card bg-dark my-5">
        <div class="card-body">
          <h2 class="card-title text-center text-white py-3">{{ title }}</h2>
          <ul class="text-center list-inline py-3">
            <li class="list-inline-item"><a routerLink="/users" class="btn btn-info">List Users</a></li>
            <li class="list-inline-item"><a routerLink="/adduser" class="btn btn-info">Add User</a></li>
          </ul>
        </div>
      </div>
      <router-outlet></router-outlet>
    </div>
  </div>
</div>
ファイルの大部分は標準のHTMLですが、注意すべきいくつかの注意事項があります。
*最初の式は_ \ {\ {title}} _式です。 二重中括弧_ \ {\ {変数名}} _は、Angularが変数補間を実行するために使用するプレースホルダーです*。
_AppComponent_クラスは、_Spring Boot – Angular Application_という値で_title_フィールドを初期化したことに注意してください。 したがって、Angularはテンプレートのこのフィールドの値を表示します。 同様に、コンストラクターで値を変更すると、テンプレートに反映されます。
  • 2番目に注意することは、_routerLink_属性*です。

  • Angularは、ルーティングモジュールを介したリクエストのルーティングにこの属性を使用します*(これについては後ほど説明します)。 今のところ、モジュールが特定のコンポーネントへの_ / users_パスへのリクエストと、別のコンポーネントへの_ / adduser_へのリクエストをディスパッチすることを知るだけで十分です。

    いずれの場合も、一致するコンポーネントに関連付けられたHTMLテンプレートは、_ <router-outlet> </ router-outlet> _プレースホルダー内にレンダリングされます。

3.6. _User_クラス

Angularアプリケーションはデータベース内の_User_エンティティからフェッチして永続化するため、TypeScriptを使用して簡単なドメインモデルを実装しましょう。
ターミナルコンソールを開いて、_model_ディレクトリを作成しましょう。
ng generate class user
Angular CLIは空の_User_クラスを生成します。 いくつかのフィールドを追加しましょう:
export class User {
    id: string;
    name: string;
    email: string;
}

3.7. _UserService_サービス

クライアント側のドメイン_User_クラスが既に設定されているので、http:// localhost:8080 / usersエンドポイントに対してGETおよびPOSTリクエストを実行するサービスクラスを実装しましょう。
*これにより、RESTコントローラーへのアクセスを単一のクラスにカプセル化でき、アプリケーション全体で再利用できます*。
コンソール端末を開いて_service_ディレクトリを作成し、そのディレクトリ内で次のコマンドを発行します。
ng generate service user-service
次に、Angular CLIが作成した_user.service.ts_ファイルを開いて、リファクタリングします。
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { User } from '../model/user';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class UserService {

  private usersUrl: string;

  constructor(private http: HttpClient) {
    this.usersUrl = 'http://localhost:8080/users';
  }

  public findAll(): Observable<User[]> {
    return this.http.get<User[]>(this.usersUrl);
  }

  public save(user: User) {
    return this.http.post<User>(this.usersUrl, user);
  }
}
_UserService_クラスがどのように機能するかを理解するために、TypeScriptの背景は必要ありません。 簡単に言えば、Spring Bootで以前に実装したRESTコントローラーAPIを使用するために必要なすべての機能を再利用可能なコンポーネントにカプセル化します。
_findAll()_メソッドは、https://angular.io/guide/http [Angular's _HttpClient_]を介してhttp:// localhost:8080 / usersエンドポイントに対してGET HTTPリクエストを実行します。 このメソッドは、_User_オブジェクトの配列を保持する_https://angular.io/guide/observables [Observable] _インスタンスを返します。
同様に、_save()_メソッドは、http:// localhost:8080 / usersエンドポイントに対してPOST HTTP要求を実行します。
_HttpClient_ ’のリクエストメソッドでタイプ_User_を指定することにより、バックエンドレスポンスをより簡単かつ効果的な方法で利用できます。
最後に、https://angular.io/api/core/Injectable [_ @ Injectable()_]メタデータマーカーの使用に注意しましょう。 これは、https://angular.io/guide/dependency-injection [Angularの依存性インジェクター] *を介してサービスを作成および注入する必要があることを通知します。

* 3.8。 _UserListComponent_コンポーネント*

この場合、_UserService_クラスは、RESTサービスとアプリケーションのプレゼンテーション層の間の薄い中間層です。 したがって、データベースに保持されている_User_エンティティのリストをレンダリングするコンポーネントを定義する必要があります。
ターミナルコンソールを開いて、_user-list_ディレクトリを作成し、ユーザーリストコンポーネントを生成しましょう。
ng generate component user-list
Angular CLIは、_https://angular.io/api/core/OnInit [ngOnInit] _インターフェイスを実装する空のコンポーネントクラスを生成します。 インターフェースはhook _ngOnInit()_メソッドを宣言します。これは、実装クラスのインスタンス化が完了した後、およびコンストラクターを呼び出した後に、Angularが呼び出します。
クラスをリファクタリングして、コンストラクタで_UserService_インスタンスを取得できるようにします。
import { Component, OnInit } from '@angular/core';
import { User } from '../model/user';
import { UserService } from '../service/user.service';

@Component({
  selector: 'app-user-list',
  templateUrl: './user-list.component.html',
  styleUrls: ['./user-list.component.css']
})
export class UserListComponent implements OnInit {

  users: User[];

  constructor(private userService: UserService) {
  }

  ngOnInit() {
    this.userService.findAll().subscribe(data => {
      this.users = data;
    });
  }
}
_UserListComponent_クラスの実装は、一目瞭然です。 単に_UserServiceのfindAll()_メソッドを使用して、データベースに保存されているすべてのエンティティを取得し、_users_フィールドに格納します。
さらに、コンポーネントのHTMLファイル_user-list.component.html、_を編集して、エンティティのリストを表示するテーブルを作成する必要があります。
<div class="card my-5">
  <div class="card-body">
    <table class="table table-bordered table-striped">
      <thead class="thead-dark">
        <tr>
          <th scope="col">#</th>
          <th scope="col">Name</th>
          <th scope="col">Email</th>
        </tr>
      </thead>
      <tbody>
        <tr *ngFor="let user of users">
          <td>{{ user.id }}</td>
          <td>{{ user.name }}</td>
          <td><a href="mailto:{{ user.email }}">{{ user.email }}</a></td>
        </tr>
      </tbody>
    </table>
  </div>
</div>
  • *ngForディレクティブの使用に注意してください。*ディレクティブは_repeater_と呼ばれ、変数のコンテンツを反復処理し、反復的にレンダリングするために使用できます。 HTML要素。 この場合、テーブルの行を動的にレンダリングするために使用しました。

    さらに、各ユーザーの_id、_ _name_、および_email_を表示するために変数補間を使用しました。

* 3.9。 _UserFormComponent_コンポーネント*

同様に、データベースに新しい_User_オブジェクトを永続化できるコンポーネントを作成する必要があります。
_user-form_ディレクトリを作成して、次のように入力します。
ng generate component user-form
次に、_user-form.component.ts_ファイルを開いて、_UserFormComponent_クラスに_User_オブジェクトを保存するメソッドを追加します。
import { Component } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { UserService } from '../service/user.service';
import { User } from '../model/user';

@Component({
  selector: 'app-user-form',
  templateUrl: './user-form.component.html',
  styleUrls: ['./user-form.component.css']
})
export class UserFormComponent {

  user: User;

  constructor(private route: ActivatedRoute, private router: Router, private userService: UserService) {
    this.user = new User();
  }

  onSubmit() {
    this.userService.save(this.user).subscribe(result => this.gotoUserList());
  }

  gotoUserList() {
    this.router.navigate(['/users']);
  }
}
この場合、_UserFormComponent_はコンストラクターで_UserService_インスタンスも取ります。_onSubmit()_メソッドは、指定された_User_オブジェクトを保存するためにこのインスタンスを使用します。
エンティティの新しいリストを永続化したら、更新されたエンティティのリストを再表示する必要があるため、挿入後に_gotoUserList()_メソッドを呼び出して、ユーザーを_ / users_パスにリダイレクトします。
さらに、_user-form.component.html_ファイルを編集し、データベースに新しいユーザーを保持するためのHTMLフォームを作成する必要があります。
<div class="card my-5">
  <div class="card-body">
    <form (ngSubmit)="onSubmit()" #userForm="ngForm">
      <div class="form-group">
        <label for="name">Name</label>
        <input type="text" [(ngModel)]="user.name"
          class="form-control" id="name" name="name" placeholder="Enter your name"
          required #name="ngModel">
      </div>
      <div [hidden]="!name.pristine" class="alert alert-danger">Name is required</div>
      <div class="form-group">
        <label for="email">Email</label>
        <input type="text" [(ngModel)]="user.email"
          class="form-control" id="email" name="email" placeholder="Enter your email address"
          required #email="ngModel">
        <div [hidden]="!email.pristine" class="alert alert-danger">Email is required</div>
      </div>
      <button type="submit" [disabled]="!userForm.form.valid" class="btn btn-info">Submit</button>
    </form>
  </div>
</div>
一見すると、フォームはかなり標準に見えます。 しかし、Angularの多くの機能をバックグラウンドでカプセル化します。
  • ngSubmitディレクティブの使用に注目しましょう。これは、フォームが送信されたときに_onSubmit()_メソッドを呼び出します*。

    次に、* template variable _#userForm_を定義したので、Angularは自動的にhttps://angular.io/api/forms/NgForm[_NgForm_]ディレクティブを追加し、フォーム全体を追跡できるようにします*。
    _NgForm_ディレクティブは、https://angular.io/api/forms/NgModel [_ngModel_]ディレクティブと_name_属性でフォーム要素用に作成したコントロールを保持し、その状態を含むプロパティを監視します。
  • _ngModel_ディレクティブは、フォームコントロールとクライアント側ドメインモデル間のhttps://angular.io/guide/template-syntax#ngModel [双方向データバインディング]機能を提供します。–– _User_クラス*。

    これは、フォーム入力フィールドに入力されたデータがモデルに流れることを意味します。 両方の要素の変更は、DOM操作を介してすぐに反映されます。
    さらに、_ngModel_を使用すると、各コントロールに異なるCSSクラスとDOMプロパティを追加することで、各フォームコントロールの状態を追跡し、https://angular.io/guide/form-validation [client-side validation]を実行できます。
    上記のHTMLファイルでは、フォームの値が変更されたときにアラートボックスを表示するためにのみ、フォームコントロールに適用されるプロパティを使用しました。

* 3.10。 _app-routing.module.ts_ファイル*

コンポーネントは単独で機能しますが、ユーザーがナビゲーションバーのボタンをクリックしたときに呼び出すためのメカニズムを使用する必要があります。
これは、https://angular.io/api/router/RouterModule [_RouterModule_]が機能する場所です。 したがって、app-routing.module.tsファイルを開いてモジュールを構成し、一致するコンポーネントにリクエストをディスパッチできるようにします。
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { UserListComponent } from './user-list/user-list.component';
import { UserFormComponent } from './user-form/user-form.component';

const routes: Routes = [
  { path: 'users', component: UserListComponent },
  { path: 'adduser', component: UserFormComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }
上記のように、* Routes_配列は、ユーザーがリンクをクリックしたとき、またはブラウザーのアドレスバーにURLを指定したときに表示するコンポーネントをルーターに指示します。*
ルートは2つの部分で構成されます。
  1. Path – a _string_は、ブラウザのアドレスバーのURLと一致します

  2. Component –ルートがアクティブなときに作成するコンポーネント
    (ナビゲーション)

    ユーザーが_ / users_パスにリンクする_List Users_ボタンをクリックするか、ブラウザーのアドレスバーにURLを入力すると、ルーターは_ <router-outlet> _プレースホルダーに_UserListComponent_コンポーネントのテンプレートファイルをレンダリングします。
    同様に、[ユーザーの追加]ボタンをクリックすると、_UserFormComponent_コンポーネントがレンダリングされます。

3.11。 _app.module.ts_ファイル

次に、app.module.tsファイルを編集する必要があります。Angularは、必要なすべてのモジュール、コンポーネント、サービスをインポートできません。
さらに、_UserService_クラスの作成と注入に使用するプロバイダーを指定する必要があります。 そうしないと、Angularはそれをコンポーネントクラスに挿入できません。
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
import { UserListComponent } from './user-list/user-list.component';
import { UserFormComponent } from './user-form/user-form.component';
import { UserService } from './service/user.service';

@NgModule({
  declarations: [
    AppComponent,
    UserListComponent,
    UserFormComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    FormsModule
  ],
  providers: [UserService],
  bootstrap: [AppComponent]
})
export class AppModule { }

4. アプリケーションの実行

最後に、アプリケーションを実行する準備が整いました。
これを実現するために、最初にSpring Bootアプリケーションを実行して、RESTサービスが稼働し、リクエストをリッスンするようにします。
Spring Bootアプリケーションが起動したら、コマンドコンソールを開いて次のコマンドを入力します。
ng serve --open
*これにより、Angularのライブ開発サーバーが起動し、http:// localhost:4200 *でブラウザーが開きます。
既存のエンティティを一覧表示したり、新しいエンティティを追加したりするためのボタンを備えたナビゲーションバーが表示されます。 最初のボタンをクリックすると、ナビゲーションバーの下に、データベースに保存されているエンティティのリストを含むテーブルが表示されます。+ link:/uploads/user-list-100x56.png%20100w [] +同様に、2番目のボタンをクリックすると、新しいエンティティを永続化するためのHTMLフォームが表示されます。
link:/uploads/user-form-100x58.png%20100w []

5. 結論

このチュートリアルでは、* Spring BootとAngular *を使用して基本的なWebアプリケーションを構築する方法を学びました。
いつものように、このチュートリアルに示されているすべてのコードサンプルはhttps://github.com/eugenp/tutorials/tree/master/spring-boot-angular[GitHubで]から入手できます。