Spring Bootをはじめる時にやるべき10のこと

心 谷本
心 谷本アクロクエストテクノロジー株式会社 - テクニカルコンサルタント at アクロクエストテクノロジー株式会社
Spring Bootをはじめる時に

やるべき10のこと

#bootきのこ
Shin Tanimoto

Acroquest Technology Co., LTD
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
皆さん

用意はいいですか?
2
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
鈴木会長は

こっちじゃないぞ?
3
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
では、始めましょう!
4
Copyright © Acroquest Technology Co., Ltd. All rights reserved.
自己紹介
5
• 谷本 心 (Shin Tanimoto)
- Acroquest Technology株式会社
- 開発&トラブルシュート教育
- JavaOneスピーカー
- JJUG / 関ジャバ / S2JSFコミッタ
- Twitter : @cero_t (日本語)
- Facebook : shin.tanimoto (英語)
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
6
Struts + Hibernate
Seasar2 + S2JSF + S2Dao
Click + Guice + Mirage
Spring MVC + Hibernate
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
フレームワークに

求めていること
7
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
開発効率

生産性
8
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
ではなくて
9
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
ハマらない

ミスしない

ミスをリカバリできる
10
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
ひとつハマれば

3人日が奪われ
11
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
ひとつミスしていれば

商用障害が起き
12
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
リカバリできずに

今日も徹夜
13
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
ハマらない

ミスしない

ミスをリカバリできる
14
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
そのための

Spring Boot
15
Spring Bootをはじめる時に

やるべき10のこと

#bootきのこ
Shin Tanimoto

Acroquest Technology Co., LTD
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
17
#1

SpringBootを知る
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
1. Spring Bootを知る
Spring Bootとは
複雑化したSpringプロジェクト群を使った開発を
シンプルに開始できる仕組み
18
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
19
Springベースの

フルスタック

プラットフォーム
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
1. Spring Bootを知る
フルスタックプラットフォーム
View層、コンテナ層、データアクセス層

監視、非同期メッセージング、クラウド対応など

様々な機能を「Spring Boot」という共通の

プラットフォーム上で利用できる。
20
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
1. Spring Bootを知る
フルスタックプラットフォームでないと
自分で様々なフレームワークを組み合わせると

もちろん自由に選べる反面、

設定の記述や、動作検証などが必要になる。
ここに「ハマり」要因がある。
21
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
1. Spring Bootを知る
あまり強調しない方が良いこと
Microservices向けフレームワーク
別にそれが目的ではない
Executable JAR ≠ Microservices
XMLを書かない
ymlや設定クラスを少し作る
22
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
23
#1
Spring Bootなら

組み合わせでハマらない!
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
24
#2

はじめての

Spring Boot
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
2. はじめてのSpring Boot
新しいプロダクトの利用時あるある
ドキュメントがない。
ドキュメントが英語しかない。
ブログがない。ノウハウがない。
とりあえず少しずつググりながら

場当たり対応で何とか凌ぐ。
そんなことをしているから「設計ミス」をする。
25
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
2. はじめてのSpring Boot
はじめてのSpring Boot
26
@makingの力作
Spring Bootを用いた

開発、試験、デプロイなどを

まるっと習得できる
こっちの入門スライドもオススメ

http://www.slideshare.net/
makingx/grails-30-spring-boot
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
27
#2
はじめてのSpring Bootで

初期学習を効率化!
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
28
#3

Spring Initializr
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
3. Spring Initializr
プロジェクト立ち上げ時あるある
pom.xmlを書いて、必要な依存ライブラリを列挙する。
・・・のは面倒だから、exampleプロジェクトを探して

不要なソースコードを削除する。
なんか不要なJARが混入している
なぜかバージョン違いのJARが混入する
頑張ってビルドファイルを書いたけど、なぜか動かない。
ここに「ミス」と「ハマり」要因がある。
29
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
3. Spring Initializr
Spring Initializrとは
https://start.spring.io/
Spring Bootプロジェクトの雛形を作る
Maven or Gradleのプロジェクト作成
利用するプロジェクトやライブラリを選択できる
Web、JDBC、Security、AOP、

JPA、Thymeleafなど
つまずかずにスタートできる!
30
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
3. Spring Initializr
使い方
https://start.spring.io/ に行く。
必要な情報と、利用するモジュールを選ぶ。
Actuatorおすすめ
Generate Projectをクリック。
ダウンロードしたzipを解凍する。
IDEにインポートする。
以下のいずれかで実行する。
mainメソッドを実行する
mvn spring-boot:run
31
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
32
#3
Spring Initializrなら

初期構築でミスしない!
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
33
#4

pom.xmlの設計
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
4. pom.xmlの設計
pom.xmlあるある
複数モジュールを作る時、依存JARのバージョンを

複数のpom.xmlに重複して書いている。
そしてJARのバージョン違いが発生する
親子モジュールとか難しいから、

単一モジュールで行くぜー!
WebAPIとバッチがなぜか同じJARに入ってる
34
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
4. pom.xmlの設計
pom.xmlのグッドプラクティス
デプロイ単位、ライフサイクル単位で分割する
共通部分を切り出す
フレームワーク部分
自動生成したエンティティ
しかしそうすると、前述したJARの

バージョン違い問題が起きる・・・?
35
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
4. pom.xmlの設計
pom.xmlのグッドプラクティス
依存JARのバージョンは、親のpom.xmlに書く
<dependencyManagement> を使ってバージョンを定義する
Spring IO platformを使う
http://platform.spring.io/platform/
大げさな名前だが、ただのpom.xml
Spring関連モジュールだけでなく、

著名なプロダクトも含むバージョンを規定したpom.xml
commons-lang、guice、joda-time、jruby、、、
Version1.1.4では552個のモジュールのバージョンが規定されている
36
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
37
#4
Spring IO platformで

pom.xmlをシンプルに!
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
38
#5

Controllerの共通設定
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
5. Controllerの共通設定
突然ですが、

JSR 310 Date and Time APIの

LocalDateクラスってご存じですか?
LocalDate : 日付のみ。時間なし。
LocalTime : 時間のみ。日付なし。
LocalDateTime : 日付も時間もあり。
39
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
5. Controllerの共通設定
java.util.DateやCalendarはハマりやすい
Dateを使って比較する際、日付だけで良いのに

余計な時分秒が入っているせいで、判定を誤る。
Calendarで時分秒に0を指定したけど

ミリ秒に余計な値が入っていて、判定を誤る。
SimpleDateFormatがスレッドセーフでないことを

知らずに、商用環境で問題が起きる。
40
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
5. Controllerの共通設定
JSR 310をSpring Bootでも使いたい
できること
yyyy-MM-dd形式の日付
JSONリクエスト → LocalDateフィールド
できないこと
yyyy/MM/dd形式の日付
LocalDateフィールド → JSONレスポンス
41
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
5. Controllerの共通設定
ControllerでLocalDateを使う
Controllerで利用するJacksonをカスタマイズする
Controllerの引数・戻り値のオブジェクトと

JSONリクエスト・レスポンスは、

Jacksonでシリアライズ・デシリアライズされる。
Jackson2ObjectMapperBuilderを

戻すメソッドに@Beanをつけることで

カスタマイズできる。
42
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
5. Controllerの共通設定
@Bean
public Jackson2ObjectMapperBuilder jacksonBuilder() {
return Jackson2ObjectMapperBuilder.json()
.indentOutput(true)
.serializerByType(LocalDate.class, new JsonSerializer<LocalDate>() {
@Override
public void serialize(LocalDate value, JsonGenerator jgen,
SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeString(value.format(DATE_FORMATTER));
}
})
.deserializerByType(LocalDate.class, new JsonDeserializer<LocalDate>() {
@Override
public LocalDate deserialize(JsonParser jp,
DeserializationContext ctxt) throws IOException, JsonProcessingException {
return LocalDate.parse(jp.getValueAsString(), DATE_PARSER);
}
})
.modules(new JSR310Module());
}
43
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
5. Controllerの共通設定
@Bean
public Jackson2ObjectMapperBuilder jacksonBuilder() {
return Jackson2ObjectMapperBuilder.json()
.indentOutput(true)
.serializerByType(LocalDate.class, new JsonSerializer<LocalDate>() {
@Override
public void serialize(LocalDate value, JsonGenerator jgen,
SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeString(value.format(DATE_FORMATTER));
}
})
.deserializerByType(LocalDate.class, new JsonDeserializer<LocalDate>() {
@Override
public LocalDate deserialize(JsonParser jp,
DeserializationContext ctxt) throws IOException, JsonProcessingException {
return LocalDate.parse(jp.getValueAsString(), DATE_PARSER);
}
})
.modules(new JSR310Module());
}
44
出力するJSONを
読みやすく
LocalDateの

シリアライズと

デシリアライズ
他のJSR 310クラスも

