spring bootで変わる javaアプリ開発! #jsug

Post on 10-May-2015

19.264 Views

Category:

Technology

13 Downloads

Preview:

Click to see full reader

DESCRIPTION

Spring Boot

TRANSCRIPT

Spring Bootで変わる Javaアプリ開発!日本Springユーザ会 勉強会 ~やっぱりSpringを始めよう!

2014/08/13 槙 俊明(@making)

ハッシュタグ #jsug

自己紹介• @making • http://blog.ik.am • 日本Javaユーザーグループ(JJUG)幹事 • Spring Boot本書いています

http://amzn.to/hajiboo

地味にSpring Boot Contributor

JJUG CCC 2014 Fall

http://www.java-users.jp/?p=12532014/11/15(土)

2014/09/30までCall for Paper募集中! Springネタを是非お待ちしております!

http://www.slideshare.net/makingx/spring-4spring-boot-spring-jjug-jsug

http://www.slideshare.net/makingx/grails-30-spring-boot

今日のコンテンツ

1. Spring Boot概要 2. Spring Bootで何が変わる?

•アプリの設定が変わる •アプリのデプロイも変わる •システムのアーキテクチャも変わる?

Spring Boot概要

Spring Bootとは?

フレームワークというよりプラットフォーム

現在1.1.5.RELEASE

簡単に言うと、Spring Frameworkでアプリケーションを簡単に作る

ための仕組み

Spring Bootを使うことで・・

モダンでいけてるJavaアプリケーションを 簡単に構築できる

Spring Bootの特徴•あらかじめオススメの組み合わせが決まる

•依存ライブラリを同梱するだけで自動で設定が決まる

•組み込みサーバーを同梱し、アプリを即実行可能 アプリケーション自体は

Spring MVCやSpring Batchで書く

Spring BootはDropwizard にインスパイアされた

Dropwizardに比べてSpring Bootがいいところ

•これまでのSpring Frameworkのノウハウがそのまま活かせる

•Spring Frameworkの開発元が開発している

•チュートリアル・サンプル・ドキュメントが充実している

チュートリアルが豊富• http://spring.io/guides

70種類以上の簡易チュートリアル

サンプルが豊富• https://github.com/spring-projects/spring-boot/tree/

master/spring-boot-samples

40種類以上のサンプルプロジェクト

Technology Radar July2014http://thoughtworks.fileburst.com/assets/technology-radar-july-2014-en.pdf

Spring BootでHello World

Mavenアーキタイプでプロジェクト雛形生成

$ mvn -B archetype:generate -DgroupId=com.example -DartifactId=jsug-helloworld -Dversion=1.0.0-SNAPSHOT -DarchetypeArtifactId=maven-archetype-quickstart

Spring Bootに関係のない汎用的な手順

pom.xmlを編集

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.1.5.RELEASE</version></parent><dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency></dependencies><build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins></build><properties> <java.version>1.8</java.version></properties>

この設定を追加するだけ

インポート後

いろいろな依存関係が追加されている

package com.example;!import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;!@RestController@EnableAutoConfigurationpublic class App {! @RequestMapping("/") String home() { return "Hello World!"; }! public static void main(String[] args) { SpringApplication.run(App.class, args); }}

魔法のアノテーション

mainメソッドでアプリ実行

まずは実行•実行方法は2通り

または

$ mvn spring-boot:run

$ gradle bootRun Gradleの場合

ログ

組込Tomcatが起動した

http://localhost:8080 にアクセス

実行可能jarを作成

$ mvn package

jarを実行

$ java -jar target/jggug-helloworld-1.0.0-SNAPSHOT.jar

プロパティを変更して実行

$ java -jar target/jggug-helloworld-1.0.0-SNAPSHOT.jar --server.port=8888

--(プロパティ名)=(プロパティ値)

予め用意されている沢山のプロパティを変更可能

• http://docs.spring.io/spring-boot/docs/1.1.4.RELEASE/reference/html/common-application-properties.html

