Spring Boot キャンプハンズオンに参加してきた! #kanjava_sbc

【脱初心者】Spring Bootキャンプ【ハンズオン】 - connpass

ついていけない人は置いてくよ、ってどんどん進んで、ついていくのに必死で楽しかった!全然知らないことばっかりで、そういうの久しぶりだったなー。すごく濃い2時間でした。

Dockerまでは行けなかったので宿題ということになりました。落ち着いたらやってみよっと。

できあがったもの↓

復習もかねて思い出しつつ、垂れ流ししてみる。

資料

これがすごい。ありがとうございます。
Spring Bootキャンプ ハンズオン資料 — Spring Bootキャンプ ハンズオン資料 1.0.0-SNAPSHOT ドキュメント

僕は当日、理解することを捨てて、分かった気になることにしました。(え

当日のスライドもアップされてます。

1. [事前準備] Spring BootでHello World — Spring Bootキャンプ ハンズオン資料 1.0.0-SNAPSHOT ドキュメント

プロジェクト作成

$ mvn archetype:generate -B\
 -DarchetypeGroupId=am.ik.archetype\
 -DarchetypeArtifactId=spring-boot-docker-blank-archetype\
 -DarchetypeVersion=1.0.2\
 -DgroupId=kanjava\
 -DartifactId=kusokora\
 -Dversion=1.0.0-SNAPSHOT

この時点で、あぁ、分からんなぁと思いました。だいたいmavenでプロジェクト作るときは既存のやつをコピーしてゴニョゴニョしちゃうからなー。

この辺読んだらよさそう。

ひな形を作っとくの便利そうだなー。なるほどなー。

pom

必要なのは、親pomとdependency1個だけなんやね。

    <!-- 最重要。Spring Bootの諸々設定を引き継ぐための親情報。 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.2.1.RELEASE</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <start-class>kanjava.App</start-class><!-- mainメソッドのあるクラスを明示的に指定 -->
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!-- 重要。Webアプリをつくるための設定。必要な依存関係は実はこれだけ。 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

実際には、mavenで実行するためのプラグインも定義されてます。

Spring Boot

@SpringBootApplication

が魔法のアノテーションね。fmfm

mainメソッドを呼び出すとTomcatが立ち上がるのかー。開発が楽そうでいいなー。

Spring MVC

@RestController

これはJAX-RSのみたいなもんね。

3. 顔変換サービスの作成 — Spring Bootキャンプ ハンズオン資料 1.0.0-SNAPSHOT ドキュメント

OpenCVを使って画像の中の顔を検出してそれをDukeっぽくしちゃうサービス。いま、ソース読んで、なるほどなーとなりました。(遅

流れ

  1. classifierFileをDIで指定して
  2. classifierFileを使いたいのでPostConstructでclassifierを初期化して
  3. FaceDetectorをコントローラーにAutowiredしといて
  4. 戻り値でBufferedImageを使えるように宣言しといて
  5. アクションメソッドで、FaceDetectorに画像を渡して処理後の画像を返す。

FaceDetector

顔を検出して、そのRectに対して変換処理を適用する。

FaceTranslator

今回のTranslatorは渡されたRectにDukeを書くっすね。上半分を黒四角、下半分を白四角、真ん中に赤丸を描画。この処理の部分がFaceDetectorのdetectFacesに渡されるすね。素敵。

    public void detectFaces(Mat source, BiConsumer<Mat, Rect> detectAction) {

5. JMSで画像変換を非同期処理 — Spring Bootキャンプ ハンズオン資料 1.0.0-SNAPSHOT ドキュメント

画像変換処理は非同期でするように、間にQueueをかませる。RabbitMQとActiveMQしか知らんかった。HornetQかー。また調べてみたいな。

HornetQ

SpringのJMSサポートがあるってことで、それを使う。GroupId見たらBootっぽいので、SpringBoot用にごにょごにょされてるんかな?

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

Sender

Queueを使う方は、こんな風にDIして

    @Autowired
    JmsMessagingTemplate jmsMessagingTemplate; // メッセージ操作用APIのJMSラッパー

sendするだけ。。。簡単だなー。

        jmsMessagingTemplate.send("hello", message); // 宛先helloにメッセージを送信

Receiver

受け取る側はアノテーションをつけるだけ。

@JmsListener(destination = "faceConverter", concurrency = "1-5")

Scope

って、ここでマルチスレッドで処理されるようにしたんだけど実際マルチスレッドで動かしてみると落ちる。

FaceDetectorがマルチスレッド対応じゃないのにSingletonスコープになってるからPrototypeスコープに変更。でも、AppコントローラーがSingletonスコープだから、そっちに引っ張られないようにscoped-proxyを使う。

7. STOMP over WebSocketで非同期処理結果を受信する — Spring Bootキャンプ ハンズオン資料 1.0.0-SNAPSHOT ドキュメント

STOMP over WebSocket

これもBootで用意されてるってことなのかなー。なんか色々すごいなー。

<!-- WebSocketプログラミングに必要な諸々 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

endpointってのを定義しておいて、クライアントはそこから情報をとってきて接続して、でコールバック処理をするって感じなのかな。

Prefix

  • /appから始まるものはControllerで処理
  • /topicで始まるものはメッセージブローカーが直接ハンドリングする。

greetingの流れ

  1. 画面で接続ボタンを押したら、endpointに接続して"/topic/greetings"を購読開始
  2. 画面で名前を入力して送信ボタンを押したら、"/app/greet"に名前を送信
  3. サーバー側では"/app/greet"で処理して、"/topic/greetings"に処理結果を渡す
  4. 画面側で"/topic/greetings"で受け取ったメッセージを画面に表示する

facesの流れ

  1. curlで画像変換処理を投げたら、convertFaceで処理した結果画像を"/topic/faces"に投げる。
  2. 画面側で"/topic/faces"を受信して画面表示

ふむー。面白いー。

8. WebRTCを使ってみる — Spring Bootキャンプ ハンズオン資料 1.0.0-SNAPSHOT ドキュメント

WebRTC

すごいなー。こんなコードでカメラが使えるんだねー。

<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Cameraテスト</title>
</head>
<body>
<video autoplay width="400" height="300"></video>

<script type="text/javascript">
    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || window.navigator.mozGetUserMedia || navigator.msGetUserMedia;
    window.URL = window.URL || window.webkitURL;

    var video = document.querySelector('video');
    navigator.getUserMedia({video: true, audio: false},
            function (stream) {
                video.src = window.URL.createObjectURL(stream);
            },
            function (error) {
                alert(JSON.stringify(error));
            }
    );
</script>
</body>
</html>

んで、スナップショットとって変換サービスに送ったら、顔がdukeになって返ってくると。

懇親会

  • nashorn
  • react.js

について調べろーってなったのでいつか頑張る。nashornってドイツ語でサイ?英語だとrhinorhinoってのもなんかなかったっけ?じゃ日本からなんかプロダクト作るときはサイだね。

面白かった!!

知らないことばかりで、面白かったー!!4月下旬になったら色々落ち着くと思うのでJavaの勉強再開しようと誓うのであった。

まきさん、うらがみさん、ありがとうございました!