使えるようにしておく
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
5. Controllerの共通設定
/** 日付フォーマット */
protected static final DateTimeFormatter DATE_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd");
/** 日付パースフォーマット */
protected static final DateTimeFormatter DATE_PARSER =
DateTimeFormatter.ofPattern(“y[-][/]M[-][/]d");
45
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
5. Controllerの共通設定
/** 日付フォーマット */
protected static final DateTimeFormatter DATE_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd");
/** 日付パースフォーマット */
protected static final DateTimeFormatter DATE_PARSER =
DateTimeFormatter.ofPattern(“y[-][/]M[-][/]d");
入力は柔軟に、出力は厳格に。
46
フォーマット時は

0埋め、

ハイフン区切り
パース時は

0埋め、区切りを

少し自由に
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
47
#5
ControllerでLocalDateを

使って日付判定ミスを防ぐ!
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
48
#6

トランザクション

境界の設定
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
6. トランザクション境界の設定
トランザクションあるある
Controllerをトランザクション境界にする
処理の途中で一度コミットしたいけどできない
非同期処理呼び出しの前にコミットとか
途中でコミットできるような仕組みを

無理に作ったら全体的な整合性が崩れた
性能改善のためのリードレプリカを作りたいが、

そもそもアクセスを振り分けられない
49
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
6. トランザクション境界の設定
Service層をトランザクション境界にする
Controllerの次の層をトランザクション境界にする
処理の単位が明確になる
Service層からreturnすればコミット、

例外で戻ればロールバック。
Service層のクラスすべてに

@Transactionalアノテーションをつける
50
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
6. トランザクション境界の設定
原則、Read Onlyトランザクションを使う
Service層のクラスすべてに

@Transactional(readOnly = true) をつける
Insert / Update / Deleteが発生する時だけ

メソッドに @Transactional(readOnly = false) を

つける
ReadOnlyトランザクションだけを

リードレプリカに振り分ける
51
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
6. トランザクション境界の設定
@Service
@Transactional(readOnly = true)
public class EmployeeService {
@Autowired
protected EmployeeDao employeeDao;
public Employee getEmployee(Integer id) {
return employeeDao.selectById(id);
}
@Transactional(readOnly = false)
public int createEmployee(Employee employee) {
return employeeDao.insert(employee);
}
}
52
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
6. トランザクション境界の設定
@Service
@Transactional(readOnly = true)
public class EmployeeService {
@Autowired
protected EmployeeDao employeeDao;
public Employee getEmployee(Integer id) {
return employeeDao.selectById(id);
}
@Transactional(readOnly = false)
public int createEmployee(Employee employee) {
return employeeDao.insert(employee);
}
}
53
クラスには

readOnly = true
更新系メソッドに

readOnly = false
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
54
#6
ServiceクラスにRead Onlyな

トランザクションを設けて

将来に備える!
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
55
#7

O/Rマッパーの選択
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
7. O/Rマッパーの選択
O/Rマッパーあるある
とりあえずHibernate
思ったのと違うSQLが発行された
1リクエストでSQLが1万回発行された
selectしたタイミングで一意制約違反が出た
キャッシュが想定外の動きをした。
要するにハマる
56
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
7. O/Rマッパーの選択
O/Rマッパーあるある
じゃぁMyBatis
Spring Bootで標準対応していない
1.3で標準対応されるかも
https://github.com/spring-projects/spring-boot/pull/3692
SQLを書いたXMLをフォーマットしたら

インデントが全部消えた
> とか < のエスケープ
57
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
7. O/Rマッパーの選択
O/Rマッパーあるある
じゃぁJdbcTemplate
なんかAPIが古くさい(Spring 2.0時代のAPI)
publicフィールドが使えない
JSR 310に対応していない
58
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
59
そこで

Bootiful SQL Template
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
7. O/Rマッパーの選択
Bootiful SQL Template
JdbcTemplate / NamedParameterJdbcTemplateの

独自ラッパー
SQLファイルを書ける(FreeMarker形式も可)
モダンなAPI
publicフィールドが使える
JSR 310に対応(ZonedDateTimeにも)
https://github.com/cero-t/sqltemplate
60
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
7. O/Rマッパーの選択
@Autowired
protected SqlTemplate sqlTemplate;
public List<Employee> selectByCondition(EmployeeCondition condition) {
return sqlTemplate.forList("sql/EmployeeDao/selectByCondition.sql",
Employee.class, condition);
}
61
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
7. O/Rマッパーの選択
@Autowired
protected SqlTemplate sqlTemplate;
public List<Employee> selectByCondition(EmployeeCondition condition) {
return sqlTemplate.forList("sql/EmployeeDao/selectByCondition.sql",
Employee.class, condition);
}
62
モダンでサクっと

使えるAPI
IntelliJなら

Command(Ctrl) + クリックで

SQLファイルにジャンプ
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
7. O/Rマッパーの選択
SELECT
*
FROM
emp
WHERE
1 = 1
<#if name??>
AND ename like '%' || :name || '%'
</#if>
<#if hiredateFrom??>
AND :hiredateFrom < hiredate
</#if>
<#if hiredateTo??>
AND hiredate < :hiredateTo
</#if>
<#if deptno??>
AND deptno = :deptno
</#if>
63
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
7. O/Rマッパーの選択
SELECT
*
FROM
emp
WHERE
1 = 1
<#if name??>
AND ename like '%' || :name || '%'
</#if>
<#if hiredateFrom??>
AND :hiredateFrom < hiredate
</#if>
<#if hiredateTo??>
AND hiredate < :hiredateTo
</#if>
<#if deptno??>
AND deptno = :deptno
</#if>
64
FreeMarker形式の

テンプレートが利用可能



ANDを自動的に消す機能が

なくてごめんな
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
65
#7
Bootiful SQL Templateで

SQLを書いてハマり知らず
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
66
#8

例外処理の共通化
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
例外処理あるある
個別の開発者任せ
もちろん死ぬ
フレームワークが返す例外(バリデーションなど)と、

アプリケーションが返す例外でJSONの形式が違う
クライアント側で判別に失敗して死ぬ
個別のエラーコードを定義しておいたので

全部ソースコード内に書く
守らない人がいて死ぬ
67
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
例外処理は共通化する
ApplicationException extends RuntimeExceptionを
作って必ずこれを使う
エラー種別をenumに定義しておき、

ApplicationExceptionのコンストラクタの

第一引数に必ず渡す
エラー種別と、HTTPステータスやエラーコード、

エラーメッセージを紐付けて管理する
68
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
public class ApplicationException extends RuntimeException {
Throwable cause;
Object[] args;
private HttpErrors error;
public AppException(HttpErrors error, Throwable cause, String... args) {
super();
this.error = error;
this.args = args;
this.cause = cause;
}
// その他のコンストラクタ、cause、args、errorのgetterは割愛
public String getMessage() {
if (args != null) {
return "[" + error.name() + "]" + MessageFormat.format(error.getMessage(), args);
}
return "[" + error.name() + "]" + error.getMessage();
}
}
69
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
public class ApplicationException extends RuntimeException {
Throwable cause;
Object[] args;
private HttpErrors error;
public AppException(HttpErrors error, Throwable cause, String... args) {
super();
this.error = error;
this.args = args;
this.cause = cause;
}
// その他のコンストラクタ、cause、args、errorのgetterは割愛
public String getMessage() {
if (args != null) {
return "[" + error.name() + "]" + MessageFormat.format(error.getMessage(), args);
}
return "[" + error.name() + "]" + error.getMessage();
}
}
70
第一引数で

エラー種別を受け取る
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
public interface HttpErrors {
/**
* HTTPステータスを取得します。
* @return HTTPステータス
*/
HttpStatus getStatus();
/**
* メッセージを取得します。
* @return メッセージ
*/
String getMessage();
/**
* エラー名を取得します。
* @return エラー名
*/
String name();
}
71
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
public enum Errors implements HttpErrors {
USER_NOT_FOUND(HttpStatus.NOT_FOUND, "入力したIDに対応するユーザーが存在しません。userId={0}"),
UNEXPECTED(HttpStatus.INTERNAL_SERVER_ERROR, "想定外のエラーが発生しました。 : {0}");
protected HttpStatus status;
protected String message;
Errors(HttpStatus status, String message) {
this.status = status;
this.message = message;
}
@Override
public HttpStatus getStatus() {
return status;
}
@Override
public String getMessage() {
return message;
}
}
72
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
public enum Errors implements HttpErrors {
USER_NOT_FOUND(HttpStatus.NOT_FOUND, "入力したIDに対応するユーザーが存在しません。userId={0}"),
UNEXPECTED(HttpStatus.INTERNAL_SERVER_ERROR, "想定外のエラーが発生しました。 : {0}");
protected HttpStatus status;
protected String message;
Errors(HttpStatus status, String message) {
this.status = status;
this.message = message;
}
@Override
public HttpStatus getStatus() {
return status;
}
@Override
public String getMessage() {
return message;
}
}
73
エラーを列挙
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
例外処理ハンドリングも共通化する
ApplicationExceptionと

RuntimeExceptionと

フレームワークが返す例外で

すべて同じ例外ハンドリングをする
74
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
@ControllerAdvice
public class ControllerExceptionHandler extends ResponseEntityExceptionHandler {
/** ロガー */
protected final Log logger = LogFactory.getLog(getClass());
@ExceptionHandler(value = ApplicationException.class)
@ResponseBody
public ResponseEntity<RestError> handleAppException(HttpServletRequest request, ApplicationException ex) {
return handleError(request, ex.getError(), ex, ex.getArgs());
}
@ExceptionHandler(value = RuntimeException.class)
@ResponseBody
public ResponseEntity<RestError> handleException(HttpServletRequest request, RuntimeException ex) {
return handleError(request, Errors.UNEXPECTED, ex, ex.toString());
}
75
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
@ControllerAdvice
public class ControllerExceptionHandler extends ResponseEntityExceptionHandler {
/** ロガー */
protected final Log logger = LogFactory.getLog(getClass());
@ExceptionHandler(value = ApplicationException.class)
@ResponseBody
public ResponseEntity<RestError> handleAppException(HttpServletRequest request, ApplicationException ex) {
return handleError(request, ex.getError(), ex, ex.getArgs());
}
@ExceptionHandler(value = RuntimeException.class)
@ResponseBody
public ResponseEntity<RestError> handleException(HttpServletRequest request, RuntimeException ex) {
return handleError(request, Errors.UNEXPECTED, ex, ex.toString());
}
76
独自のApplicationExceptionと

想定しないRuntimeExceptionの両方を

同じ方式でハンドリング
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
protected ResponseEntity<RestError> handleError(HttpServletRequest request, HttpErrors error, Exception ex,
Object... args) {
String message = MessageFormat.format(error.getMessage(), args);
if (error.getStatus() == HttpStatus.INTERNAL_SERVER_ERROR) {
logger.error(message, ex);
} else {
logger.debug(message, ex);
}
if (error.getStatus() == HttpStatus.UNAUTHORIZED) {
return new ResponseEntity<>(error.getStatus());
}
RestError restError = new RestError();
restError.path = request.getRequestURI();
restError.error = error.name();
restError.status = error.getStatus()
.value();
restError.message = message;
restError.exception = ex.getClass()
.getName();
return new ResponseEntity<>(restError, error.getStatus());
}
77
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
protected ResponseEntity<RestError> handleError(HttpServletRequest request, HttpErrors error, Exception ex,
Object... args) {
String message = MessageFormat.format(error.getMessage(), args);
if (error.getStatus() == HttpStatus.INTERNAL_SERVER_ERROR) {
logger.error(message, ex);
} else {
logger.debug(message, ex);
}
if (error.getStatus() == HttpStatus.UNAUTHORIZED) {
return new ResponseEntity<>(error.getStatus());
}
RestError restError = new RestError();
restError.path = request.getRequestURI();
restError.error = error.name();
restError.status = error.getStatus()
.value();
restError.message = message;
restError.exception = ex.getClass()
.getName();
return new ResponseEntity<>(restError, error.getStatus());
}
78
例外オブジェクトへの変換
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
@Override
protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers,
HttpStatus status, WebRequest request) {
RestError restError = new RestError();
if (request instanceof ServletWebRequest) {
restError.path = ((ServletWebRequest) request).getRequest()
.getRequestURI();
} else {
restError.path = request.getContextPath();
}
restError.error = status.getReasonPhrase();
restError.status = status.value();
restError.message = ex.getMessage();
restError.exception = ex.getClass()
.getName();
return new ResponseEntity<>(restError, status);
}
}
79
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8. 例外処理の共通化
@Override
protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers,
HttpStatus status, WebRequest request) {
RestError restError = new RestError();
if (request instanceof ServletWebRequest) {
restError.path = ((ServletWebRequest) request).getRequest()
.getRequestURI();
} else {
restError.path = request.getContextPath();
}
restError.error = status.getReasonPhrase();
restError.status = status.value();
restError.message = ex.getMessage();
restError.exception = ex.getClass()
.getName();
return new ResponseEntity<>(restError, status);
}
}
80
このオーバーライドで

Spring MVCが投げる例外を

ハンドリングできる
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
81
#8
すべての例外を共通して

ハンドリングせよ!
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
82
#9