一度作ったjarはそのまま本番環境で使用可能。配布も可能。

Spring Bootで何が変わる?

Spring Bootで何が変わる?

•アプリの設定が変わる

•アプリのデプロイが変わる

Spring Bootで何が変わる?

•アプリの設定が変わる

•アプリのデプロイが変わる

ほとんど設定不要!

Spring Bootで何が変わる?

•アプリの設定が変わる

•アプリのデプロイが変わる

ほとんど設定不要!

jarを実行するだけ!

アプリの設定が変わる

AutoConfigure• 自動でいい感じの設定が行われる仕組み

• @EnableAutoConfigurationで自動設定が有効化

• ポイントは@Conditionalアノテーション

AutoConfigureの説明の前に ベースとなるJavaConfigの説明

package com.example;!import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;!@Configurationpublic class AppConfig {! @Bean SomeBean someBean() { returen new SomeBean(); }}

JavaConfigの記法 com.example.AppConfig

JavaConfig宣言

Bean定義宣言

@Conditionalpackage com.example;!import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;!@Configuration@ConditionalOnClass({SomeBean.class})public class AppConfig {! @Bean SomeBean someBean() { returen new SomeBean(); }}

クラスパス上にSomeBeanが存在した場合にこのBean定義が有効

SomeBeanを含むライブラリ(jar)を追加するだけで有効になる!

Autoconfigureを支える@Conditional

@ConditionalOnBean 指定したクラスの有効

@ConditionalOnClass 指定したクラスがクラスパス上にあれば有効@ConditionalOnMissingBean

指定したクラスのば有効

@ConditionalOnMissingClass 指定したクラスがクラスパス上にあれば有効

@ConditionalOnProperty

指定したプロパティが指定した値であれば有効@ConditionalOnExpression

指定した等。 org.springframework.boot.autoconfigure.condition以下を参照

初めからサポートされているAutoconfigure

初めからサポートされているAutoconfigure

•Spring AMQP(RabitMQ) •Spring Batch •Spring Data •Spring HATEOAS •Spring Integration •Spring Mobile •Spring Security •Spring Social •Tomcat •Jetty

•ThymeLeaf •JPA •JMS •WebSocket •Solr •ElasticSearch •MongoDB •Redis •Liquibase •Flyway

など

Starter• 使いたい機能のAutoConfigureを有効にするための、依存関係を定義したMavenプロジェクト(pom)

https://github.com/spring-projects/spring-boot/tree/master/spring-boot-starters

30種類以上のstarterプロジェクト

!<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId></dependency>

spring-boot-starter-data-jpaを追加するだけ。

[例] Spring Data JPAを使いたい

必要な依存関係が追加される

👉 AutoConfigureの中をのぞこう

@Configuration@ConditionalOnBean(DataSource.class)@ConditionalOnClass(JpaRepository.class)@ConditionalOnMissingBean(RepositoryFactoryBeanSupport.class)@ConditionalOnExpression("${spring.data.jpa.repositories.enabled:true}")@Import(JpaRepositoriesAutoConfigureRegistrar.class)@AutoConfigureAfter(HibernateJpaAutoConfiguration.class)public class JpaRepositoriesAutoConfiguration { @Configuration @EnableSpringDataWebSupport @ConditionalOnWebApplication @ConditionalOnMissingBean(PageableHandlerMethodArgumentResolver.class) protected static class JpaWebConfiguration { }}

DataSourceが出来ていてJpaRepositoryクラスが存在

各種条件が揃ったら有効

別の定義をimport

