【脱初心者】Spring Bootキャンプ【ハンズオン】 - connpass
ついていけない人は置いてくよ、ってどんどん進んで、ついていくのに必死で楽しかった!全然知らないことばっかりで、そういうの久しぶりだったなー。すごく濃い2時間でした。
SpringBoot -> OpenCV -> JMS(HornetQ) -> HornetQ -> STOMP -> WebRTC 盛りだくさんだわー!プログラミングってすごいなー。たのしいなー。 #kanjava_sbc
— バファラティ (@bufferings) March 7, 2015
Dockerまでは行けなかったので宿題ということになりました。落ち着いたらやってみよっと。
できあがったもの↓
さいごに娘たちのファイルをアップしてみたら奥行きを感じる画像になりました! #kanjava_sbc #sbc09 34 faces are detected! pic.twitter.com/dp0ImJDioV
— バファラティ (@bufferings) March 7, 2015
復習もかねて思い出しつつ、垂れ流ししてみる。
資料
これがすごい。ありがとうございます。
Spring Bootキャンプ ハンズオン資料 — Spring Bootキャンプ ハンズオン資料 1.0.0-SNAPSHOT ドキュメント
僕は当日、理解することを捨てて、分かった気になることにしました。(え
考えることをやめた。コピペに集中した。達成感に包まれた。勝った(違 #kanjava_sbc
— バファラティ (@bufferings) March 7, 2015
当日のスライドもアップされてます。
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>
3. 顔変換サービスの作成 — Spring Bootキャンプ ハンズオン資料 1.0.0-SNAPSHOT ドキュメント
OpenCVを使って画像の中の顔を検出してそれをDukeっぽくしちゃうサービス。いま、ソース読んで、なるほどなーとなりました。(遅
流れ
- classifierFileをDIで指定して
- classifierFileを使いたいのでPostConstructでclassifierを初期化して
- FaceDetectorをコントローラーにAutowiredしといて
- 戻り値でBufferedImageを使えるように宣言しといて
- アクションメソッドで、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にメッセージを送信
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の流れ
- 画面で接続ボタンを押したら、endpointに接続して"/topic/greetings"を購読開始
- 画面で名前を入力して送信ボタンを押したら、"/app/greet"に名前を送信
- サーバー側では"/app/greet"で処理して、"/topic/greetings"に処理結果を渡す
- 画面側で"/topic/greetings"で受け取ったメッセージを画面に表示する
facesの流れ
- curlで画像変換処理を投げたら、convertFaceで処理した結果画像を"/topic/faces"に投げる。
- 画面側で"/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になって返ってくると。