AOPによるロギング
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
9. AOPによるロギング
AOPとは
アプリケーション横断的に行う処理
トランザクションのコミットやロールバックもAOPで実現されている
オススメは、AOPによる自動ロギング
Controller / Service / DaoのIn/Outでロギング
デバッグ時に、アプリケーションの挙動がとてもよく分かる
ログレベルに応じて引数、戻り値なども出す
SpringではXMLやアノテーションでAOPの対象を記述することができる
正直、アノテーションの記述はイマイチ。分かりづらい。
記述性はGuice > Seasar > Spring。
83
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
9. AOPによるロギング
@Aspect
@Component
public class DumpLogInterceptor {
protected Logger logger = LoggerFactory.getLogger(getClass());
@Around("execution(* ninja.cero.springboot..*.*(..)) && (bean(*Controller) || bean(*Service) || bean(*Dao))")
public Object dump(ProceedingJoinPoint joinPoint) throws Throwable {
try {
logger.debug("BEGIN - " + toCall(joinPoint));
logger.trace("with args - " + ToStringBuilder.reflectionToString(joinPoint.getArgs(),
ToStringStyle.SHORT_PREFIX_STYLE));
Object retValue = joinPoint.proceed(joinPoint.getArgs());
logger.debug("END - " + toCall(joinPoint));
logger.trace(
"with return - " + ToStringBuilder.reflectionToString(retValue, ToStringStyle.SHORT_PREFIX_STYLE));
return retValue;
} catch (Throwable th) {
logger.debug("END throw - " + toCall(joinPoint));
logger.debug("Exception: " + th);
throw th;
}
}
}
84
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
9. AOPによるロギング
@Aspect
@Component
public class DumpLogInterceptor {
protected Logger logger = LoggerFactory.getLogger(getClass());
@Around("execution(* ninja.cero.springboot..*.*(..)) && (bean(*Controller) || bean(*Service) || bean(*Dao))")
public Object dump(ProceedingJoinPoint joinPoint) throws Throwable {
try {
logger.debug("BEGIN - " + toCall(joinPoint));
logger.trace("with args - " + ToStringBuilder.reflectionToString(joinPoint.getArgs(),
ToStringStyle.SHORT_PREFIX_STYLE));
Object retValue = joinPoint.proceed(joinPoint.getArgs());
logger.debug("END - " + toCall(joinPoint));
logger.trace(
"with return - " + ToStringBuilder.reflectionToString(retValue, ToStringStyle.SHORT_PREFIX_STYLE));
return retValue;
} catch (Throwable th) {
logger.debug("END throw - " + toCall(joinPoint));
logger.debug("Exception: " + th);
throw th;
}
}
}
85
この記述でController / Service

Daoの実行前後に処理を差し込む
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
86
#9
AOPによるロギングで

問題発生時のリカバリを

高速化しよう
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
87
#10

テスト設計
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
テストあるある
とりあえず、手動でテストしようぜ!

 → 回帰試験で死ぬ。
ロジックがあるControllerからテストすればOK!

 → バリデーションの設定ミスで死ぬ。
通常使うComponentとモックのComponentは

@Profileで切り替えるのがSpring流!

 → 管理できなくなってきて死ぬ。
Spring Bootはend-to-endでテストしやすいから

end-to-endのテストでカバレッジ80%を目指そう!

 → そして死ぬ。
88
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
テストのグッドプラクティス
Controller以降をJUnitでテストする。
カバレッジは最低60%、できれば80%を目指す。
外部サービス呼び出し部分は、モック化する(後述)
例外を任意で発生させたい場合も、モック化すると良い。
無名クラスを活用したモックを作れるようになろう。
end-to-endのJUnitを書いて、