@EnableConfigurationProperties(JpaProperties.class)@Import(DataSourceInitializedPublisher.Registrar.class)public abstract class JpaBaseConfiguration implements BeanFactoryAware {! // ... @Bean @ConditionalOnMissingBean public EntityManagerFactoryBuilder entityManagerFactoryBuilder( JpaVendorAdapter jpaVendorAdapter) { EntityManagerFactoryBuilder builder = new EntityManagerFactoryBuilder( jpaVendorAdapter, this.jpaProperties, this.persistenceUnitManager); builder.setCallback(getVendorCallback()); return builder; } @Bean @Primary @ConditionalOnMissingBean public LocalContainerEntityManagerFactoryBean entityManagerFactory( EntityManagerFactoryBuilder factory) { return factory.dataSource(this.dataSource).packages(getPackagesToScan()) .properties(getVendorProperties()).build(); }}

HibernateJpaAutoConfigurationの親クラス

EntityManagerFactoryの生成

@Configuration@ConditionalOnWebApplication@ConditionalOnMissingBean({ OpenEntityManagerInViewInterceptor.class, OpenEntityManagerInViewFilter.class })@ConditionalOnExpression("${spring.jpa.openInView:${spring.jpa.open_in_view:true}}")protected static class JpaWebConfiguration extends WebMvcConfigurerAdapter { // ...! @Bean public OpenEntityManagerInViewInterceptor openEntityManagerInViewInterceptor() { return new OpenEntityManagerInViewInterceptor(); }}

Open Session In Viewパターンがデフォルトで適用されている = Springのオススメパターン?

@EnableAutoConfiguration

package com.example;!import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.context.annotation.ComponentScan;!@EnableAutoConfiguration@ComponentScanpublic class App {! public static void main(String[] args) { SpringApplication.run(App.class, args); }}

エントリポイントに@EnableAutoConfigurationをつけると

自動設定が有効になる

@Service@Transactionalpublic class BookmarkService { @Autowired BookmarkRepository bookmarkRepository;! public List<Bookmark> findAll() { return bookmarkRepository.findAll(new Sort(Sort.Direction.ASC, "id")); }! public Bookmark save(Bookmark bookmark) { return bookmarkRepository.save(bookmark); }! public void delete(Long id) { bookmarkRepository.delete(id); }}

public interface BookmarkRepository extends JpaRepository<Bookmark, Long> {!}

特別な設定なしでSpring Data JPAが使える。特別な設定なしでSpring Data JPAが使える。

ハンズオンで作ったアプリ設定なしでREST API

を作れる!

AutoConfigureは黒魔術ではない

org.springframework.boot.autoconfigureパッケージのソースを読めば、 何が設定されるか分かる。

通常はマニュアル読めばよい。

使いたい機能が合った場合(いままで)

1.必要なライブラリ群の依存関係(通常複数)を追加

2.ライブラリを使うために必要な設定を追加

3.アプリケーションからライブラリを使用する

使いたい機能が合った場合(いままで)

1.必要なライブラリ群の依存関係(通常複数)を追加

2.ライブラリを使うために必要な設定を追加

3.アプリケーションからライブラリを使用する

autoconfigureで不要

starterだけでOK

ここに注力できる

使いたい機能が合った場合(これから)

1.必要なライブラリのstarterを追加

2.ライブラリを使うために必要な設定を追加

3.アプリケーションからライブラリを使用する

例1: 「Spring Social Twitter」を使ってつぶやく

HelloWorldアプリから10数行だけコードを足して、OAuth認可後、

Twitterへツイートできるようにする。

!<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-social-twitter</artifactId></dependency>

HelloWorldアプリから10数行だけコードを足して、OAuth認可後、Twitterへツイートできるようにする。

例1: 「Spring Social Twitter」を使ってつぶやく

starterを追加

@RestController@EnableAutoConfigurationpublic class App { @Autowired ConnectionRepository connectionReposiory; @Autowired Twitter twitter;! @RequestMapping("/") String home(@RequestParam("tweet") String tweet) { if (connectionRepository.findPrimaryConnection(Twitter.class) == null) { return "<a href='/connect/twitter'>Please connect</a>"; } twitter.timelineOperations().updateStatus(tweet); return tweet + " is tweeted!"; }! public static void main(String[] args) { SpringApplication.run(App.class, args); }}

App.java編集

アプリケーション登録https://dev.twitter.com/

APIキーの設定

spring.social.twitter: app-id: 3b6ZO4iF4AG08P62OVFWlVxEP app-secret: 2IdbPGbLjwsCw6prcPNumrQlV07uMKi4hseQoShaeJl51xEEkAspring.social.auto-connection-views: true

コネクション用の画面を自動生成

application.yml

Appを実行

ツイート

例2: DBマイグレーションライブラリ「FlyWay」を使ってみる

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency> <groupId>org.hsqldb</groupId> <artifactId>hsqldb</artifactId> <scope>runtime</scope></dependency><dependency> <groupId>org.flywaydb</groupId> <artifactId>flyway-core</artifactId></dependency>

ライブラリを追加するだけでAutoConfigureが有効に

あとは所定の位置にSQLを書くだけ

spring.jpa.hibernate.ddl-auto: validate

CREATE TABLE PERSON ( id BIGINT GENERATED BY DEFAULT AS IDENTITY, first_name varchar(255) not null, last_name varchar(255) not null);!insert into PERSON (first_name, last_name) values ('Dave', 'Syer');

現在適用されているSQLのバージョンを確認して、必要なSQLを自動で実行

DDLの実行はFlywayに任せるために、JPAの機能を抑制

Spring Bootの対象は Webアプリだけではない

•バッチ処理

•システム連携

• Hadoop YARN

説明量が増えすぎたので 今日はカット😢

アプリのデプロイが変わる

これまでのデプロイ(開発)

1.コードを書く/修正する

2.(アプリケーションをビルドする) <= IDEが自動で行う

3.IDEのプラグインでAPサーバーを起動する

4.IDEのプラグインでAPサーバー上でアプリケーションを実行する

これまでのデプロイ(本番)1.コードを書く/修正する

2.Ant/Maven/Gradleなどでアプリケーションをビルドしてwarを作成する

3.APサーバーを起動する

4.APサーバーにwarをデプロイする(warを所定の場所に配置する)

Spring Bootのデプロイ(開発)

1.コードを書く/修正する

2.(アプリケーションをビルドする) <= IDEが自動で行う

3.mainメソッド実行する

Spring Bootのデプロイ(本番)

1.コードを書く/修正する

2.Maven/Grandleでビルドして実行可能jarを作成する

3.jarを所定のフォルダにcpする

4.jarを実行する

Spring Bootの基本パターン

実行可能jarを作って実行。 プロパティは外から変える。

一度作ったjarはどこでも使えてポータブル!

アプリケーションの更新

新しいjarをcpするだけ。

JenkinsやGitbucketと同じ!

起動スクリプト(RedHat系)# 途中略case "$1" in start) echo -n "Starting MyApp " nohup java $JVM_OPTS -jar $MYAPP_HOME/myapp.jar $PARAMS >> $LOG_FILE 2>&1 & pid=$! echo $pid > "$MYAPP_PID_FILE" success echo ;; stop) echo -n "Shutting down MyApp " killproc myapp RETVAL=$? echo ;; *) echo "Usage: $0 {start|stop}" exit 1 ;;esac

/etc/init.d/myapp start /etc/init.d/myapp stop

ポータビリティはPaaSフレンドリ

Spring Bootで作ったWebアプリはHerokuやCloud Foundryへ簡単にデプロイできる

Immutable/Disposable Infrastructureと相性が良い。Dockerとか。

Herokuにデプロイ

web: java $JAVA_OPTS -jar target/*.jar --server.port=$PORT

プロジェクト直下のProcfileに以下を記述

$ heroku create$ git push heroku masterでHerokuへデプロイ!

Herokuとローカルで DBを動的に切り替えたい場合

@Bean(destroyMethod = "close")DataSource dataSource() throws URISyntaxException { String url, username, password; String databaseUrl = System.getenv("DATABASE_URL"); if (databaseUrl != null) { URI dbUri = new URI(databaseUrl); url = "jdbc:postgresql://" + dbUri.getHost() + dbUri.getPath() + ":" + dbUri.getPort() + dbUri.getPath(); username = dbUri.getUserInfo().split(":")[0]; password = dbUri.getUserInfo().split(":")[1]; } else { url = this.properties.getUrl(); username = this.properties.getUsername(); password = this.properties.getPassword(); } DataSourceBuilder factory = DataSourceBuilder .create(this.properties.getClassLoader()) .url(url) .username(username) .password(password); return factory.build();}

Herokuでは環境変数DATABASE_URLにDB情報

が含まれる

Herokuの場合

ローカルの場合

Spring Cloudというサブプロジェクトを使うとこのへんを吸収できる

Herokuとローカルで DBを動的に切り替えたい場合

spring: profle: active: dev jpa.hibernate.ddl-auto: update---spring: profiles: dev datasource: driverClassName: org.h2.Driver url: jdbc:h2:file:/tmp/bookmark username: sa password: jpa.database: H2---spring: profiles: heroku datasource: driverClassName: org.postgresql.Driver jpa.database: POSTGRESQL

Profile毎にYAMLで設定可能 デフォルトでdevを指定

Herokuの場合 PostgreSQLを使用する

ローカル(dev)の場合 H2データベースを使用する

application.yml

profile毎のファイルを 作成することも可能

実行時にProfile指定

web: java $JAVA_OPTS -jar target/*.jar —server.port=$PORT --spring.profiles.active=heroku

Procfileに--spring.profiles.activeでherokuプロファイルを指定

ちなみにこれはBoot以前からある機能。 YAMLもSpring4.1から本体に取り込まれる。

Heroku Button

Github上のアプリを「ボタンぽち」で Herokuにデプロイできる仕組み

[![Deploy](https://www.herokucdn.com/deploy/button.png)](https://heroku.com/deploy)

README.mdにボタンのリンクを貼るだけ

Spring Bootなら簡単

Procfileと app.jsonを用意

{ "name": "Bookmark Application", "description": “Handson Application"}

app.json

http://bit.ly/jsug-heroku

Spring Bootなら簡単

Procfileと app.jsonを用意

{ "name": "Bookmark Application", "description": “Handson Application"}

app.json

ぽち

http://bit.ly/jsug-heroku

ブランチを自動で判断

ぽち

ブランチを自動で判断

2~3分

2~3分

アプリの配布も変わる?

Spring Bootでアプリを作成して、 Githubで管理し、

Heroku Buttonを配置

アプリの配布も変わる?

Spring Bootでアプリを作成して、 Githubで管理し、

Heroku Buttonを配置

アプリを即座にDeploy & Tryできる!

(PaaS上の)アプリの状態を知りたい

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId></dependency>

Spring Boot Actuator

(PaaS上の)アプリの状態を知りたい

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId></dependency>

Spring Boot Actuator

依存関係を追加するだけで、アプリの情報やメトリクスを取得するためのエンド

ポイントが公開される

JSONで取得できる情報

http://docs.spring.io/spring-boot/docs/1.1.5.RELEASE/reference/html/production-ready-endpoints.html

パス 取得内容

/metricsアクセスカウンタやレスポンスタイム、JVM

/health 各種データソースのヘルスチェック/dump スレッドダンプ/configprops プロパティ/env 環境変数

Actuator用のAutoconfigure対応サードパーティ

• CRaSH (SSHサポート) • Jolokia (JMXをJSONで出力) • CodaHale Metrics (さらなるメトリクス)

システムアーキテクチャも 変わる?

伝統的なアーキテクチャ

http://www.infoq.com/articles/microservices-intro より図を拝借

モノリシックアーキテクチャ

伝統的なアーキテクチャ

http://www.infoq.com/articles/microservices-intro より図を拝借

モノリシックアーキテクチャ

システムが大きくなると、全体を把握するのが大変で、保守が難しい。

伝統的なアーキテクチャ

http://www.infoq.com/articles/microservices-intro より図を拝借

モノリシックアーキテクチャ

システムが大きくなると、全体を把握するのが大変で、保守が難しい。

技術の変更は難しい(リスキーd)

伝統的なアーキテクチャ

http://www.infoq.com/articles/microservices-intro より図を拝借

モノリシックアーキテクチャ

システムが大きくなると、全体を把握するのが大変で、保守が難しい。

技術の変更は難しい(リスキーd)

技術的に発展的成長が難しいアーキテクチャ

マイクロサービスアーキテクチャ

http://www.infoq.com/articles/microservices-intro より図を拝借

Single Responsibility Principle (SRP) に基づき名詞や動詞単位でサービスを分割

マイクロサービスアーキテクチャ

http://www.infoq.com/articles/microservices-intro より図を拝借

Single Responsibility Principle (SRP) に基づき名詞や動詞単位でサービスを分割

HTT

PやAM

QPで通信

マイクロサービスアーキテクチャ

http://www.infoq.com/articles/microservices-intro より図を拝借

Single Responsibility Principle (SRP) に基づき名詞や動詞単位でサービスを分割

HTT

PやAM

QPで通信

Amazon Netfilx eBay

などが採用

マイクロサービスアーキテクチャ

http://www.infoq.com/articles/microservices-intro より図を拝借

Single Responsibility Principle (SRP) に基づき名詞や動詞単位でサービスを分割

HTT

PやAM

QPで通信 これまで説明

してきたSpring Bootの機能が効く!

Amazon Netfilx eBay

などが採用

マイクロサービスアーキテクチャの メリット・デメリット

メリット デメリット自担当のサービスのコードを

理解しやすい システム全体を見なくなる

新しい技術を採用しやすい・失敗してもやり直しやすい

分散システムの整合をとるのが難しい

サービス単位でスケールできる サービス間の通信オーバーヘッドがある

1ーク等

他サービスの障害をふまえた設計が必要

IDE

マイクロサービスアーキテクチャの メリット・デメリット

メリット デメリット自担当のサービスのコードを

理解しやすい システム全体を見なくなる

新しい技術を採用しやすい・失敗してもやり直しやすい

分散システムの整合をとるのが難しい

サービス単位でスケールできる サービス間の通信オーバーヘッドがある

1ーク等

他サービスの障害をふまえた設計が必要

IDE 銀の弾丸ではない

続きはWebでhttp://www.infoq.com/minibooks/emag-microservices

まとめアプリの設定が変わる • Autoconfigureで自動設定 • Starterで依存関係解決 アプリのデプロイが変わる • 実行可能jar + 外部プロパティ • Herokuボタン システムアーキテクチャも変わる? • モノリシックアーキテクチャ • マイクロサービスアーキテクチャ

まとめアプリの設定が変わる • Autoconfigureで自動設定 • Starterで依存関係解決 アプリのデプロイが変わる • 実行可能jar + 外部プロパティ • Herokuボタン システムアーキテクチャも変わる? • モノリシックアーキテクチャ • マイクロサービスアーキテクチャ

_人人人人人人人人人人人人人人_ > SIerの皆様は使えないかも <  ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄

最後に

これからのレガシーJavaアプリ

•JSP •web.xml •src/main/webapp

使ったら負け!

移行の際の注意

• Bean定義ファイルの内容を”そのまま移植”してはいけない

• JSP、warなど踏襲してはいけない

Grails3のベースにもなるhttp://www.slideshare.net/danveloper/future-of-grails

Scala、Kotlinでも普通に使えます

https://github.com/making/jggug-workshop-springboot/tree/bookmark-scala

https://github.com/making/spring-boot-demo-jvm-languages

色々なJVM言語でHello World

ハンズオンアプリのScala版

まずはハンズオンから

Webブラウザ

curl

TomcatSpring Boot

Spring FrameworkSpring Security

ThymeLeaf

Spring MVC

Jackson

Spring Data JPA

Hibernate

H2 Database画面のあるアプリ

REST API

http://www.slideshare.net/makingx/grails-30-spring-boot

ご清聴有り難うございました

Spring Boot本出版されたら買ってください!

top related