狠狠撸

狠狠撸Share a Scribd company logo
#jjug_ccc #ccc_e5
AngularとSpring Bootで作る
SPA + RESTful Web Service
アプリケーション
株式会社カサレアル
多田 真敏?菊池 真登
2019/11/23
JJUG CCC 2019 Fall
(C) CASAREAL, Inc. All rights reserved. 1
#jjug_ccc #ccc_e5
大切なことなので
(C) CASAREAL, Inc. All rights reserved. 2
100%
宣伝です
80%
#jjug_ccc #ccc_e5
このセッションは
(C) CASAREAL, Inc. All rights reserved. 3
株式会社カサレアルは Angular と Spring Boot による
SPA開発の研修を提供します!
このセッションは
? Spring Boot と Angular の概要
? 組み合わせた時の開発のイメージ
をお伝えし、SPA開発へ誘う45分間です。
#jjug_ccc #ccc_e5
自己紹介:多田真敏
(C) CASAREAL, Inc. All rights reserved. 4
? 研修トレーナー@カサレアル
? Spring / Java EE / Microservices /
Cloud Foundry / Kubernetes
? Pivotal認定講師
? 日本Springユーザ会スタッフ
? CCCは12回連続12回目の登壇
#jjug_ccc #ccc_e5
株式会社カサレアル
(C) CASAREAL, Inc. All rights reserved. 5
?他社にはない色々なプログラミング言語の
研修を提供しています!
#jjug_ccc #ccc_e5
目次
(C) CASAREAL, Inc. All rights reserved. 6
1.新しいコースを作ることになった背景
2.Spring Bootによるサーバサイド開発
3.Angularによるクライアント開発
4.どう組み合わせるの?
#jjug_ccc #ccc_e5
目次
(C) CASAREAL, Inc. All rights reserved. 7
1.新しいコースを作ることになった背景
2.Spring Bootによるサーバサイド開発
3.Angularによるクライアント開発
4.どう組み合わせるの?
#jjug_ccc #ccc_e5
新しいコースを作ることになった背景
(C) CASAREAL, Inc. All rights reserved. 8
? 引き合いが多数!
特に Angular のコースをご受講のお客様から
「Spring Boot との組み合わせ方が知りたい」
という声が!
#jjug_ccc #ccc_e5
それぞれ独立したコースを提供しています
(C) CASAREAL, Inc. All rights reserved. 9
? Angular入門(3日間)
? Angular 単体のコース
? 基礎からのSpring Boot(2日間)
? Spring Boot 単体のコース
たくさんの方にご受講いただいております!
#jjug_ccc #ccc_e5
両コースの受講者数も年々増加!
(C) CASAREAL, Inc. All rights reserved. 10
0
20
40
60
80
100
120
140
160
2017年度 2018年度 2019年度
Spring Boot受講者数増加率
Spring Boot受講者数増加率
0
20
40
60
80
100
120
140
160
180
200
2017年度 2018年度 2019年度
Angular入門受講者数増加率
Angular入門受講者数増加率
? 通年で提供を開始した2017年度を基準とした増加率
? 2019年度は11月までの実績値
2019年度も増加見込み! 11月でこの増加率!
#jjug_ccc #ccc_e5
両コースとも実績がある!
引き合いも多い!
組み合わせて提供することが
私たちの使命!
(C) CASAREAL, Inc. All rights reserved. 11
#jjug_ccc #ccc_e5
ワークショップとして提供!
(C) CASAREAL, Inc. All rights reserved. 12
?実際にアプリを作る研修
?クライアント、サーバの両サイドが一通り実装
できるようになることが目標の研修
?認証やページネーションも扱う予定
?本格的なアプリケーションの実装方法を学ぶ
チャンス!
?選べる二つのコース体系!
#jjug_ccc #ccc_e5
一ヶ月パック
(C) CASAREAL, Inc. All rights reserved. 13
? HTML/CSS、JavaScriptといったフロントエンドの基礎
? AngularによるSPA開発
? Javaの文法からSpring Bootによるサーバサイド開発
? AngularとSpring BootによるSPA開発
を一気に学べる一ヶ月のコースです。
他のプログラミング経験者のスキルチェンジに最適!
#jjug_ccc #ccc_e5
定期オープンコース(3日間)
(C) CASAREAL, Inc. All rights reserved. 14
? Angular入門(3日間)
? 基礎からのSpring Boot(2日間)
を、ご受講いただいた方を対象に、
AngularとSpring BootによるSPA開発
を体験いただく3日間のオープンコースです。
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 15
準備中…
#jjug_ccc #ccc_e5
ご興味ありますか?
(C) CASAREAL, Inc. All rights reserved. 16
ふるってご参加ください!
#jjug_ccc #ccc_e5
目次
(C) CASAREAL, Inc. All rights reserved. 17
1.新しいコースを作ることになった背景
2.Spring Bootによるサーバサイド開発
3.Angularによるクライアント開発
4.どう組み合わせるの?
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 18
? Pivotal社が中心に開発
? Spring Framework の設定地獄から脱却を目指したもの
? Starter ライブラリで Maven の dependency の記述を
減らせる
? Auto Configuration で必要な設定は済んでいる
Spring Bootとは
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 19
?業務固有の処理を実装するのは相変わらず
?開発効率が上がるわけではない
?三つの層を地道に実装していく
ただし
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 20
?https://start.spring.io/
?Web 上でひな型を作成できる
?IntelliJ IDEA や STS などの主要 IDE も連携している
今回は
? Maven
? Java 11
? Dependencies Spring Web
で作成
Spring Initializrで楽々初期構築
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 21
作成例 - 1
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 22
作成例 - 2
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 23
? Spring MVC による Webアプリの開発用 Starter
? 内部に組み込み Tomcat を持つ
? Javaアプリとして起動するだけで Webアプリとして
立ち上がる
? JSON ? Java オブジェクトの変換機能をあらかじ
め持っている
spring-boot-starter-web
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 24
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
pom.xmlにこれを追加するだけで、
Webアプリに必要な設定が完了する
spring-boot-starter-web
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 25
?デフォルトでは jar ファイルが出来上がる
?必要となるライブラリが内包される
?実行するだけで Webアプリとして立ち上がる
パッケージングで出来上がるもの
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 26
DispatcherServlet
JSONを送信
RestControllerRestControllerRestControllerRestController
リクエストでは
JSON ? Java オブジェクト
に変換される
レスポンスでは
Java オブジェクト ? JSON
に変換される
JSONを返却
RESTとしてのSpring Boot
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 27
@RestController
@RequestMapping("/api/tasks")
public class TaskRestController {
@PostMapping
public ResponseEntity order(@RequestBody TaskRequest taskRequest) {
// 要件に応じた処理
return ResponseEntity.created(uri).build();
}
}
RESTful Web Service
が構築できる
Javaオブジェクトを受け取り返すだけで
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 28
? static locations
? src/main/resources/static 配下に静的コンテンツ
を配置することでクライアントに返却できる
? Welcome Page
? src/main/resources/static 配下に置いた
index.html が自動的に Welcome Page に設定され
トップページアクセスすると返却される
Webサーバとしての機能も充実
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 29
http://localhost:8080
にアクセスすると返却される
http://localhost:8080/js/index.js
とリクエストすると返却される
Webサーバとしての機能も充実
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 30
? Spring Security を導入する
? Spring Boot なら Starterライブラリを追加するだけ
? ログイン?ログアウトだけじゃない!
? クロスサイト?リクエストフォージェリ(CSRF)対策も
デフォルトでサポート
? しかも、Angular アプリ向けのモードあり
もちろん新規コースで取り扱います!
Security対策も楽々!
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 31
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
pom.xmlにこれを追加するだけで、
Spring Securityが使えるようになる
spring-boot-starter-security
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 32
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository
.withHttpOnlyFalse());
}
} Security用のJavaConfigでこの太字の
部分を追加するだけ!
Angularアプリ用のCSRF対策の設定
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 33
? レスポンスヘッダーの Cookie に XSRF-TOKEN という
名前で CSRFトークンを発行する
? デフォルトの発行先は HttpSession
? Spring Security 4.1 からある
実は、Angularの動作に合わせたもの
CookieCsrfTokenRepositoryとは
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 34
A CsrfTokenRepository that persists the CSRF token in a
cookie named "XSRF-TOKEN" and reads from the header
"X-XSRF-TOKEN" following the conventions of AngularJS.
AngularJSの規則に従ってヘッダー「X-XSRF-TOKEN」か
らCSRFトークンから読み取る
Spring Securityのドキュメントにも
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 35
正規のWebサイト
①購入ページをリクエスト
②CSRFトークンを発行し、
レスポンスヘッダーのCookieに含める
③CookieからCSRFトークンを取得し、
リクエストボディ(またはヘッダー)に含めて
購入リクエストを送信
④CookieのCSRFトークンと
リクエストボディのCSRFトークンを比較し、
同じであれば購入OKとする
Cookieを利用したCSRF対策の動作概要
#jjug_ccc #ccc_e5
目次
(C) CASAREAL, Inc. All rights reserved. 36
1.新しいコースを作ることになった背景
2.Spring Bootによるサーバサイド開発
3.Angularによるクライアント開発
4.どう組み合わせるの?
#jjug_ccc #ccc_e5
自己紹介:菊池真登
(C) CASAREAL, Inc. All rights reserved. 37
? 研修トレーナー@カサレアル
? 登壇実績:Spring / Java SE
? 開発歴[Spring]:2012年から
? 開発歴[Angular]:2015年頃に
1.5年間AngularJSに触れて冬眠
? 今回新規コースのコンテンツ
作成を任命される
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 38
? Google製のフレームワーク
? JavaScript上で動作するWebアプリケーション用
? フルスタック
? TypeScript推奨
Angularとは
#jjug_ccc #ccc_e5
って、ネット検索で見つけられる情報なんて、
いらないですよね。。。
(C) CASAREAL, Inc. All rights reserved. 39
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 40
? 画面は基本的に index.html だけで遷移は
ない
? ボタンクリックなどで表示の切り替えができるが、
Angular が頑張ってそれっぽく見せている
? 必要なデータは XMLHttpRequest(XHR) でサーバ
から非同期で取得
? 構成要素が Spring MVCに近い
少し砕けた紹介を
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 41
http://localhost:4200 http://localhost:4200/product/list
左側のリンクをクリックすると、この部分の表示するための
「部品?Component」をAngularが切り替える
実際の作業イメージとしては、この「部品?Component」単位で
作成していく
Angularの頑張り
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 42
Template
<html>
Component
Injector
Service
データ
入力値
XHR
Angularを構成するもの
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 43
サーバサイド三層アーキテクチャー
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 44
サーバサイドJavaエンジニアであれば、実はとっつきやすいかも!
(注意:個人的な主観)
Template
<html>
Component
Injector
Service
データ
入力値
XHR
構成要素がSpring MVCに近い
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 45
? だからこそのTypeScript!
? クラスベースのオブジェクト指向
? 静的な型の指定
JavaScriptって、型なしじゃ?
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 46
@Injectable({
providedIn: 'root'
})
export class TaskDataService {
constructor(private http: HttpClient) {}
findAll(): Observable<Task[]> {
return this.http.get<Task[]>('/api/tasks');
}
}
DI で HttpClient を代入
HTTP GET リクエスト
でデータを取得
実際のソースコード - Service
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 47
@Component({
selector: 'app-task-table',
templateUrl: './task-table.component.html',
styleUrls: ['./task-table.component.css']
})
export class TaskTableComponent implements OnInit {
taskList: Task[];
constructor(private taskDataService: TaskDataService) {}
ngOnInit() {
this.taskDataService.findAll().subscribe(tasks => {
this.taskList = tasks;
});
}
データを取得して
フィールドに代入
実際のソースコード - Component
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 48
<table>
<tr *ngFor="let todoTask of taskList"
(click)="clickRow(todoTask)" [ngClass]="onColor(todoTask)">
<td>{{todoTask.id}}</td>
<td>{{todoTask.todo}}</td>
<td>{{todoTask.priority}}</td>
</tr>
</table>
Component と Template間は
双方向データバインディングで
やり取り可能
実際のソースコード - Template
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 49
export class Task {
id: number;
todo: string;
priority: string;
constructor(id: number, todo: string, priority: string) {
this.id = id;
this.todo = todo;
this.priority = priority;
}
}
オリジナルのクラスを定義
クラスの宣言
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 50
export class TaskDataService {
constructor(private http: HttpClient) {}
findAll(): Observable<Task[]> {
return this.http.get<Task[]>('/api/tasks');
}
}
ジェネリクスの
型パラメータとして利用
Service のソースコード
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 51
IDEの手厚い補完機能が受けられるので、
Java開発者にとってはありがたい
トランスパイル!
(変換!)
Webブラウザで動かすには
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 52
? HttpClient が高度に抽象化!
? Angular に標準で備わっている
? GET、POST など直感的でわかりやすい
? ジェネリクスによって戻り値の型をある程度は
精査できる
XHRって、しんどくない?
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 53
export class TaskDataService {
constructor(private http: HttpClient) {}
findAll(): Observable<Task[]> {
return this.http.get<Task[]>('/api/tasks');
}
}
HttpClientの呼び出し
方のサンプル
jQueryのコードと比較
するとだいぶ簡略化
Serviceのソースコード
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 54
正規のWebサイト
①購入ページをリクエスト
②CSRFトークンを発行し、
レスポンスヘッダーのCookieに含める
③CookieからCSRFトークンを取得し、
リクエストボディ(またはヘッダー)に含めて
購入リクエストを送信
④CookieのCSRFトークンと
リクエストボディのCSRFトークンを比較し、
同じであれば購入OKとする
この部分が自動
化されます!
HttpClientはCSRF対策もばっちり
#jjug_ccc #ccc_e5
(C) CASAREAL, Inc. All rights reserved. 55
? X-XSRF-TOKENヘッダーにトークンを含めて送信
HttpClient はこれをリクエスト時に自動的に 行う
フレームワークに乗っかるだけで
お手軽にセキュアなアプリが作れる!
HttpClientはCSRF対策もばっちり
#jjug_ccc #ccc_e5
目次
(C) CASAREAL, Inc. All rights reserved. 56
1.新しいコースを作ることになった背景
2.Spring Bootによるサーバサイド開発
3.Angularによるクライアント開発
4.どう組み合わせるの?
#jjug_ccc #ccc_e5
プロジェクトの構成
(C) CASAREAL, Inc. All rights reserved. 57
? クライアントサイド?サーバサイドは別プロジェクト
にする
? 分業がしやすい
? マイクロサービスへの足掛かりにしやすい
? (無いとは思うが)クライアントもしくは
サーバサイドの載せ替えがしやすい
#jjug_ccc #ccc_e5
全体のイメージ
(C) CASAREAL, Inc. All rights reserved. 58
親プロジェクト
Angular
プロジェクト
Spring Boot
プロジェクト
MavenやGradleの
マルチプロジェクト機能で
サブプロジェクトとして作成
#jjug_ccc #ccc_e5
どう組み合わせるの? - 開発時
(C) CASAREAL, Inc. All rights reserved. 59
? Spring Bootは通常起動でポート8080で動作
? Angularは検証用サーバでポート4200で動作
? 任意のURLにリクエストを転送する機能をもつ
? サーバのAPIとの通信はポート8080に転送する
#jjug_ccc #ccc_e5
Angular CLIのng serve
(C) CASAREAL, Inc. All rights reserved. 60
?Angular CLI
?開発をサポートするコマンドライン
?ng serve
?Angular CLI に含まれる検証サーバ機能
?ファイルの編集を検知し即時反映される
?サーバ再起動が必要ないため開発効率が向上
#jjug_ccc #ccc_e5
転送のイメージ
(C) CASAREAL, Inc. All rights reserved. 61
index.htmlなどは
直接返却
Webブラウザ
ng serve
ポート4200
Spring Boot
ポート8080
/api/tasks /api/tasks
JSONJSON
検証用サーバが
ポート8080に転送
する
#jjug_ccc #ccc_e5
転送の設定
(C) CASAREAL, Inc. All rights reserved. 62
{
"/api": {
"target": "http://localhost:8080",
"secure": false
}
} http://localhost:4200/api/**
に合致するリクエストは、
http://localhost:8080/api/**
に転送する設定
proxy.conf.json
"serve": {
"options": {
"browserTarget": "client:build",
"proxyConfig": "src/proxy.conf.json"
},
angular.json
ng serveのオプションに転送
の設定を読み込ませる
#jjug_ccc #ccc_e5
開発時、特に気にするものはない
(C) CASAREAL, Inc. All rights reserved. 63
export class TaskDataService {
findAll(): Observable<Task[]> {
return this.http.get<Task[]>('/api/tasks');
}
}
@RestController
@RequestMapping("/api/tasks")
public class TaskRestController {
@GetMapping
public List<TaskResponse> findAll() {
return this.todoService.findAll().stream()
.map(
todo -> new TaskResponse(todo))
.collect(Collectors.toList());
}
}
HttpClientのメソッドには
「/api/tasks」とだけ記述。
ポート番号の違いの考慮は不要
#jjug_ccc #ccc_e5
どう組み合わせるの? - パッケージング
(C) CASAREAL, Inc. All rights reserved. 64
? 今回は1つの成果物で動くようする
Webブラウザ サーバ
APIだけでなく
静的コンテンツも
返却
#jjug_ccc #ccc_e5
基本方針
(C) CASAREAL, Inc. All rights reserved. 65
? トップページアクセスで index.html を返却
? 関連する JavaScript もダウンロード可能
? Spring Boot の static locations
? Spring Boot の Welcome Page
の機能を使う
#jjug_ccc #ccc_e5
なぜSpring BootのWebサーバ機能?
(C) CASAREAL, Inc. All rights reserved. 66
? Cross-Origin Resource Sharing の考慮が不要
? 最終成果物を1つにできるのでディプロイが楽
? 静的コンテンツのダウンロードは初回アクセスの
時だけなので Webサーバとしての負荷は高くない
#jjug_ccc #ccc_e5
別々にホスティングするケースもご紹介
(C) CASAREAL, Inc. All rights reserved. 67
#jjug_ccc #ccc_e5
ホスティングサービスへのディプロイ
(C) CASAREAL, Inc. All rights reserved. 68
? Firebase hosting
? Azure
? Now
? Netlify
? GitHub pages
等の主要ホスティングサービスにはAngular CLI で
自動ディプロイが可能
https://angular.jp/guide/deployment#automatic-
deployment-with-the-cli
#jjug_ccc #ccc_e5
任意のWebサーバへのディプロイ
(C) CASAREAL, Inc. All rights reserved. 69
? Angular CLIのビルド機能を使ってビルドする
? ng build --prod というコマンドを使う
? 成果物のすべてをWebサーバにコピーする
という手順になる
詳しい手順はこちら
https://angular.jp/guide/deployment#basic-
deployment-to-a-remote-server
*サーバサイドのディプロイ先は別途ご用意ください
#jjug_ccc #ccc_e5
Same Origin Policy
(C) CASAREAL, Inc. All rights reserved. 70
異なるドメインへの通信は
許可されない
#jjug_ccc #ccc_e5
Spring MVC で CORS 対応
(C) CASAREAL, Inc. All rights reserved. 71
@RestController
@RequestMapping("/api/tasks")
public class TaskRestController {
@GetMapping
@CrossOrigin
public List<TaskResponse> findAll() {
return this.todoService.findAll().stream()
.map(todo -> new TaskResponse(todo))
.collect(Collectors.toList());
}
}
@CrossOriginを付けるだけ
#jjug_ccc #ccc_e5
サーバホスト名解決
(C) CASAREAL, Inc. All rights reserved. 72
Angular Spring Boot
http://localhost:4200 http://localhost:8080
Angular Spring Boot
https://angular.com https://spring.com
開発環境
本番環境
?開発環境の Angular アプリは http://localhost:8080
?本番環境のAngular アプリは https://boot.example.com
に非同期通信を行うように切り替える
#jjug_ccc #ccc_e5
環境設定ファイル
(C) CASAREAL, Inc. All rights reserved. 73
? Angular は環境ごとの設定値を定義できる
? 開発用のAPIのURL
? 本番用のAPIのURL
等を設定する
? ビルドのコマンドのオプションで環境を指定する
#jjug_ccc #ccc_e5
別々にホスティングするケースの紹介でした
(C) CASAREAL, Inc. All rights reserved. 74
こちら、別途qiita記事を用意しています!
Spring MVC で CORS
https://qiita.com/m_kikuchi/items/df8c070b228d
f44a5462
#jjug_ccc #ccc_e5
最終的に以下の形を目指す
(C) CASAREAL, Inc. All rights reserved. 75
Spring Boot アプリの jar :最終成果物
Angular アプリの jar
BOOT-INF
lib
META-INF
resources
#jjug_ccc #ccc_e5
static locations と Welcome Page
(C) CASAREAL, Inc. All rights reserved. 76
? classpath:/META-INF/resources/
? classpath:/resources/
? classpath:/static/
? classpath:/public/
static locations と Welcome Page は
デフォルトでは上記4か所が有効
新規コースでは、classpath:/META-INF/resources/を使う
#jjug_ccc #ccc_e5
なぜ /META-INF/resources/ か?
(C) CASAREAL, Inc. All rights reserved. 77
? 最終的にAngularアプリの成果物を jar にまとめる
? /META-INF/resources/ が格納場所としてしっくりくる
? Servlet3.0 の 「10.5 ディレクトリ構造」 とも合致する
? サーバサイドをSpring以外にしても応用が利く
? ただし、Spring Bootではjarの中のstaticディレクトリに格
納しても有効
#jjug_ccc #ccc_e5
やること
(C) CASAREAL, Inc. All rights reserved. 78
? Angularアプリの成果物をjarにまとめる
? Spring Bootアプリの依存性に追加する
#jjug_ccc #ccc_e5
Angularアプリの成果物をjarにまとめる
(C) CASAREAL, Inc. All rights reserved. 79
? frontend-maven-pluginを導入
? https://github.com/eirslett/frontend-maven-
plugin
? Mavenでのビルド時に前述のトランスパイル
などを組み込むことができる
#jjug_ccc #ccc_e5
Angularアプリの成果物をjarにまとめる
(C) CASAREAL, Inc. All rights reserved. 80
Mavenのリソースフォルダ
にAngularアプリの成果物
の出力先フォルダを追加
することで、自動的にjar
の中に取り込まれる
#jjug_ccc #ccc_e5
Spring Bootアプリの依存性に追加する
(C) CASAREAL, Inc. All rights reserved. 81
? MavenのdependencyにAngularアプリを追加
? jar の中にAngularアプリが組み込まれる
<dependency>
<groupId>com.example</groupId>
<artifactId>client</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
#jjug_ccc #ccc_e5
親プロジェクトをパッケージング
(C) CASAREAL, Inc. All rights reserved. 82
Spring Boot アプリの jar :最終成果物
Angular アプリの jar
BOOT-
INF
lib
META-
INF
resource
s
Angular ? Spring Boot
の順でパッケージング
され最終的にこの形に
なる
#jjug_ccc #ccc_e5
ソースコードを公開しています
(C) CASAREAL, Inc. All rights reserved. 83
https://github.com/Masato1986/angular-spring-parent
? 紹介しきれなかった細かな設定は参照願います。
? 環境構築手順も書いています。
#jjug_ccc #ccc_e5
まとめ
(C) CASAREAL, Inc. All rights reserved. 84
? Angular と Spring Boot は相性抜群
? サービスやDIなどの構成要素が似ている
? CSRF対策もばっちり
SPA開発の最初の一歩として、
ぜひ弊社研修をご利用ください!

More Related Content

AngularとSpring Bootで作るSPA + RESTful Web Serviceアプリケーション

  • 1. #jjug_ccc #ccc_e5 AngularとSpring Bootで作る SPA + RESTful Web Service アプリケーション 株式会社カサレアル 多田 真敏?菊池 真登 2019/11/23 JJUG CCC 2019 Fall (C) CASAREAL, Inc. All rights reserved. 1
  • 2. #jjug_ccc #ccc_e5 大切なことなので (C) CASAREAL, Inc. All rights reserved. 2 100% 宣伝です 80%
  • 3. #jjug_ccc #ccc_e5 このセッションは (C) CASAREAL, Inc. All rights reserved. 3 株式会社カサレアルは Angular と Spring Boot による SPA開発の研修を提供します! このセッションは ? Spring Boot と Angular の概要 ? 組み合わせた時の開発のイメージ をお伝えし、SPA開発へ誘う45分間です。
  • 4. #jjug_ccc #ccc_e5 自己紹介:多田真敏 (C) CASAREAL, Inc. All rights reserved. 4 ? 研修トレーナー@カサレアル ? Spring / Java EE / Microservices / Cloud Foundry / Kubernetes ? Pivotal認定講師 ? 日本Springユーザ会スタッフ ? CCCは12回連続12回目の登壇
  • 5. #jjug_ccc #ccc_e5 株式会社カサレアル (C) CASAREAL, Inc. All rights reserved. 5 ?他社にはない色々なプログラミング言語の 研修を提供しています!
  • 6. #jjug_ccc #ccc_e5 目次 (C) CASAREAL, Inc. All rights reserved. 6 1.新しいコースを作ることになった背景 2.Spring Bootによるサーバサイド開発 3.Angularによるクライアント開発 4.どう組み合わせるの?
  • 7. #jjug_ccc #ccc_e5 目次 (C) CASAREAL, Inc. All rights reserved. 7 1.新しいコースを作ることになった背景 2.Spring Bootによるサーバサイド開発 3.Angularによるクライアント開発 4.どう組み合わせるの?
  • 8. #jjug_ccc #ccc_e5 新しいコースを作ることになった背景 (C) CASAREAL, Inc. All rights reserved. 8 ? 引き合いが多数! 特に Angular のコースをご受講のお客様から 「Spring Boot との組み合わせ方が知りたい」 という声が!
  • 9. #jjug_ccc #ccc_e5 それぞれ独立したコースを提供しています (C) CASAREAL, Inc. All rights reserved. 9 ? Angular入門(3日間) ? Angular 単体のコース ? 基礎からのSpring Boot(2日間) ? Spring Boot 単体のコース たくさんの方にご受講いただいております!
  • 10. #jjug_ccc #ccc_e5 両コースの受講者数も年々増加! (C) CASAREAL, Inc. All rights reserved. 10 0 20 40 60 80 100 120 140 160 2017年度 2018年度 2019年度 Spring Boot受講者数増加率 Spring Boot受講者数増加率 0 20 40 60 80 100 120 140 160 180 200 2017年度 2018年度 2019年度 Angular入門受講者数増加率 Angular入門受講者数増加率 ? 通年で提供を開始した2017年度を基準とした増加率 ? 2019年度は11月までの実績値 2019年度も増加見込み! 11月でこの増加率!
  • 12. #jjug_ccc #ccc_e5 ワークショップとして提供! (C) CASAREAL, Inc. All rights reserved. 12 ?実際にアプリを作る研修 ?クライアント、サーバの両サイドが一通り実装 できるようになることが目標の研修 ?認証やページネーションも扱う予定 ?本格的なアプリケーションの実装方法を学ぶ チャンス! ?選べる二つのコース体系!
  • 13. #jjug_ccc #ccc_e5 一ヶ月パック (C) CASAREAL, Inc. All rights reserved. 13 ? HTML/CSS、JavaScriptといったフロントエンドの基礎 ? AngularによるSPA開発 ? Javaの文法からSpring Bootによるサーバサイド開発 ? AngularとSpring BootによるSPA開発 を一気に学べる一ヶ月のコースです。 他のプログラミング経験者のスキルチェンジに最適!
  • 14. #jjug_ccc #ccc_e5 定期オープンコース(3日間) (C) CASAREAL, Inc. All rights reserved. 14 ? Angular入門(3日間) ? 基礎からのSpring Boot(2日間) を、ご受講いただいた方を対象に、 AngularとSpring BootによるSPA開発 を体験いただく3日間のオープンコースです。
  • 15. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 15 準備中…
  • 16. #jjug_ccc #ccc_e5 ご興味ありますか? (C) CASAREAL, Inc. All rights reserved. 16 ふるってご参加ください!
  • 17. #jjug_ccc #ccc_e5 目次 (C) CASAREAL, Inc. All rights reserved. 17 1.新しいコースを作ることになった背景 2.Spring Bootによるサーバサイド開発 3.Angularによるクライアント開発 4.どう組み合わせるの?
  • 18. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 18 ? Pivotal社が中心に開発 ? Spring Framework の設定地獄から脱却を目指したもの ? Starter ライブラリで Maven の dependency の記述を 減らせる ? Auto Configuration で必要な設定は済んでいる Spring Bootとは
  • 19. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 19 ?業務固有の処理を実装するのは相変わらず ?開発効率が上がるわけではない ?三つの層を地道に実装していく ただし
  • 20. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 20 ?https://start.spring.io/ ?Web 上でひな型を作成できる ?IntelliJ IDEA や STS などの主要 IDE も連携している 今回は ? Maven ? Java 11 ? Dependencies Spring Web で作成 Spring Initializrで楽々初期構築
  • 21. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 21 作成例 - 1
  • 22. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 22 作成例 - 2
  • 23. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 23 ? Spring MVC による Webアプリの開発用 Starter ? 内部に組み込み Tomcat を持つ ? Javaアプリとして起動するだけで Webアプリとして 立ち上がる ? JSON ? Java オブジェクトの変換機能をあらかじ め持っている spring-boot-starter-web
  • 24. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 24 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> pom.xmlにこれを追加するだけで、 Webアプリに必要な設定が完了する spring-boot-starter-web
  • 25. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 25 ?デフォルトでは jar ファイルが出来上がる ?必要となるライブラリが内包される ?実行するだけで Webアプリとして立ち上がる パッケージングで出来上がるもの
  • 26. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 26 DispatcherServlet JSONを送信 RestControllerRestControllerRestControllerRestController リクエストでは JSON ? Java オブジェクト に変換される レスポンスでは Java オブジェクト ? JSON に変換される JSONを返却 RESTとしてのSpring Boot
  • 27. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 27 @RestController @RequestMapping("/api/tasks") public class TaskRestController { @PostMapping public ResponseEntity order(@RequestBody TaskRequest taskRequest) { // 要件に応じた処理 return ResponseEntity.created(uri).build(); } } RESTful Web Service が構築できる Javaオブジェクトを受け取り返すだけで
  • 28. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 28 ? static locations ? src/main/resources/static 配下に静的コンテンツ を配置することでクライアントに返却できる ? Welcome Page ? src/main/resources/static 配下に置いた index.html が自動的に Welcome Page に設定され トップページアクセスすると返却される Webサーバとしての機能も充実
  • 29. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 29 http://localhost:8080 にアクセスすると返却される http://localhost:8080/js/index.js とリクエストすると返却される Webサーバとしての機能も充実
  • 30. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 30 ? Spring Security を導入する ? Spring Boot なら Starterライブラリを追加するだけ ? ログイン?ログアウトだけじゃない! ? クロスサイト?リクエストフォージェリ(CSRF)対策も デフォルトでサポート ? しかも、Angular アプリ向けのモードあり もちろん新規コースで取り扱います! Security対策も楽々!
  • 31. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 31 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> pom.xmlにこれを追加するだけで、 Spring Securityが使えるようになる spring-boot-starter-security
  • 32. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 32 @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf() .csrfTokenRepository(CookieCsrfTokenRepository .withHttpOnlyFalse()); } } Security用のJavaConfigでこの太字の 部分を追加するだけ! Angularアプリ用のCSRF対策の設定
  • 33. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 33 ? レスポンスヘッダーの Cookie に XSRF-TOKEN という 名前で CSRFトークンを発行する ? デフォルトの発行先は HttpSession ? Spring Security 4.1 からある 実は、Angularの動作に合わせたもの CookieCsrfTokenRepositoryとは
  • 34. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 34 A CsrfTokenRepository that persists the CSRF token in a cookie named "XSRF-TOKEN" and reads from the header "X-XSRF-TOKEN" following the conventions of AngularJS. AngularJSの規則に従ってヘッダー「X-XSRF-TOKEN」か らCSRFトークンから読み取る Spring Securityのドキュメントにも
  • 35. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 35 正規のWebサイト ①購入ページをリクエスト ②CSRFトークンを発行し、 レスポンスヘッダーのCookieに含める ③CookieからCSRFトークンを取得し、 リクエストボディ(またはヘッダー)に含めて 購入リクエストを送信 ④CookieのCSRFトークンと リクエストボディのCSRFトークンを比較し、 同じであれば購入OKとする Cookieを利用したCSRF対策の動作概要
  • 36. #jjug_ccc #ccc_e5 目次 (C) CASAREAL, Inc. All rights reserved. 36 1.新しいコースを作ることになった背景 2.Spring Bootによるサーバサイド開発 3.Angularによるクライアント開発 4.どう組み合わせるの?
  • 37. #jjug_ccc #ccc_e5 自己紹介:菊池真登 (C) CASAREAL, Inc. All rights reserved. 37 ? 研修トレーナー@カサレアル ? 登壇実績:Spring / Java SE ? 開発歴[Spring]:2012年から ? 開発歴[Angular]:2015年頃に 1.5年間AngularJSに触れて冬眠 ? 今回新規コースのコンテンツ 作成を任命される
  • 38. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 38 ? Google製のフレームワーク ? JavaScript上で動作するWebアプリケーション用 ? フルスタック ? TypeScript推奨 Angularとは
  • 40. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 40 ? 画面は基本的に index.html だけで遷移は ない ? ボタンクリックなどで表示の切り替えができるが、 Angular が頑張ってそれっぽく見せている ? 必要なデータは XMLHttpRequest(XHR) でサーバ から非同期で取得 ? 構成要素が Spring MVCに近い 少し砕けた紹介を
  • 41. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 41 http://localhost:4200 http://localhost:4200/product/list 左側のリンクをクリックすると、この部分の表示するための 「部品?Component」をAngularが切り替える 実際の作業イメージとしては、この「部品?Component」単位で 作成していく Angularの頑張り
  • 42. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 42 Template <html> Component Injector Service データ 入力値 XHR Angularを構成するもの
  • 43. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 43 サーバサイド三層アーキテクチャー
  • 44. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 44 サーバサイドJavaエンジニアであれば、実はとっつきやすいかも! (注意:個人的な主観) Template <html> Component Injector Service データ 入力値 XHR 構成要素がSpring MVCに近い
  • 45. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 45 ? だからこそのTypeScript! ? クラスベースのオブジェクト指向 ? 静的な型の指定 JavaScriptって、型なしじゃ?
  • 46. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 46 @Injectable({ providedIn: 'root' }) export class TaskDataService { constructor(private http: HttpClient) {} findAll(): Observable<Task[]> { return this.http.get<Task[]>('/api/tasks'); } } DI で HttpClient を代入 HTTP GET リクエスト でデータを取得 実際のソースコード - Service
  • 47. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 47 @Component({ selector: 'app-task-table', templateUrl: './task-table.component.html', styleUrls: ['./task-table.component.css'] }) export class TaskTableComponent implements OnInit { taskList: Task[]; constructor(private taskDataService: TaskDataService) {} ngOnInit() { this.taskDataService.findAll().subscribe(tasks => { this.taskList = tasks; }); } データを取得して フィールドに代入 実際のソースコード - Component
  • 48. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 48 <table> <tr *ngFor="let todoTask of taskList" (click)="clickRow(todoTask)" [ngClass]="onColor(todoTask)"> <td>{{todoTask.id}}</td> <td>{{todoTask.todo}}</td> <td>{{todoTask.priority}}</td> </tr> </table> Component と Template間は 双方向データバインディングで やり取り可能 実際のソースコード - Template
  • 49. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 49 export class Task { id: number; todo: string; priority: string; constructor(id: number, todo: string, priority: string) { this.id = id; this.todo = todo; this.priority = priority; } } オリジナルのクラスを定義 クラスの宣言
  • 50. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 50 export class TaskDataService { constructor(private http: HttpClient) {} findAll(): Observable<Task[]> { return this.http.get<Task[]>('/api/tasks'); } } ジェネリクスの 型パラメータとして利用 Service のソースコード
  • 51. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 51 IDEの手厚い補完機能が受けられるので、 Java開発者にとってはありがたい トランスパイル! (変換!) Webブラウザで動かすには
  • 52. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 52 ? HttpClient が高度に抽象化! ? Angular に標準で備わっている ? GET、POST など直感的でわかりやすい ? ジェネリクスによって戻り値の型をある程度は 精査できる XHRって、しんどくない?
  • 53. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 53 export class TaskDataService { constructor(private http: HttpClient) {} findAll(): Observable<Task[]> { return this.http.get<Task[]>('/api/tasks'); } } HttpClientの呼び出し 方のサンプル jQueryのコードと比較 するとだいぶ簡略化 Serviceのソースコード
  • 54. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 54 正規のWebサイト ①購入ページをリクエスト ②CSRFトークンを発行し、 レスポンスヘッダーのCookieに含める ③CookieからCSRFトークンを取得し、 リクエストボディ(またはヘッダー)に含めて 購入リクエストを送信 ④CookieのCSRFトークンと リクエストボディのCSRFトークンを比較し、 同じであれば購入OKとする この部分が自動 化されます! HttpClientはCSRF対策もばっちり
  • 55. #jjug_ccc #ccc_e5 (C) CASAREAL, Inc. All rights reserved. 55 ? X-XSRF-TOKENヘッダーにトークンを含めて送信 HttpClient はこれをリクエスト時に自動的に 行う フレームワークに乗っかるだけで お手軽にセキュアなアプリが作れる! HttpClientはCSRF対策もばっちり
  • 56. #jjug_ccc #ccc_e5 目次 (C) CASAREAL, Inc. All rights reserved. 56 1.新しいコースを作ることになった背景 2.Spring Bootによるサーバサイド開発 3.Angularによるクライアント開発 4.どう組み合わせるの?
  • 57. #jjug_ccc #ccc_e5 プロジェクトの構成 (C) CASAREAL, Inc. All rights reserved. 57 ? クライアントサイド?サーバサイドは別プロジェクト にする ? 分業がしやすい ? マイクロサービスへの足掛かりにしやすい ? (無いとは思うが)クライアントもしくは サーバサイドの載せ替えがしやすい
  • 58. #jjug_ccc #ccc_e5 全体のイメージ (C) CASAREAL, Inc. All rights reserved. 58 親プロジェクト Angular プロジェクト Spring Boot プロジェクト MavenやGradleの マルチプロジェクト機能で サブプロジェクトとして作成
  • 59. #jjug_ccc #ccc_e5 どう組み合わせるの? - 開発時 (C) CASAREAL, Inc. All rights reserved. 59 ? Spring Bootは通常起動でポート8080で動作 ? Angularは検証用サーバでポート4200で動作 ? 任意のURLにリクエストを転送する機能をもつ ? サーバのAPIとの通信はポート8080に転送する
  • 60. #jjug_ccc #ccc_e5 Angular CLIのng serve (C) CASAREAL, Inc. All rights reserved. 60 ?Angular CLI ?開発をサポートするコマンドライン ?ng serve ?Angular CLI に含まれる検証サーバ機能 ?ファイルの編集を検知し即時反映される ?サーバ再起動が必要ないため開発効率が向上
  • 61. #jjug_ccc #ccc_e5 転送のイメージ (C) CASAREAL, Inc. All rights reserved. 61 index.htmlなどは 直接返却 Webブラウザ ng serve ポート4200 Spring Boot ポート8080 /api/tasks /api/tasks JSONJSON 検証用サーバが ポート8080に転送 する
  • 62. #jjug_ccc #ccc_e5 転送の設定 (C) CASAREAL, Inc. All rights reserved. 62 { "/api": { "target": "http://localhost:8080", "secure": false } } http://localhost:4200/api/** に合致するリクエストは、 http://localhost:8080/api/** に転送する設定 proxy.conf.json "serve": { "options": { "browserTarget": "client:build", "proxyConfig": "src/proxy.conf.json" }, angular.json ng serveのオプションに転送 の設定を読み込ませる
  • 63. #jjug_ccc #ccc_e5 開発時、特に気にするものはない (C) CASAREAL, Inc. All rights reserved. 63 export class TaskDataService { findAll(): Observable<Task[]> { return this.http.get<Task[]>('/api/tasks'); } } @RestController @RequestMapping("/api/tasks") public class TaskRestController { @GetMapping public List<TaskResponse> findAll() { return this.todoService.findAll().stream() .map( todo -> new TaskResponse(todo)) .collect(Collectors.toList()); } } HttpClientのメソッドには 「/api/tasks」とだけ記述。 ポート番号の違いの考慮は不要
  • 64. #jjug_ccc #ccc_e5 どう組み合わせるの? - パッケージング (C) CASAREAL, Inc. All rights reserved. 64 ? 今回は1つの成果物で動くようする Webブラウザ サーバ APIだけでなく 静的コンテンツも 返却
  • 65. #jjug_ccc #ccc_e5 基本方針 (C) CASAREAL, Inc. All rights reserved. 65 ? トップページアクセスで index.html を返却 ? 関連する JavaScript もダウンロード可能 ? Spring Boot の static locations ? Spring Boot の Welcome Page の機能を使う
  • 66. #jjug_ccc #ccc_e5 なぜSpring BootのWebサーバ機能? (C) CASAREAL, Inc. All rights reserved. 66 ? Cross-Origin Resource Sharing の考慮が不要 ? 最終成果物を1つにできるのでディプロイが楽 ? 静的コンテンツのダウンロードは初回アクセスの 時だけなので Webサーバとしての負荷は高くない
  • 68. #jjug_ccc #ccc_e5 ホスティングサービスへのディプロイ (C) CASAREAL, Inc. All rights reserved. 68 ? Firebase hosting ? Azure ? Now ? Netlify ? GitHub pages 等の主要ホスティングサービスにはAngular CLI で 自動ディプロイが可能 https://angular.jp/guide/deployment#automatic- deployment-with-the-cli
  • 69. #jjug_ccc #ccc_e5 任意のWebサーバへのディプロイ (C) CASAREAL, Inc. All rights reserved. 69 ? Angular CLIのビルド機能を使ってビルドする ? ng build --prod というコマンドを使う ? 成果物のすべてをWebサーバにコピーする という手順になる 詳しい手順はこちら https://angular.jp/guide/deployment#basic- deployment-to-a-remote-server *サーバサイドのディプロイ先は別途ご用意ください
  • 70. #jjug_ccc #ccc_e5 Same Origin Policy (C) CASAREAL, Inc. All rights reserved. 70 異なるドメインへの通信は 許可されない
  • 71. #jjug_ccc #ccc_e5 Spring MVC で CORS 対応 (C) CASAREAL, Inc. All rights reserved. 71 @RestController @RequestMapping("/api/tasks") public class TaskRestController { @GetMapping @CrossOrigin public List<TaskResponse> findAll() { return this.todoService.findAll().stream() .map(todo -> new TaskResponse(todo)) .collect(Collectors.toList()); } } @CrossOriginを付けるだけ
  • 72. #jjug_ccc #ccc_e5 サーバホスト名解決 (C) CASAREAL, Inc. All rights reserved. 72 Angular Spring Boot http://localhost:4200 http://localhost:8080 Angular Spring Boot https://angular.com https://spring.com 開発環境 本番環境 ?開発環境の Angular アプリは http://localhost:8080 ?本番環境のAngular アプリは https://boot.example.com に非同期通信を行うように切り替える
  • 73. #jjug_ccc #ccc_e5 環境設定ファイル (C) CASAREAL, Inc. All rights reserved. 73 ? Angular は環境ごとの設定値を定義できる ? 開発用のAPIのURL ? 本番用のAPIのURL 等を設定する ? ビルドのコマンドのオプションで環境を指定する
  • 74. #jjug_ccc #ccc_e5 別々にホスティングするケースの紹介でした (C) CASAREAL, Inc. All rights reserved. 74 こちら、別途qiita記事を用意しています! Spring MVC で CORS https://qiita.com/m_kikuchi/items/df8c070b228d f44a5462
  • 75. #jjug_ccc #ccc_e5 最終的に以下の形を目指す (C) CASAREAL, Inc. All rights reserved. 75 Spring Boot アプリの jar :最終成果物 Angular アプリの jar BOOT-INF lib META-INF resources
  • 76. #jjug_ccc #ccc_e5 static locations と Welcome Page (C) CASAREAL, Inc. All rights reserved. 76 ? classpath:/META-INF/resources/ ? classpath:/resources/ ? classpath:/static/ ? classpath:/public/ static locations と Welcome Page は デフォルトでは上記4か所が有効 新規コースでは、classpath:/META-INF/resources/を使う
  • 77. #jjug_ccc #ccc_e5 なぜ /META-INF/resources/ か? (C) CASAREAL, Inc. All rights reserved. 77 ? 最終的にAngularアプリの成果物を jar にまとめる ? /META-INF/resources/ が格納場所としてしっくりくる ? Servlet3.0 の 「10.5 ディレクトリ構造」 とも合致する ? サーバサイドをSpring以外にしても応用が利く ? ただし、Spring Bootではjarの中のstaticディレクトリに格 納しても有効
  • 78. #jjug_ccc #ccc_e5 やること (C) CASAREAL, Inc. All rights reserved. 78 ? Angularアプリの成果物をjarにまとめる ? Spring Bootアプリの依存性に追加する
  • 79. #jjug_ccc #ccc_e5 Angularアプリの成果物をjarにまとめる (C) CASAREAL, Inc. All rights reserved. 79 ? frontend-maven-pluginを導入 ? https://github.com/eirslett/frontend-maven- plugin ? Mavenでのビルド時に前述のトランスパイル などを組み込むことができる
  • 80. #jjug_ccc #ccc_e5 Angularアプリの成果物をjarにまとめる (C) CASAREAL, Inc. All rights reserved. 80 Mavenのリソースフォルダ にAngularアプリの成果物 の出力先フォルダを追加 することで、自動的にjar の中に取り込まれる
  • 81. #jjug_ccc #ccc_e5 Spring Bootアプリの依存性に追加する (C) CASAREAL, Inc. All rights reserved. 81 ? MavenのdependencyにAngularアプリを追加 ? jar の中にAngularアプリが組み込まれる <dependency> <groupId>com.example</groupId> <artifactId>client</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
  • 82. #jjug_ccc #ccc_e5 親プロジェクトをパッケージング (C) CASAREAL, Inc. All rights reserved. 82 Spring Boot アプリの jar :最終成果物 Angular アプリの jar BOOT- INF lib META- INF resource s Angular ? Spring Boot の順でパッケージング され最終的にこの形に なる
  • 83. #jjug_ccc #ccc_e5 ソースコードを公開しています (C) CASAREAL, Inc. All rights reserved. 83 https://github.com/Masato1986/angular-spring-parent ? 紹介しきれなかった細かな設定は参照願います。 ? 環境構築手順も書いています。
  • 84. #jjug_ccc #ccc_e5 まとめ (C) CASAREAL, Inc. All rights reserved. 84 ? Angular と Spring Boot は相性抜群 ? サービスやDIなどの構成要素が似ている ? CSRF対策もばっちり SPA開発の最初の一歩として、 ぜひ弊社研修をご利用ください!