正常系1本とバリデーション部分をテストする。
JUnitのテストクラスに @IntegrationTest(“server.port=0”) をつけ、
RestTemplateを用いてテストする。
バリデーションの試験は、end-to-endでしかできない。
89
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {BlankWeb.class, TestContextConfig.class})
@Transactional
public class EmployeesControllerTest {
@Autowired
EmployeesController controller;
@Test
public void testGetAll() {
List<EmployeesOut> employees = controller.getEmployees();
// TODO: assert
}
90
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {BlankWeb.class, TestContextConfig.class})
@Transactional
public class EmployeesControllerTest {
@Autowired
EmployeesController controller;
@Test
public void testGetAll() {
List<EmployeesOut> employees = controller.getEmployees();
// TODO: assert
}
91
テストの時に必ずつけるアノテーション。
トランザクションを有効にして

試験が終わったら自動でロールバック。
TestContextConfigはあとで。
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {BlankWeb.class, TestContextConfig.class})
@WebAppConfiguration
@IntegrationTest("server.port=0")
@Transactional
public class EmployeesTest {
@Value("http://localhost:${local.server.port}/employees")
String baseUrl;
@Autowired
RestTemplate restTemplate;
@Test
public void testGetList() {
ResponseEntity<List> out = restTemplate.getForEntity(baseUrl, List.class);
// TODO: assert
}
92
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {BlankWeb.class, TestContextConfig.class})
@WebAppConfiguration
@IntegrationTest("server.port=0")
@Transactional
public class EmployeesTest {
@Value("http://localhost:${local.server.port}/employees")
String baseUrl;
@Autowired
RestTemplate restTemplate;
@Test
public void testGetList() {
ResponseEntity<List> out = restTemplate.getForEntity(baseUrl, List.class);
// TODO: assert
}
93
@WebAppConfigurationと

@IntegrationTestをつけて

Tomcatを起動
RestTemplateでアクセス
URLを設定
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
テストのTips
schema.sqlとdata.sqlでデータ投入する
/src/test/resources にschema.sqlとdata.sqlを

置いておけば、JUnitの起動前にのみ実行される。
/src/main/resources に置いておけば

通常起動時に実行される(動作確認向け)
事故ってproduction環境で動かさないように!
Controllerのテストと、end-to-endのテストは同じapplication.ymlでテストする
end-to-endの試験も自動化するため。
end-to-endのテストは、ついつい範囲を広げたくなるが

自動化する試験と、そうでない試験は分けるべき。
94
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
テストのTips
@Componentのモックは、

@Profileよりも@Primaryをつけた方が良い
外部サービスの呼び出しなどをモック化する場合、

モック化したい部分を @Autowired にしておく。
モッククラスを /src/test/java 以下で作成し、

@Component (@Bean) と@Primaryアノテーションを

つければ、JUnit実行時のみ利用される。
95
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
public interface Context {
/**
* セッションIDを取得します。
* @return セッションID
*/
String getSessionId();
}
96
本体コード側にある

インタフェース。
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
public class RequestContext implements Context {
protected HttpServletRequest request;
public RequestContext(HttpServletRequest request) {
this.request = request;
}
@Override
public String getSessionId() {
return request.getSession().getId();
}
}
97
本体コード側にある実装。

HttpServletRequestを使っているので

JUnit時にはエラーが起きる
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
@Configuration
public class TestContextConfig {
@Bean
@Primary
public Context context() {
return new Context() {
@Override
public String getSessionId() {
return "JUNIT";
}
};
}
}
98
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
@Configuration
public class TestContextConfig {
@Bean
@Primary
public Context context() {
return new Context() {
@Override
public String getSessionId() {
return "JUNIT";
}
};
}
}
99
テスト側の設定クラス。
ここに@Primaryを書けば

このコンポーネントが

優先して使われる。
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {BlankWeb.class, TestContextConfig.class})
@Transactional
public class EmployeesControllerTest {
@Autowired
EmployeesController controller;
@Test
public void testGetAll() {
List<EmployeesOut> employees = controller.getEmployees();
// TODO: assert
}
100
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {BlankWeb.class, TestContextConfig.class})
@Transactional
public class EmployeesControllerTest {
@Autowired
EmployeesController controller;
@Test
public void testGetAll() {
List<EmployeesOut> employees = controller.getEmployees();
// TODO: assert
}
101
テスト側で、先ほど書いた

Configurationを明示的に読み込む
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
10. テスト設計
テストのTips
/src/test/java 側に作ったテスト用の

@Primary つき@Component (@Bean) は

end-to-endのサーバ側にも適用されるので

サーバ側でもモックを使いやすい
たぶんこれ相当便利。
102
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
103
まとめ
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
104
スライド読み直せ!
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
105
One more thing…
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
106
今日紹介したソースは

GitHubで公開中!
Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved.
107
https://github.com/cero-t/
spring-boot-kinoko-2015
Copyright © Acroquest Technology Co., Ltd. All rights reserved.
108
Enjoy Spring Boot!
1 of 108

Recommended

怖くないSpring Bootのオートコンフィグレーション by
怖くないSpring Bootのオートコンフィグレーション怖くないSpring Bootのオートコンフィグレーション
怖くないSpring Bootのオートコンフィグレーション土岐 孝平
2.9K views39 slides
これからSpringを使う開発者が知っておくべきこと by
これからSpringを使う開発者が知っておくべきことこれからSpringを使う開発者が知っておくべきこと
これからSpringを使う開発者が知っておくべきこと土岐 孝平
21.4K views32 slides
入社1年目のプログラミング初心者がSpringを学ぶための手引き by
入社1年目のプログラミング初心者がSpringを学ぶための手引き入社1年目のプログラミング初心者がSpringを学ぶための手引き
入社1年目のプログラミング初心者がSpringを学ぶための手引き土岐 孝平
24.7K views60 slides
Java ORマッパー選定のポイント #jsug by
Java ORマッパー選定のポイント #jsugJava ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugMasatoshi Tada
90.1K views66 slides
さくっと理解するSpring bootの仕組み by
さくっと理解するSpring bootの仕組みさくっと理解するSpring bootの仕組み
さくっと理解するSpring bootの仕組みTakeshi Ogawa
65.2K views38 slides
今こそ知りたいSpring Batch(Spring Fest 2020講演資料) by
今こそ知りたいSpring Batch(Spring Fest 2020講演資料)今こそ知りたいSpring Batch(Spring Fest 2020講演資料)
今こそ知りたいSpring Batch(Spring Fest 2020講演資料)NTT DATA Technology & Innovation
8.4K views53 slides

More Related Content

What's hot

初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー by
初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー
初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービューMasatoshi Tada
29.8K views63 slides
Spring Boot × Vue.jsでSPAを作る by
Spring Boot × Vue.jsでSPAを作るSpring Boot × Vue.jsでSPAを作る
Spring Boot × Vue.jsでSPAを作るGo Miyasaka
14.9K views31 slides
Pivotal認定講師によるSpring Framework 5.1 & Spring Boot 2.1ハンズオン! #jjug_ccc by
Pivotal認定講師によるSpring Framework 5.1 & Spring Boot 2.1ハンズオン! #jjug_cccPivotal認定講師によるSpring Framework 5.1 & Spring Boot 2.1ハンズオン! #jjug_ccc
Pivotal認定講師によるSpring Framework 5.1 & Spring Boot 2.1ハンズオン! #jjug_cccMasatoshi Tada
6.8K views68 slides
Form認証で学ぶSpring Security入門 by
Form認証で学ぶSpring Security入門Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門Ryosuke Uchitate
11.2K views64 slides
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 - by
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -onozaty
3.2K views30 slides
Springを何となく使ってる人が抑えるべきポイント by
Springを何となく使ってる人が抑えるべきポイントSpringを何となく使ってる人が抑えるべきポイント
Springを何となく使ってる人が抑えるべきポイント土岐 孝平
25K views18 slides

What's hot(20)

初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー by Masatoshi Tada
初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー
初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー
Masatoshi Tada29.8K views
Spring Boot × Vue.jsでSPAを作る by Go Miyasaka
Spring Boot × Vue.jsでSPAを作るSpring Boot × Vue.jsでSPAを作る
Spring Boot × Vue.jsでSPAを作る
Go Miyasaka14.9K views
Pivotal認定講師によるSpring Framework 5.1 & Spring Boot 2.1ハンズオン! #jjug_ccc by Masatoshi Tada
Pivotal認定講師によるSpring Framework 5.1 & Spring Boot 2.1ハンズオン! #jjug_cccPivotal認定講師によるSpring Framework 5.1 & Spring Boot 2.1ハンズオン! #jjug_ccc
Pivotal認定講師によるSpring Framework 5.1 & Spring Boot 2.1ハンズオン! #jjug_ccc
Masatoshi Tada6.8K views
Form認証で学ぶSpring Security入門 by Ryosuke Uchitate
Form認証で学ぶSpring Security入門Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
Ryosuke Uchitate11.2K views
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 - by onozaty
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
onozaty3.2K views
Springを何となく使ってる人が抑えるべきポイント by 土岐 孝平
Springを何となく使ってる人が抑えるべきポイントSpringを何となく使ってる人が抑えるべきポイント
Springを何となく使ってる人が抑えるべきポイント
土岐 孝平25K views
これで怖くない!?コードリーディングで学ぶSpring Security #中央線Meetup by Masatoshi Tada
これで怖くない!?コードリーディングで学ぶSpring Security #中央線Meetupこれで怖くない!?コードリーディングで学ぶSpring Security #中央線Meetup
これで怖くない!?コードリーディングで学ぶSpring Security #中央線Meetup
Masatoshi Tada14.5K views
SPAセキュリティ入門~PHP Conference Japan 2021 by Hiroshi Tokumaru
SPAセキュリティ入門~PHP Conference Japan 2021SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021
Hiroshi Tokumaru99.5K views
ReactiveだけじゃないSpring 5 & Spring Boot 2新機能解説 by Masatoshi Tada
ReactiveだけじゃないSpring 5 & Spring Boot 2新機能解説ReactiveだけじゃないSpring 5 & Spring Boot 2新機能解説
ReactiveだけじゃないSpring 5 & Spring Boot 2新機能解説
Masatoshi Tada15.9K views
O/Rマッパーによるトラブルを未然に防ぐ by kwatch
O/Rマッパーによるトラブルを未然に防ぐO/Rマッパーによるトラブルを未然に防ぐ
O/Rマッパーによるトラブルを未然に防ぐ
kwatch48.4K views
Javaのログ出力: 道具と考え方 by Taku Miyakawa
Javaのログ出力: 道具と考え方Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方
Taku Miyakawa74.3K views
AngularとSpring Bootで作るSPA + RESTful Web Serviceアプリケーション by ssuser070fa9
AngularとSpring Bootで作るSPA + RESTful Web ServiceアプリケーションAngularとSpring Bootで作るSPA + RESTful Web Serviceアプリケーション
AngularとSpring Bootで作るSPA + RESTful Web Serviceアプリケーション
ssuser070fa99.7K views
今さら聞けないDiとspring by 土岐 孝平
今さら聞けないDiとspring今さら聞けないDiとspring
今さら聞けないDiとspring
土岐 孝平24.8K views
Grails 3.0先取り!? Spring Boot入門ハンズオン #jggug_boot by Toshiaki Maki
Grails 3.0先取り!? Spring Boot入門ハンズオン #jggug_bootGrails 3.0先取り!? Spring Boot入門ハンズオン #jggug_boot
Grails 3.0先取り!? Spring Boot入門ハンズオン #jggug_boot
Toshiaki Maki37.3K views
Spring Boot の Web アプリケーションを Docker に載せて AWS ECS で動かしている話 by JustSystems Corporation
Spring Boot の Web アプリケーションを Docker に載せて AWS ECS で動かしている話Spring Boot の Web アプリケーションを Docker に載せて AWS ECS で動かしている話
Spring Boot の Web アプリケーションを Docker に載せて AWS ECS で動かしている話
これから始めるSpringのwebアプリケーション by 土岐 孝平
これから始めるSpringのwebアプリケーションこれから始めるSpringのwebアプリケーション
これから始めるSpringのwebアプリケーション
土岐 孝平19.2K views
FlutterでGraphQLを扱う by IgaHironobu
FlutterでGraphQLを扱うFlutterでGraphQLを扱う
FlutterでGraphQLを扱う
IgaHironobu2.9K views
Junitを使ったjavaのテスト入門 by Satoshi Kubo
Junitを使ったjavaのテスト入門Junitを使ったjavaのテスト入門
Junitを使ったjavaのテスト入門
Satoshi Kubo37.6K views

Viewers also liked

イマドキの現場で使えるJavaライブラリ事情 by
イマドキの現場で使えるJavaライブラリ事情イマドキの現場で使えるJavaライブラリ事情
イマドキの現場で使えるJavaライブラリ事情takezoe
24.8K views38 slides
Let's reconsider about collecting logs. Plus, visiting elastic@Moutain View! by
Let's reconsider about collecting logs. Plus, visiting elastic@Moutain View!Let's reconsider about collecting logs. Plus, visiting elastic@Moutain View!
Let's reconsider about collecting logs. Plus, visiting elastic@Moutain View!心 谷本
1.7K views59 slides
JJUG CCC 2015 Fall keynote by
JJUG CCC 2015 Fall keynoteJJUG CCC 2015 Fall keynote
JJUG CCC 2015 Fall keynote心 谷本
5.1K views98 slides
Spring Boot + Netflix Eureka by
Spring Boot + Netflix EurekaSpring Boot + Netflix Eureka
Spring Boot + Netflix Eureka心 谷本
41.2K views83 slides
サバフェス 2016 Yahoo! ID連携のご紹介 〜OpenID Connect入門〜 by
サバフェス 2016 Yahoo! ID連携のご紹介 〜OpenID Connect入門〜サバフェス 2016 Yahoo! ID連携のご紹介 〜OpenID Connect入門〜
サバフェス 2016 Yahoo! ID連携のご紹介 〜OpenID Connect入門〜Masaru Kurahayashi
4.9K views65 slides
Microserviceなんて最初からやるもんじゃ無かった by
Microserviceなんて最初からやるもんじゃ無かったMicroserviceなんて最初からやるもんじゃ無かった
Microserviceなんて最初からやるもんじゃ無かったAkira Miki
70.5K views31 slides

Viewers also liked(20)

イマドキの現場で使えるJavaライブラリ事情 by takezoe
イマドキの現場で使えるJavaライブラリ事情イマドキの現場で使えるJavaライブラリ事情
イマドキの現場で使えるJavaライブラリ事情
takezoe24.8K views
Let's reconsider about collecting logs. Plus, visiting elastic@Moutain View! by 心 谷本
Let's reconsider about collecting logs. Plus, visiting elastic@Moutain View!Let's reconsider about collecting logs. Plus, visiting elastic@Moutain View!
Let's reconsider about collecting logs. Plus, visiting elastic@Moutain View!
心 谷本1.7K views
JJUG CCC 2015 Fall keynote by 心 谷本
JJUG CCC 2015 Fall keynoteJJUG CCC 2015 Fall keynote
JJUG CCC 2015 Fall keynote
心 谷本5.1K views
Spring Boot + Netflix Eureka by 心 谷本
Spring Boot + Netflix EurekaSpring Boot + Netflix Eureka
Spring Boot + Netflix Eureka
心 谷本41.2K views
サバフェス 2016 Yahoo! ID連携のご紹介 〜OpenID Connect入門〜 by Masaru Kurahayashi
サバフェス 2016 Yahoo! ID連携のご紹介 〜OpenID Connect入門〜サバフェス 2016 Yahoo! ID連携のご紹介 〜OpenID Connect入門〜
サバフェス 2016 Yahoo! ID連携のご紹介 〜OpenID Connect入門〜
Masaru Kurahayashi4.9K views
Microserviceなんて最初からやるもんじゃ無かった by Akira Miki
Microserviceなんて最初からやるもんじゃ無かったMicroserviceなんて最初からやるもんじゃ無かった
Microserviceなんて最初からやるもんじゃ無かった
Akira Miki70.5K views
Beginning Java EE 6 勉強会(6) #bje_study by Masato Kawamura
Beginning Java EE 6 勉強会(6) #bje_studyBeginning Java EE 6 勉強会(6) #bje_study
Beginning Java EE 6 勉強会(6) #bje_study
Masato Kawamura3.2K views
OAuth / OpenID Connectを中心とするAPIセキュリティについて #yuzawaws by Tatsuo Kudo
OAuth / OpenID Connectを中心とするAPIセキュリティについて #yuzawawsOAuth / OpenID Connectを中心とするAPIセキュリティについて #yuzawaws
OAuth / OpenID Connectを中心とするAPIセキュリティについて #yuzawaws
Tatsuo Kudo13.4K views
WebAPIのこれまでとこれから by Yohei Yamamoto
WebAPIのこれまでとこれからWebAPIのこれまでとこれから
WebAPIのこれまでとこれから
Yohei Yamamoto29.6K views
Java でつくる 低レイテンシ実装の技巧 by Ryosuke Yamazaki
Java でつくる低レイテンシ実装の技巧Java でつくる低レイテンシ実装の技巧
Java でつくる 低レイテンシ実装の技巧
Ryosuke Yamazaki10.8K views
金融 API 時代のセキュリティ: OpenID Financial API (FAPI) WG by Nat Sakimura
金融 API 時代のセキュリティ: OpenID Financial API (FAPI) WG金融 API 時代のセキュリティ: OpenID Financial API (FAPI) WG
金融 API 時代のセキュリティ: OpenID Financial API (FAPI) WG
Nat Sakimura13.2K views
今更聞けないOAuth2.0 by Takahiro Sato
今更聞けないOAuth2.0今更聞けないOAuth2.0
今更聞けないOAuth2.0
Takahiro Sato68.9K views
Office365のIdentity管理 by Naohiro Fujie
Office365のIdentity管理Office365のIdentity管理
Office365のIdentity管理
Naohiro Fujie36.4K views
なぜOpenID Connectが必要となったのか、その歴史的背景 by Tatsuo Kudo
なぜOpenID Connectが必要となったのか、その歴史的背景なぜOpenID Connectが必要となったのか、その歴史的背景
なぜOpenID Connectが必要となったのか、その歴史的背景
Tatsuo Kudo49.3K views
エンタープライズITでのOpenID Connect利用ガイドライン by Tatsuo Kudo
エンタープライズITでのOpenID Connect利用ガイドラインエンタープライズITでのOpenID Connect利用ガイドライン
エンタープライズITでのOpenID Connect利用ガイドライン
Tatsuo Kudo13.8K views
SAML / OpenID Connect / OAuth / SCIM 技術解説 - ID&IT 2014 #idit2014 by Nov Matake
SAML / OpenID Connect / OAuth / SCIM 技術解説  - ID&IT 2014 #idit2014SAML / OpenID Connect / OAuth / SCIM 技術解説  - ID&IT 2014 #idit2014
SAML / OpenID Connect / OAuth / SCIM 技術解説 - ID&IT 2014 #idit2014
Nov Matake98.8K views
OpenID Connect 入門 〜コンシューマーにおけるID連携のトレンド〜 by Masaru Kurahayashi
OpenID Connect 入門 〜コンシューマーにおけるID連携のトレンド〜OpenID Connect 入門 〜コンシューマーにおけるID連携のトレンド〜
OpenID Connect 入門 〜コンシューマーにおけるID連携のトレンド〜
Masaru Kurahayashi146.9K views

Similar to Spring Bootをはじめる時にやるべき10のこと

人気番組との戦い! Javaシステムのパフォーマンスチューニング奮闘記 by
人気番組との戦い! Javaシステムのパフォーマンスチューニング奮闘記人気番組との戦い! Javaシステムのパフォーマンスチューニング奮闘記
人気番組との戦い! Javaシステムのパフォーマンスチューニング奮闘記心 谷本
6K views92 slides
QAエンジニアを通じて 弊社の開発環境がより良くなる日 〜 OpenSTF 編 〜 by
QAエンジニアを通じて弊社の開発環境がより良くなる日 〜 OpenSTF 編 〜QAエンジニアを通じて弊社の開発環境がより良くなる日 〜 OpenSTF 編 〜
QAエンジニアを通じて 弊社の開発環境がより良くなる日 〜 OpenSTF 編 〜gree_tech
7.5K views92 slides
ドリコムを支える課金ライブラリを支えるJenkins by
ドリコムを支える課金ライブラリを支えるJenkinsドリコムを支える課金ライブラリを支えるJenkins
ドリコムを支える課金ライブラリを支えるJenkinsGo Sueyoshi (a.k.a sue445)
5.1K views59 slides
2015年5月期 AITCオープンラボ 「第二回 デジタルガジェット祭り!」 by
2015年5月期 AITCオープンラボ 「第二回 デジタルガジェット祭り!」2015年5月期 AITCオープンラボ 「第二回 デジタルガジェット祭り!」
2015年5月期 AITCオープンラボ 「第二回 デジタルガジェット祭り!」aitc_jp
1K views54 slides
RPAって何、どんなことできるの by
RPAって何、どんなことできるのRPAって何、どんなことできるの
RPAって何、どんなことできるの株式会社オプト 仙台ラボラトリ
3K views59 slides
[Agile Japan 2019]DXを実現するためにユーザ企業とSI企業が 今すぐとるべき3つのステップ by
[Agile Japan 2019]DXを実現するためにユーザ企業とSI企業が 今すぐとるべき3つのステップ[Agile Japan 2019]DXを実現するためにユーザ企業とSI企業が 今すぐとるべき3つのステップ
[Agile Japan 2019]DXを実現するためにユーザ企業とSI企業が 今すぐとるべき3つのステップShigeki Morizane
1.5K views80 slides

Similar to Spring Bootをはじめる時にやるべき10のこと(20)

人気番組との戦い! Javaシステムのパフォーマンスチューニング奮闘記 by 心 谷本
人気番組との戦い! Javaシステムのパフォーマンスチューニング奮闘記人気番組との戦い! Javaシステムのパフォーマンスチューニング奮闘記
人気番組との戦い! Javaシステムのパフォーマンスチューニング奮闘記
心 谷本6K views
QAエンジニアを通じて 弊社の開発環境がより良くなる日 〜 OpenSTF 編 〜 by gree_tech
QAエンジニアを通じて弊社の開発環境がより良くなる日 〜 OpenSTF 編 〜QAエンジニアを通じて弊社の開発環境がより良くなる日 〜 OpenSTF 編 〜
QAエンジニアを通じて 弊社の開発環境がより良くなる日 〜 OpenSTF 編 〜
gree_tech7.5K views
2015年5月期 AITCオープンラボ 「第二回 デジタルガジェット祭り!」 by aitc_jp
2015年5月期 AITCオープンラボ 「第二回 デジタルガジェット祭り!」2015年5月期 AITCオープンラボ 「第二回 デジタルガジェット祭り!」
2015年5月期 AITCオープンラボ 「第二回 デジタルガジェット祭り!」
aitc_jp1K views
[Agile Japan 2019]DXを実現するためにユーザ企業とSI企業が 今すぐとるべき3つのステップ by Shigeki Morizane
[Agile Japan 2019]DXを実現するためにユーザ企業とSI企業が 今すぐとるべき3つのステップ[Agile Japan 2019]DXを実現するためにユーザ企業とSI企業が 今すぐとるべき3つのステップ
[Agile Japan 2019]DXを実現するためにユーザ企業とSI企業が 今すぐとるべき3つのステップ
Shigeki Morizane1.5K views
iPhoneアプリ開発を楽に楽しくするサイトまとめ by Hiramatsu Ryosuke
iPhoneアプリ開発を楽に楽しくするサイトまとめiPhoneアプリ開発を楽に楽しくするサイトまとめ
iPhoneアプリ開発を楽に楽しくするサイトまとめ
Hiramatsu Ryosuke4.6K views
どうする!?これからのCto c(仮) by Junya Tanaka
どうする!?これからのCto c(仮)どうする!?これからのCto c(仮)
どうする!?これからのCto c(仮)
Junya Tanaka732 views
スタートアップ向け!1人日でできるサービスの高速化方法と成果 by Koichiro Sumi
スタートアップ向け!1人日でできるサービスの高速化方法と成果スタートアップ向け!1人日でできるサービスの高速化方法と成果
スタートアップ向け!1人日でできるサービスの高速化方法と成果
Koichiro Sumi6.5K views
おすすめインフラ! for スタートアップ by Koichiro Sumi
おすすめインフラ! for スタートアップおすすめインフラ! for スタートアップ
おすすめインフラ! for スタートアップ
Koichiro Sumi1.6K views
Soracom ug#10:SORACOM Techonology Camp夜の部!東京支部活動報告 by Haruka Yamashita
Soracom ug#10:SORACOM Techonology Camp夜の部!東京支部活動報告Soracom ug#10:SORACOM Techonology Camp夜の部!東京支部活動報告
Soracom ug#10:SORACOM Techonology Camp夜の部!東京支部活動報告
Haruka Yamashita277 views
Google apps scriptを使って業務改善 by dcubeio
Google apps scriptを使って業務改善Google apps scriptを使って業務改善
Google apps scriptを使って業務改善
dcubeio5.6K views
SoftLayerのAPIを活用した􀀁 ポータルサービス「SETTA」 by softlayerjp
SoftLayerのAPIを活用した􀀁 ポータルサービス「SETTA」SoftLayerのAPIを活用した􀀁 ポータルサービス「SETTA」
SoftLayerのAPIを活用した􀀁 ポータルサービス「SETTA」
softlayerjp1.2K views
Whomor spine勉強会 遠藤加筆_150114 by 幹也 芝辻
Whomor spine勉強会 遠藤加筆_150114Whomor spine勉強会 遠藤加筆_150114
Whomor spine勉強会 遠藤加筆_150114
幹也 芝辻3.5K views
IETF90 IoT関連WG報告 #isocjp by Kaoru Maeda
IETF90 IoT関連WG報告 #isocjpIETF90 IoT関連WG報告 #isocjp
IETF90 IoT関連WG報告 #isocjp
Kaoru Maeda3.1K views
技術選択とアーキテクトの役割 (要約版) by Toru Yamaguchi
技術選択とアーキテクトの役割 (要約版)技術選択とアーキテクトの役割 (要約版)
技術選択とアーキテクトの役割 (要約版)
Toru Yamaguchi5K views
ああ、素晴らしきTDD ~アプリとエンジニアの心に安寧を~ by Saiki Iijima
ああ、素晴らしきTDD  ~アプリとエンジニアの心に安寧を~ああ、素晴らしきTDD  ~アプリとエンジニアの心に安寧を~
ああ、素晴らしきTDD ~アプリとエンジニアの心に安寧を~
Saiki Iijima8.2K views
Coldfusionを活かすシステム企画をリーンスタートアップに学ぶ by masashi takehara
Coldfusionを活かすシステム企画をリーンスタートアップに学ぶColdfusionを活かすシステム企画をリーンスタートアップに学ぶ
Coldfusionを活かすシステム企画をリーンスタートアップに学ぶ
masashi takehara1.8K views
Instok[file makerを用いた弊社の取組について」 by 基演 伊藤
Instok[file makerを用いた弊社の取組について」Instok[file makerを用いた弊社の取組について」
Instok[file makerを用いた弊社の取組について」
基演 伊藤460 views

More from 心 谷本

プレゼンの技術 2 実践編 by
プレゼンの技術 2 実践編プレゼンの技術 2 実践編
プレゼンの技術 2 実践編心 谷本
72.9K views90 slides
プレゼンの技術 1 考え方 by
プレゼンの技術 1 考え方プレゼンの技術 1 考え方
プレゼンの技術 1 考え方心 谷本
11.2K views106 slides
プレゼンの技術 by
プレゼンの技術プレゼンの技術
プレゼンの技術心 谷本
134.2K views112 slides
from old java to java8 - KanJava Edition by
from old java to java8 - KanJava Editionfrom old java to java8 - KanJava Edition
from old java to java8 - KanJava Edition心 谷本
2.9K views91 slides
実例Javaトラブルシューティング! 〜稼働中のシステムを立て直した半年間の軌跡 by
実例Javaトラブルシューティング! 〜稼働中のシステムを立て直した半年間の軌跡実例Javaトラブルシューティング! 〜稼働中のシステムを立て直した半年間の軌跡
実例Javaトラブルシューティング! 〜稼働中のシステムを立て直した半年間の軌跡心 谷本
24.7K views76 slides
from old Java to modern Java by
from old Java to modern Javafrom old Java to modern Java
from old Java to modern Java心 谷本
35.4K views102 slides

More from 心 谷本(10)

プレゼンの技術 2 実践編 by 心 谷本
プレゼンの技術 2 実践編プレゼンの技術 2 実践編
プレゼンの技術 2 実践編
心 谷本72.9K views
プレゼンの技術 1 考え方 by 心 谷本
プレゼンの技術 1 考え方プレゼンの技術 1 考え方
プレゼンの技術 1 考え方
心 谷本11.2K views
プレゼンの技術 by 心 谷本
プレゼンの技術プレゼンの技術
プレゼンの技術
心 谷本134.2K views
from old java to java8 - KanJava Edition by 心 谷本
from old java to java8 - KanJava Editionfrom old java to java8 - KanJava Edition
from old java to java8 - KanJava Edition
心 谷本2.9K views
実例Javaトラブルシューティング! 〜稼働中のシステムを立て直した半年間の軌跡 by 心 谷本
実例Javaトラブルシューティング! 〜稼働中のシステムを立て直した半年間の軌跡実例Javaトラブルシューティング! 〜稼働中のシステムを立て直した半年間の軌跡
実例Javaトラブルシューティング! 〜稼働中のシステムを立て直した半年間の軌跡
心 谷本24.7K views
from old Java to modern Java by 心 谷本
from old Java to modern Javafrom old Java to modern Java
from old Java to modern Java
心 谷本35.4K views
日本一細かいJavaOne2011報告 by 心 谷本
日本一細かいJavaOne2011報告日本一細かいJavaOne2011報告
日本一細かいJavaOne2011報告
心 谷本1.2K views
勝敗は常に見積もりで決まる〜Redmineを使った時間記録の話 by 心 谷本
勝敗は常に見積もりで決まる〜Redmineを使った時間記録の話勝敗は常に見積もりで決まる〜Redmineを使った時間記録の話
勝敗は常に見積もりで決まる〜Redmineを使った時間記録の話
心 谷本6.9K views
日本で二番目に「細かい」JavaOne2011報告 by 心 谷本
日本で二番目に「細かい」JavaOne2011報告日本で二番目に「細かい」JavaOne2011報告
日本で二番目に「細かい」JavaOne2011報告
心 谷本1K views
[関ジャバ]Java News 2011 Mar by 心 谷本
[関ジャバ]Java News 2011 Mar[関ジャバ]Java News 2011 Mar
[関ジャバ]Java News 2011 Mar
心 谷本831 views

Recently uploaded

さくらのひやおろし2023 by
さくらのひやおろし2023さくらのひやおろし2023
さくらのひやおろし2023法林浩之
94 views58 slides
今、改めて考えるPostgreSQLプラットフォーム - マルチクラウドとポータビリティ -(PostgreSQL Conference Japan 20... by
今、改めて考えるPostgreSQLプラットフォーム - マルチクラウドとポータビリティ -(PostgreSQL Conference Japan 20...今、改めて考えるPostgreSQLプラットフォーム - マルチクラウドとポータビリティ -(PostgreSQL Conference Japan 20...
今、改めて考えるPostgreSQLプラットフォーム - マルチクラウドとポータビリティ -(PostgreSQL Conference Japan 20...NTT DATA Technology & Innovation
101 views42 slides
The Things Stack説明資料 by The Things Industries by
The Things Stack説明資料 by The Things IndustriesThe Things Stack説明資料 by The Things Industries
The Things Stack説明資料 by The Things IndustriesCRI Japan, Inc.
50 views29 slides
Web3 Career_クレデン資料 .pdf by
Web3 Career_クレデン資料 .pdfWeb3 Career_クレデン資料 .pdf
Web3 Career_クレデン資料 .pdfnanamatsuo
14 views9 slides
01Booster Studio ご紹介資料 by
01Booster Studio ご紹介資料01Booster Studio ご紹介資料
01Booster Studio ご紹介資料ssusere7a2172
345 views19 slides
「概念モデリング自動化に向けた第一歩」 ~ ChatGPT・Open AI 活用による開発対象のモデル化 by
「概念モデリング自動化に向けた第一歩」 ~ ChatGPT・Open AI 活用による開発対象のモデル化「概念モデリング自動化に向けた第一歩」 ~ ChatGPT・Open AI 活用による開発対象のモデル化
「概念モデリング自動化に向けた第一歩」 ~ ChatGPT・Open AI 活用による開発対象のモデル化Knowledge & Experience
12 views34 slides

Recently uploaded(11)

さくらのひやおろし2023 by 法林浩之
さくらのひやおろし2023さくらのひやおろし2023
さくらのひやおろし2023
法林浩之94 views
今、改めて考えるPostgreSQLプラットフォーム - マルチクラウドとポータビリティ -(PostgreSQL Conference Japan 20... by NTT DATA Technology & Innovation
今、改めて考えるPostgreSQLプラットフォーム - マルチクラウドとポータビリティ -(PostgreSQL Conference Japan 20...今、改めて考えるPostgreSQLプラットフォーム - マルチクラウドとポータビリティ -(PostgreSQL Conference Japan 20...
今、改めて考えるPostgreSQLプラットフォーム - マルチクラウドとポータビリティ -(PostgreSQL Conference Japan 20...
The Things Stack説明資料 by The Things Industries by CRI Japan, Inc.
The Things Stack説明資料 by The Things IndustriesThe Things Stack説明資料 by The Things Industries
The Things Stack説明資料 by The Things Industries
CRI Japan, Inc.50 views
Web3 Career_クレデン資料 .pdf by nanamatsuo
Web3 Career_クレデン資料 .pdfWeb3 Career_クレデン資料 .pdf
Web3 Career_クレデン資料 .pdf
nanamatsuo14 views
01Booster Studio ご紹介資料 by ssusere7a2172
01Booster Studio ご紹介資料01Booster Studio ご紹介資料
01Booster Studio ご紹介資料
ssusere7a2172345 views
「概念モデリング自動化に向けた第一歩」 ~ ChatGPT・Open AI 活用による開発対象のモデル化 by Knowledge & Experience
「概念モデリング自動化に向けた第一歩」 ~ ChatGPT・Open AI 活用による開発対象のモデル化「概念モデリング自動化に向けた第一歩」 ~ ChatGPT・Open AI 活用による開発対象のモデル化
「概念モデリング自動化に向けた第一歩」 ~ ChatGPT・Open AI 活用による開発対象のモデル化
SSH応用編_20231129.pdf by icebreaker4
SSH応用編_20231129.pdfSSH応用編_20231129.pdf
SSH応用編_20231129.pdf
icebreaker4184 views
Windows 11 information that can be used at the development site by Atomu Hidaka
Windows 11 information that can be used at the development siteWindows 11 information that can be used at the development site
Windows 11 information that can be used at the development site
Atomu Hidaka76 views
SNMPセキュリティ超入門 by mkoda
SNMPセキュリティ超入門SNMPセキュリティ超入門
SNMPセキュリティ超入門
mkoda188 views
速習! PostgreSQL専用HAソフトウェア: Patroni(PostgreSQL Conference Japan 2023 発表資料) by NTT DATA Technology & Innovation
速習! PostgreSQL専用HAソフトウェア: Patroni(PostgreSQL Conference Japan 2023 発表資料)速習! PostgreSQL専用HAソフトウェア: Patroni(PostgreSQL Conference Japan 2023 発表資料)
速習! PostgreSQL専用HAソフトウェア: Patroni(PostgreSQL Conference Japan 2023 発表資料)

Spring Bootをはじめる時にやるべき10のこと

  • 2. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 皆さん
 用意はいいですか? 2
  • 3. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 鈴木会長は
 こっちじゃないぞ? 3
  • 4. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. では、始めましょう! 4
  • 5. Copyright © Acroquest Technology Co., Ltd. All rights reserved. 自己紹介 5 • 谷本 心 (Shin Tanimoto) - Acroquest Technology株式会社 - 開発&トラブルシュート教育 - JavaOneスピーカー - JJUG / 関ジャバ / S2JSFコミッタ - Twitter : @cero_t (日本語) - Facebook : shin.tanimoto (英語)
  • 6. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 6 Struts + Hibernate Seasar2 + S2JSF + S2Dao Click + Guice + Mirage Spring MVC + Hibernate
  • 7. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. フレームワークに
 求めていること 7
  • 8. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 開発効率
 生産性 8
  • 9. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. ではなくて 9
  • 10. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. ハマらない
 ミスしない
 ミスをリカバリできる 10
  • 11. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. ひとつハマれば
 3人日が奪われ 11
  • 12. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. ひとつミスしていれば
 商用障害が起き 12
  • 13. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. リカバリできずに
 今日も徹夜 13
  • 14. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. ハマらない
 ミスしない
 ミスをリカバリできる 14
  • 15. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. そのための
 Spring Boot 15
  • 17. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 17 #1
 SpringBootを知る
  • 18. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 1. Spring Bootを知る Spring Bootとは 複雑化したSpringプロジェクト群を使った開発を シンプルに開始できる仕組み 18
  • 19. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 19 Springベースの
 フルスタック
 プラットフォーム
  • 20. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 1. Spring Bootを知る フルスタックプラットフォーム View層、コンテナ層、データアクセス層
 監視、非同期メッセージング、クラウド対応など
 様々な機能を「Spring Boot」という共通の
 プラットフォーム上で利用できる。 20
  • 21. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 1. Spring Bootを知る フルスタックプラットフォームでないと 自分で様々なフレームワークを組み合わせると
 もちろん自由に選べる反面、
 設定の記述や、動作検証などが必要になる。 ここに「ハマり」要因がある。 21
  • 22. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 1. Spring Bootを知る あまり強調しない方が良いこと Microservices向けフレームワーク 別にそれが目的ではない Executable JAR ≠ Microservices XMLを書かない ymlや設定クラスを少し作る 22
  • 23. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 23 #1 Spring Bootなら
 組み合わせでハマらない!
  • 24. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 24 #2
 はじめての
 Spring Boot
  • 25. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 2. はじめてのSpring Boot 新しいプロダクトの利用時あるある ドキュメントがない。 ドキュメントが英語しかない。 ブログがない。ノウハウがない。 とりあえず少しずつググりながら
 場当たり対応で何とか凌ぐ。 そんなことをしているから「設計ミス」をする。 25
  • 26. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 2. はじめてのSpring Boot はじめてのSpring Boot 26 @makingの力作 Spring Bootを用いた
 開発、試験、デプロイなどを
 まるっと習得できる こっちの入門スライドもオススメ
 http://www.slideshare.net/ makingx/grails-30-spring-boot
  • 27. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 27 #2 はじめてのSpring Bootで
 初期学習を効率化!
  • 28. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 28 #3
 Spring Initializr
  • 29. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 3. Spring Initializr プロジェクト立ち上げ時あるある pom.xmlを書いて、必要な依存ライブラリを列挙する。 ・・・のは面倒だから、exampleプロジェクトを探して
 不要なソースコードを削除する。 なんか不要なJARが混入している なぜかバージョン違いのJARが混入する 頑張ってビルドファイルを書いたけど、なぜか動かない。 ここに「ミス」と「ハマり」要因がある。 29
  • 30. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 3. Spring Initializr Spring Initializrとは https://start.spring.io/ Spring Bootプロジェクトの雛形を作る Maven or Gradleのプロジェクト作成 利用するプロジェクトやライブラリを選択できる Web、JDBC、Security、AOP、
 JPA、Thymeleafなど つまずかずにスタートできる! 30
  • 31. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 3. Spring Initializr 使い方 https://start.spring.io/ に行く。 必要な情報と、利用するモジュールを選ぶ。 Actuatorおすすめ Generate Projectをクリック。 ダウンロードしたzipを解凍する。 IDEにインポートする。 以下のいずれかで実行する。 mainメソッドを実行する mvn spring-boot:run 31
  • 32. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 32 #3 Spring Initializrなら
 初期構築でミスしない!
  • 33. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 33 #4
 pom.xmlの設計
  • 34. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 4. pom.xmlの設計 pom.xmlあるある 複数モジュールを作る時、依存JARのバージョンを
 複数のpom.xmlに重複して書いている。 そしてJARのバージョン違いが発生する 親子モジュールとか難しいから、
 単一モジュールで行くぜー! WebAPIとバッチがなぜか同じJARに入ってる 34
  • 35. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 4. pom.xmlの設計 pom.xmlのグッドプラクティス デプロイ単位、ライフサイクル単位で分割する 共通部分を切り出す フレームワーク部分 自動生成したエンティティ しかしそうすると、前述したJARの
 バージョン違い問題が起きる・・・? 35
  • 36. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 4. pom.xmlの設計 pom.xmlのグッドプラクティス 依存JARのバージョンは、親のpom.xmlに書く <dependencyManagement> を使ってバージョンを定義する Spring IO platformを使う http://platform.spring.io/platform/ 大げさな名前だが、ただのpom.xml Spring関連モジュールだけでなく、
 著名なプロダクトも含むバージョンを規定したpom.xml commons-lang、guice、joda-time、jruby、、、 Version1.1.4では552個のモジュールのバージョンが規定されている 36
  • 37. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 37 #4 Spring IO platformで
 pom.xmlをシンプルに!
  • 38. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 38 #5
 Controllerの共通設定
  • 39. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 5. Controllerの共通設定 突然ですが、
 JSR 310 Date and Time APIの
 LocalDateクラスってご存じですか? LocalDate : 日付のみ。時間なし。 LocalTime : 時間のみ。日付なし。 LocalDateTime : 日付も時間もあり。 39
  • 40. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 5. Controllerの共通設定 java.util.DateやCalendarはハマりやすい Dateを使って比較する際、日付だけで良いのに
 余計な時分秒が入っているせいで、判定を誤る。 Calendarで時分秒に0を指定したけど
 ミリ秒に余計な値が入っていて、判定を誤る。 SimpleDateFormatがスレッドセーフでないことを
 知らずに、商用環境で問題が起きる。 40
  • 41. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 5. Controllerの共通設定 JSR 310をSpring Bootでも使いたい できること yyyy-MM-dd形式の日付 JSONリクエスト → LocalDateフィールド できないこと yyyy/MM/dd形式の日付 LocalDateフィールド → JSONレスポンス 41
  • 42. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 5. Controllerの共通設定 ControllerでLocalDateを使う Controllerで利用するJacksonをカスタマイズする Controllerの引数・戻り値のオブジェクトと
 JSONリクエスト・レスポンスは、
 Jacksonでシリアライズ・デシリアライズされる。 Jackson2ObjectMapperBuilderを
 戻すメソッドに@Beanをつけることで
 カスタマイズできる。 42
  • 43. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 5. Controllerの共通設定 @Bean public Jackson2ObjectMapperBuilder jacksonBuilder() { return Jackson2ObjectMapperBuilder.json() .indentOutput(true) .serializerByType(LocalDate.class, new JsonSerializer<LocalDate>() { @Override public void serialize(LocalDate value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { jgen.writeString(value.format(DATE_FORMATTER)); } }) .deserializerByType(LocalDate.class, new JsonDeserializer<LocalDate>() { @Override public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { return LocalDate.parse(jp.getValueAsString(), DATE_PARSER); } }) .modules(new JSR310Module()); } 43
  • 44. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 5. Controllerの共通設定 @Bean public Jackson2ObjectMapperBuilder jacksonBuilder() { return Jackson2ObjectMapperBuilder.json() .indentOutput(true) .serializerByType(LocalDate.class, new JsonSerializer<LocalDate>() { @Override public void serialize(LocalDate value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { jgen.writeString(value.format(DATE_FORMATTER)); } }) .deserializerByType(LocalDate.class, new JsonDeserializer<LocalDate>() { @Override public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { return LocalDate.parse(jp.getValueAsString(), DATE_PARSER); } }) .modules(new JSR310Module()); } 44 出力するJSONを 読みやすく LocalDateの
 シリアライズと
 デシリアライズ 他のJSR 310クラスも
 使えるようにしておく
  • 45. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 5. Controllerの共通設定 /** 日付フォーマット */ protected static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); /** 日付パースフォーマット */ protected static final DateTimeFormatter DATE_PARSER = DateTimeFormatter.ofPattern(“y[-][/]M[-][/]d"); 45
  • 46. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 5. Controllerの共通設定 /** 日付フォーマット */ protected static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); /** 日付パースフォーマット */ protected static final DateTimeFormatter DATE_PARSER = DateTimeFormatter.ofPattern(“y[-][/]M[-][/]d"); 入力は柔軟に、出力は厳格に。 46 フォーマット時は
 0埋め、
 ハイフン区切り パース時は
 0埋め、区切りを
 少し自由に
  • 47. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 47 #5 ControllerでLocalDateを
 使って日付判定ミスを防ぐ!
  • 48. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 48 #6
 トランザクション
 境界の設定
  • 49. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 6. トランザクション境界の設定 トランザクションあるある Controllerをトランザクション境界にする 処理の途中で一度コミットしたいけどできない 非同期処理呼び出しの前にコミットとか 途中でコミットできるような仕組みを
 無理に作ったら全体的な整合性が崩れた 性能改善のためのリードレプリカを作りたいが、
 そもそもアクセスを振り分けられない 49
  • 50. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 6. トランザクション境界の設定 Service層をトランザクション境界にする Controllerの次の層をトランザクション境界にする 処理の単位が明確になる Service層からreturnすればコミット、
 例外で戻ればロールバック。 Service層のクラスすべてに
 @Transactionalアノテーションをつける 50
  • 51. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 6. トランザクション境界の設定 原則、Read Onlyトランザクションを使う Service層のクラスすべてに
 @Transactional(readOnly = true) をつける Insert / Update / Deleteが発生する時だけ
 メソッドに @Transactional(readOnly = false) を
 つける ReadOnlyトランザクションだけを
 リードレプリカに振り分ける 51
  • 52. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 6. トランザクション境界の設定 @Service @Transactional(readOnly = true) public class EmployeeService { @Autowired protected EmployeeDao employeeDao; public Employee getEmployee(Integer id) { return employeeDao.selectById(id); } @Transactional(readOnly = false) public int createEmployee(Employee employee) { return employeeDao.insert(employee); } } 52
  • 53. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 6. トランザクション境界の設定 @Service @Transactional(readOnly = true) public class EmployeeService { @Autowired protected EmployeeDao employeeDao; public Employee getEmployee(Integer id) { return employeeDao.selectById(id); } @Transactional(readOnly = false) public int createEmployee(Employee employee) { return employeeDao.insert(employee); } } 53 クラスには
 readOnly = true 更新系メソッドに
 readOnly = false
  • 54. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 54 #6 ServiceクラスにRead Onlyな
 トランザクションを設けて
 将来に備える!
  • 55. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 55 #7
 O/Rマッパーの選択
  • 56. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 7. O/Rマッパーの選択 O/Rマッパーあるある とりあえずHibernate 思ったのと違うSQLが発行された 1リクエストでSQLが1万回発行された selectしたタイミングで一意制約違反が出た キャッシュが想定外の動きをした。 要するにハマる 56
  • 57. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 7. O/Rマッパーの選択 O/Rマッパーあるある じゃぁMyBatis Spring Bootで標準対応していない 1.3で標準対応されるかも https://github.com/spring-projects/spring-boot/pull/3692 SQLを書いたXMLをフォーマットしたら
 インデントが全部消えた > とか < のエスケープ 57
  • 58. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 7. O/Rマッパーの選択 O/Rマッパーあるある じゃぁJdbcTemplate なんかAPIが古くさい(Spring 2.0時代のAPI) publicフィールドが使えない JSR 310に対応していない 58
  • 59. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 59 そこで
 Bootiful SQL Template
  • 60. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 7. O/Rマッパーの選択 Bootiful SQL Template JdbcTemplate / NamedParameterJdbcTemplateの
 独自ラッパー SQLファイルを書ける(FreeMarker形式も可) モダンなAPI publicフィールドが使える JSR 310に対応(ZonedDateTimeにも) https://github.com/cero-t/sqltemplate 60
  • 61. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 7. O/Rマッパーの選択 @Autowired protected SqlTemplate sqlTemplate; public List<Employee> selectByCondition(EmployeeCondition condition) { return sqlTemplate.forList("sql/EmployeeDao/selectByCondition.sql", Employee.class, condition); } 61
  • 62. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 7. O/Rマッパーの選択 @Autowired protected SqlTemplate sqlTemplate; public List<Employee> selectByCondition(EmployeeCondition condition) { return sqlTemplate.forList("sql/EmployeeDao/selectByCondition.sql", Employee.class, condition); } 62 モダンでサクっと
 使えるAPI IntelliJなら
 Command(Ctrl) + クリックで
 SQLファイルにジャンプ
  • 63. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 7. O/Rマッパーの選択 SELECT * FROM emp WHERE 1 = 1 <#if name??> AND ename like '%' || :name || '%' </#if> <#if hiredateFrom??> AND :hiredateFrom < hiredate </#if> <#if hiredateTo??> AND hiredate < :hiredateTo </#if> <#if deptno??> AND deptno = :deptno </#if> 63
  • 64. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 7. O/Rマッパーの選択 SELECT * FROM emp WHERE 1 = 1 <#if name??> AND ename like '%' || :name || '%' </#if> <#if hiredateFrom??> AND :hiredateFrom < hiredate </#if> <#if hiredateTo??> AND hiredate < :hiredateTo </#if> <#if deptno??> AND deptno = :deptno </#if> 64 FreeMarker形式の
 テンプレートが利用可能
 
 ANDを自動的に消す機能が
 なくてごめんな
  • 65. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 65 #7 Bootiful SQL Templateで
 SQLを書いてハマり知らず
  • 66. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 66 #8
 例外処理の共通化
  • 67. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 例外処理あるある 個別の開発者任せ もちろん死ぬ フレームワークが返す例外(バリデーションなど)と、
 アプリケーションが返す例外でJSONの形式が違う クライアント側で判別に失敗して死ぬ 個別のエラーコードを定義しておいたので
 全部ソースコード内に書く 守らない人がいて死ぬ 67
  • 68. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 例外処理は共通化する ApplicationException extends RuntimeExceptionを 作って必ずこれを使う エラー種別をenumに定義しておき、
 ApplicationExceptionのコンストラクタの
 第一引数に必ず渡す エラー種別と、HTTPステータスやエラーコード、
 エラーメッセージを紐付けて管理する 68
  • 69. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 public class ApplicationException extends RuntimeException { Throwable cause; Object[] args; private HttpErrors error; public AppException(HttpErrors error, Throwable cause, String... args) { super(); this.error = error; this.args = args; this.cause = cause; } // その他のコンストラクタ、cause、args、errorのgetterは割愛 public String getMessage() { if (args != null) { return "[" + error.name() + "]" + MessageFormat.format(error.getMessage(), args); } return "[" + error.name() + "]" + error.getMessage(); } } 69
  • 70. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 public class ApplicationException extends RuntimeException { Throwable cause; Object[] args; private HttpErrors error; public AppException(HttpErrors error, Throwable cause, String... args) { super(); this.error = error; this.args = args; this.cause = cause; } // その他のコンストラクタ、cause、args、errorのgetterは割愛 public String getMessage() { if (args != null) { return "[" + error.name() + "]" + MessageFormat.format(error.getMessage(), args); } return "[" + error.name() + "]" + error.getMessage(); } } 70 第一引数で
 エラー種別を受け取る
  • 71. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 public interface HttpErrors { /** * HTTPステータスを取得します。 * @return HTTPステータス */ HttpStatus getStatus(); /** * メッセージを取得します。 * @return メッセージ */ String getMessage(); /** * エラー名を取得します。 * @return エラー名 */ String name(); } 71
  • 72. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 public enum Errors implements HttpErrors { USER_NOT_FOUND(HttpStatus.NOT_FOUND, "入力したIDに対応するユーザーが存在しません。userId={0}"), UNEXPECTED(HttpStatus.INTERNAL_SERVER_ERROR, "想定外のエラーが発生しました。 : {0}"); protected HttpStatus status; protected String message; Errors(HttpStatus status, String message) { this.status = status; this.message = message; } @Override public HttpStatus getStatus() { return status; } @Override public String getMessage() { return message; } } 72
  • 73. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 public enum Errors implements HttpErrors { USER_NOT_FOUND(HttpStatus.NOT_FOUND, "入力したIDに対応するユーザーが存在しません。userId={0}"), UNEXPECTED(HttpStatus.INTERNAL_SERVER_ERROR, "想定外のエラーが発生しました。 : {0}"); protected HttpStatus status; protected String message; Errors(HttpStatus status, String message) { this.status = status; this.message = message; } @Override public HttpStatus getStatus() { return status; } @Override public String getMessage() { return message; } } 73 エラーを列挙
  • 74. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 例外処理ハンドリングも共通化する ApplicationExceptionと
 RuntimeExceptionと
 フレームワークが返す例外で
 すべて同じ例外ハンドリングをする 74
  • 75. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 @ControllerAdvice public class ControllerExceptionHandler extends ResponseEntityExceptionHandler { /** ロガー */ protected final Log logger = LogFactory.getLog(getClass()); @ExceptionHandler(value = ApplicationException.class) @ResponseBody public ResponseEntity<RestError> handleAppException(HttpServletRequest request, ApplicationException ex) { return handleError(request, ex.getError(), ex, ex.getArgs()); } @ExceptionHandler(value = RuntimeException.class) @ResponseBody public ResponseEntity<RestError> handleException(HttpServletRequest request, RuntimeException ex) { return handleError(request, Errors.UNEXPECTED, ex, ex.toString()); } 75
  • 76. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 @ControllerAdvice public class ControllerExceptionHandler extends ResponseEntityExceptionHandler { /** ロガー */ protected final Log logger = LogFactory.getLog(getClass()); @ExceptionHandler(value = ApplicationException.class) @ResponseBody public ResponseEntity<RestError> handleAppException(HttpServletRequest request, ApplicationException ex) { return handleError(request, ex.getError(), ex, ex.getArgs()); } @ExceptionHandler(value = RuntimeException.class) @ResponseBody public ResponseEntity<RestError> handleException(HttpServletRequest request, RuntimeException ex) { return handleError(request, Errors.UNEXPECTED, ex, ex.toString()); } 76 独自のApplicationExceptionと
 想定しないRuntimeExceptionの両方を
 同じ方式でハンドリング
  • 77. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 protected ResponseEntity<RestError> handleError(HttpServletRequest request, HttpErrors error, Exception ex, Object... args) { String message = MessageFormat.format(error.getMessage(), args); if (error.getStatus() == HttpStatus.INTERNAL_SERVER_ERROR) { logger.error(message, ex); } else { logger.debug(message, ex); } if (error.getStatus() == HttpStatus.UNAUTHORIZED) { return new ResponseEntity<>(error.getStatus()); } RestError restError = new RestError(); restError.path = request.getRequestURI(); restError.error = error.name(); restError.status = error.getStatus() .value(); restError.message = message; restError.exception = ex.getClass() .getName(); return new ResponseEntity<>(restError, error.getStatus()); } 77
  • 78. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 protected ResponseEntity<RestError> handleError(HttpServletRequest request, HttpErrors error, Exception ex, Object... args) { String message = MessageFormat.format(error.getMessage(), args); if (error.getStatus() == HttpStatus.INTERNAL_SERVER_ERROR) { logger.error(message, ex); } else { logger.debug(message, ex); } if (error.getStatus() == HttpStatus.UNAUTHORIZED) { return new ResponseEntity<>(error.getStatus()); } RestError restError = new RestError(); restError.path = request.getRequestURI(); restError.error = error.name(); restError.status = error.getStatus() .value(); restError.message = message; restError.exception = ex.getClass() .getName(); return new ResponseEntity<>(restError, error.getStatus()); } 78 例外オブジェクトへの変換
  • 79. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 @Override protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request) { RestError restError = new RestError(); if (request instanceof ServletWebRequest) { restError.path = ((ServletWebRequest) request).getRequest() .getRequestURI(); } else { restError.path = request.getContextPath(); } restError.error = status.getReasonPhrase(); restError.status = status.value(); restError.message = ex.getMessage(); restError.exception = ex.getClass() .getName(); return new ResponseEntity<>(restError, status); } } 79
  • 80. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8. 例外処理の共通化 @Override protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request) { RestError restError = new RestError(); if (request instanceof ServletWebRequest) { restError.path = ((ServletWebRequest) request).getRequest() .getRequestURI(); } else { restError.path = request.getContextPath(); } restError.error = status.getReasonPhrase(); restError.status = status.value(); restError.message = ex.getMessage(); restError.exception = ex.getClass() .getName(); return new ResponseEntity<>(restError, status); } } 80 このオーバーライドで
 Spring MVCが投げる例外を
 ハンドリングできる
  • 81. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 81 #8 すべての例外を共通して
 ハンドリングせよ!
  • 82. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 82 #9
 AOPによるロギング
  • 83. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 9. AOPによるロギング AOPとは アプリケーション横断的に行う処理 トランザクションのコミットやロールバックもAOPで実現されている オススメは、AOPによる自動ロギング Controller / Service / DaoのIn/Outでロギング デバッグ時に、アプリケーションの挙動がとてもよく分かる ログレベルに応じて引数、戻り値なども出す SpringではXMLやアノテーションでAOPの対象を記述することができる 正直、アノテーションの記述はイマイチ。分かりづらい。 記述性はGuice > Seasar > Spring。 83
  • 84. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 9. AOPによるロギング @Aspect @Component public class DumpLogInterceptor { protected Logger logger = LoggerFactory.getLogger(getClass()); @Around("execution(* ninja.cero.springboot..*.*(..)) && (bean(*Controller) || bean(*Service) || bean(*Dao))") public Object dump(ProceedingJoinPoint joinPoint) throws Throwable { try { logger.debug("BEGIN - " + toCall(joinPoint)); logger.trace("with args - " + ToStringBuilder.reflectionToString(joinPoint.getArgs(), ToStringStyle.SHORT_PREFIX_STYLE)); Object retValue = joinPoint.proceed(joinPoint.getArgs()); logger.debug("END - " + toCall(joinPoint)); logger.trace( "with return - " + ToStringBuilder.reflectionToString(retValue, ToStringStyle.SHORT_PREFIX_STYLE)); return retValue; } catch (Throwable th) { logger.debug("END throw - " + toCall(joinPoint)); logger.debug("Exception: " + th); throw th; } } } 84
  • 85. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 9. AOPによるロギング @Aspect @Component public class DumpLogInterceptor { protected Logger logger = LoggerFactory.getLogger(getClass()); @Around("execution(* ninja.cero.springboot..*.*(..)) && (bean(*Controller) || bean(*Service) || bean(*Dao))") public Object dump(ProceedingJoinPoint joinPoint) throws Throwable { try { logger.debug("BEGIN - " + toCall(joinPoint)); logger.trace("with args - " + ToStringBuilder.reflectionToString(joinPoint.getArgs(), ToStringStyle.SHORT_PREFIX_STYLE)); Object retValue = joinPoint.proceed(joinPoint.getArgs()); logger.debug("END - " + toCall(joinPoint)); logger.trace( "with return - " + ToStringBuilder.reflectionToString(retValue, ToStringStyle.SHORT_PREFIX_STYLE)); return retValue; } catch (Throwable th) { logger.debug("END throw - " + toCall(joinPoint)); logger.debug("Exception: " + th); throw th; } } } 85 この記述でController / Service
 Daoの実行前後に処理を差し込む
  • 86. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 86 #9 AOPによるロギングで
 問題発生時のリカバリを
 高速化しよう
  • 87. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 87 #10
 テスト設計
  • 88. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 テストあるある とりあえず、手動でテストしようぜ!
  → 回帰試験で死ぬ。 ロジックがあるControllerからテストすればOK!
  → バリデーションの設定ミスで死ぬ。 通常使うComponentとモックのComponentは
 @Profileで切り替えるのがSpring流!
  → 管理できなくなってきて死ぬ。 Spring Bootはend-to-endでテストしやすいから
 end-to-endのテストでカバレッジ80%を目指そう!
  → そして死ぬ。 88
  • 89. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 テストのグッドプラクティス Controller以降をJUnitでテストする。 カバレッジは最低60%、できれば80%を目指す。 外部サービス呼び出し部分は、モック化する(後述) 例外を任意で発生させたい場合も、モック化すると良い。 無名クラスを活用したモックを作れるようになろう。 end-to-endのJUnitを書いて、
 正常系1本とバリデーション部分をテストする。 JUnitのテストクラスに @IntegrationTest(“server.port=0”) をつけ、 RestTemplateを用いてテストする。 バリデーションの試験は、end-to-endでしかできない。 89
  • 90. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = {BlankWeb.class, TestContextConfig.class}) @Transactional public class EmployeesControllerTest { @Autowired EmployeesController controller; @Test public void testGetAll() { List<EmployeesOut> employees = controller.getEmployees(); // TODO: assert } 90
  • 91. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = {BlankWeb.class, TestContextConfig.class}) @Transactional public class EmployeesControllerTest { @Autowired EmployeesController controller; @Test public void testGetAll() { List<EmployeesOut> employees = controller.getEmployees(); // TODO: assert } 91 テストの時に必ずつけるアノテーション。 トランザクションを有効にして
 試験が終わったら自動でロールバック。 TestContextConfigはあとで。
  • 92. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = {BlankWeb.class, TestContextConfig.class}) @WebAppConfiguration @IntegrationTest("server.port=0") @Transactional public class EmployeesTest { @Value("http://localhost:${local.server.port}/employees") String baseUrl; @Autowired RestTemplate restTemplate; @Test public void testGetList() { ResponseEntity<List> out = restTemplate.getForEntity(baseUrl, List.class); // TODO: assert } 92
  • 93. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = {BlankWeb.class, TestContextConfig.class}) @WebAppConfiguration @IntegrationTest("server.port=0") @Transactional public class EmployeesTest { @Value("http://localhost:${local.server.port}/employees") String baseUrl; @Autowired RestTemplate restTemplate; @Test public void testGetList() { ResponseEntity<List> out = restTemplate.getForEntity(baseUrl, List.class); // TODO: assert } 93 @WebAppConfigurationと
 @IntegrationTestをつけて
 Tomcatを起動 RestTemplateでアクセス URLを設定
  • 94. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 テストのTips schema.sqlとdata.sqlでデータ投入する /src/test/resources にschema.sqlとdata.sqlを
 置いておけば、JUnitの起動前にのみ実行される。 /src/main/resources に置いておけば
 通常起動時に実行される(動作確認向け) 事故ってproduction環境で動かさないように! Controllerのテストと、end-to-endのテストは同じapplication.ymlでテストする end-to-endの試験も自動化するため。 end-to-endのテストは、ついつい範囲を広げたくなるが
 自動化する試験と、そうでない試験は分けるべき。 94
  • 95. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 テストのTips @Componentのモックは、
 @Profileよりも@Primaryをつけた方が良い 外部サービスの呼び出しなどをモック化する場合、
 モック化したい部分を @Autowired にしておく。 モッククラスを /src/test/java 以下で作成し、
 @Component (@Bean) と@Primaryアノテーションを
 つければ、JUnit実行時のみ利用される。 95
  • 96. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 public interface Context { /** * セッションIDを取得します。 * @return セッションID */ String getSessionId(); } 96 本体コード側にある
 インタフェース。
  • 97. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 public class RequestContext implements Context { protected HttpServletRequest request; public RequestContext(HttpServletRequest request) { this.request = request; } @Override public String getSessionId() { return request.getSession().getId(); } } 97 本体コード側にある実装。
 HttpServletRequestを使っているので
 JUnit時にはエラーが起きる
  • 98. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 @Configuration public class TestContextConfig { @Bean @Primary public Context context() { return new Context() { @Override public String getSessionId() { return "JUNIT"; } }; } } 98
  • 99. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 @Configuration public class TestContextConfig { @Bean @Primary public Context context() { return new Context() { @Override public String getSessionId() { return "JUNIT"; } }; } } 99 テスト側の設定クラス。 ここに@Primaryを書けば
 このコンポーネントが
 優先して使われる。
  • 100. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = {BlankWeb.class, TestContextConfig.class}) @Transactional public class EmployeesControllerTest { @Autowired EmployeesController controller; @Test public void testGetAll() { List<EmployeesOut> employees = controller.getEmployees(); // TODO: assert } 100
  • 101. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = {BlankWeb.class, TestContextConfig.class}) @Transactional public class EmployeesControllerTest { @Autowired EmployeesController controller; @Test public void testGetAll() { List<EmployeesOut> employees = controller.getEmployees(); // TODO: assert } 101 テスト側で、先ほど書いた
 Configurationを明示的に読み込む
  • 102. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10. テスト設計 テストのTips /src/test/java 側に作ったテスト用の
 @Primary つき@Component (@Bean) は
 end-to-endのサーバ側にも適用されるので
 サーバ側でもモックを使いやすい たぶんこれ相当便利。 102
  • 103. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 103 まとめ
  • 104. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 104 スライド読み直せ!
  • 105. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 105 One more thing…
  • 106. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 106 今日紹介したソースは
 GitHubで公開中!
  • 107. Copyright © Acroquest Technology Co., Ltd. All rights reserved.Copyright © Acroquest Technology Co., Ltd. All rights reserved. 107 https://github.com/cero-t/ spring-boot-kinoko-2015
  • 108. Copyright © Acroquest Technology Co., Ltd. All rights reserved. 108 Enjoy Spring Boot!