SpringBoot入門
SpringBoot入門してみた
Spring Boot + Thymeleaf
環境
$ sw_vers ProductName: Mac OS X ProductVersion: 10.10.4 BuildVersion: 14E46
$ java -version java version "1.8.0_51" Java(TM) SE Runtime Environment (build 1.8.0_51-b16) Java HotSpot(TM) 64-Bit Server VM (build 25.51-b03, mixed mode)
以下のページを参考にしましたm(__)m
- めちゃわかりやすい、チュートリアル記事2つ
- Spring Data JPAでの実装について
- Thymeleafの日本語ドキュメント
http://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf_ja.htmlwww.thymeleaf.org
- Spring MVCについて
個人でこれだけまとめるとかすごすぎ・・・
- Springをより詳しく知りたいときに読む
m12i.hatenablog.com http://terasolunaorg.github.io/guideline/5.0.1.RELEASE/ja/terasolunaorg.github.io
- 公式ドキュメント(英語)
- アプリケーションの設定値
http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.htmldocs.spring.io
- 書籍
はじめてのSpring Boot―「Spring Framework」で簡単Javaアプリ開発 (I・O BOOKS)
- 作者: 槇俊明
- 出版社/メーカー: 工学社
- 発売日: 2014/11
- メディア: 単行本
- この商品を含むブログ (5件) を見る
試しに、簡単なアプリケーションを作成してみた。
メモ. その1
Spring Securityで、どうやって認証が行われるのかよくわからなかった。
認証の設定は、SecurityConfig
でしている。
protected void configure(HttpSecurity http)
にて、アクセス認証の設定をしている。
public void configure(WebSecurity web)
では、セキュリティの設定対象外として設定している。
protected void configure(HttpSecurity http)
内でも、.antMatchers("/login/form").permitAll()
で同じようなことをしているが、 違いがわかっていない。。。
static class AuthenticationConfiguration extends GlobalAuthenticationConfigurerAdapter
が、一番謎だった。
ざっくりと動作を記述する。
ログイン画面(/login/form)からFormが送信されると、
リクエストパラメータであるmail
の値がLoginUserDetailService#loadUserByUsername(String username)
に渡される。
この時、username
を元にリポジトリ(DB)から対象のデータ(レコード)を取得する。
取得結果が、nullならば存在しないユーザーIDなので例外をthrowする。
存在する場合は、org.springframework.security.core.userdetails.User
を継承した、LoginUserDetail
のインスタンスを返す。
LoginUserDetail
のコンストラクタには、引数として取得したAuthUser
のインスタンスを設定する。
LoginUserDetail
のコンストラクタ内では、org.springframework.security.core.userdetails.User
のコンストラクタを呼び出している。
呼び出しているコンストラクタの引数は、User(String username, String password, Collection<? extends GrantedAuthority> authorities)
となっている。
1, 2番目の引数は見ての通り、username
, password
になっている。
この値が、Formで送信された値と比較される。
パスワードは、SecurityConfig.AuthenticationConfiguration#init(AuthenticationManagerBuilder auth)
内で
設定したpasswordEncoder(getPasswordEncoder())
によって暗号化されて比較されるぽい。
Collection<? extends GrantedAuthority> authorities
については、
よくわかってないが認証したユーザーの権限を渡しているみたい。
わかったら追記。。。
LoginUserDetail
について
LoginUserDetail
は、org.springframework.security.core.userdetails.User
を継承したクラスorg.springframework.security.core.userdetails.User
は、org.springframework.security.core.userdetails.UserDetails
の実装なので、拡張(継承)して使うorg.springframework.security.core.userdetails.UserDetails
は、認証ユーザーの情報を取得するためのAPIを定義したinterface
メモ. その2
CSRFについて。
Spring Securityを有効にすると、デフォルトでCSRF対策が有効になるが、 Thymeleaf側で、正しくform要素を定義しないといけない。
以下のように、<form> ~ </form>
にth:action
属性を追加することで、
自動的に<input type="hidden" name="_csrf" value="e5521ea3-3cc5-4be4-84a5-7acd9ce10987" />
のような
トークンがリクエストパラメータとして追加される。
<form th:action="@{/xxx/xxx}" method="xxx"> ~ </form>
正しく設定されてない場合は、403でエラーとなる。
メモ. その3
Thymeleafでの、バリデーションエラーの表示について。
見たほうがわかりやすい。
<form th:object="${user}" th:action="@{/user/input}" method="POST"> ~ 省略 ~ <p th:if="${#fields.hasErrors('name')}" th:errors="*{name}">error</p> ~ 省略 ~ </form>
上記について。
th:if="${#fields.hasErrors('name')}"
user
オブジェクトのname
フィールドにエラーが存在するか
th:errors="*{name}"
name
フィールドのエラーを表示する
Thymeleafがオブジェクトのプロパティにアクセスする場合は、
getXxx
やisXxxx
のメソッドに対して、xxx
という名前に変換してアクセスするので、
アクセスするプロパティにはGetterが必要。
ex) user.name <- user.getName()
なので、Getterメソッドだけ定義してフィールドを宣言しなくてもOK。
ex)
sample.user.auth.domain.AuthUser#isCheckPassword
この辺の実装は↓
- sample.user.controller.UserController#confirm
- src/main/resources/templates/user/form.html
SpringBootを使ってみて
Springの面倒な設定がいらない。
Springのみの場合、xmlとかannotationでいろいろ設定しないといけない
最初、理解するためにSpringだけでやってみようとしたけど、設定で躓いて諦めた。。。
ライブラリを追加する場合でも、SpringBootがよしなにやってくれるのでかなり楽。
組み込みのWebサーバがある。
ビルドしたらjarが作られるので、配置先のサーバで
java -jar xxx.jar
でAPサーバが立ち上がる(!) Gradleだと、gradle bootRun
で一発(!)
Annotationつけるだけで、全部設定してくれる。
ある程度わかってくると楽になっていいけど、初めはつらいかも。。
How Google Worksを読んだ
How Google Works (ハウ・グーグル・ワークス) ―私たちの働き方とマネジメント
- 作者: エリック・シュミット,ジョナサン・ローゼンバーグ,アラン・イーグル,ラリー・ペイジ,土方奈美
- 出版社/メーカー: 日本経済新聞出版社
- 発売日: 2014/10/09
- メディア: 単行本
- この商品を含むブログ (17件) を見る
Googleがどのようにしてこれまでの成功を収めたのかについて書かれている本。
現在のインターネットによる変化が著しい時代(本の中では、"インターネットの世紀"と呼ばれてる)で成功するためには、 プロダクトの優位性が必要で、それがあればユーザーを獲得することができるし、あとから利益もついてくる。
プロダクトの優位性を得るには、既存の市場を参考にするのではなく これまでにない技術的アイデアによって実現されることが成功の鍵。
ex) Gmailだと、今までメールソフト使うのが常識だったけどブラウザで出来るようなったとかかな
ユーザーに焦点を絞るというのも、プロダクトの優位性を保ち続けるためのもので、ユーザーにとっての価値が最優先。
そのプロダクトを実現するには、専門性と実現力を備えたとても優秀な人材が必要で その人材のことが"スマートクリエイティブ"と呼ばれている。
スマートクリエイティブを獲得するために、 Googleは採用を経営者の一番重要な仕事だと考えていて、 中には"自分より優秀な人間を採用せよ"というルールがあるらしい。
ほかにもイノベーションや組織のマネジメントについても書かれており、 人材についてはGoogleみたいな企業しか出来ないこともあると思うけど(破格の報酬とか・・・)、 Googleが実践してきた手法を学べる良い本だと思いました。
PlayFramework2.3(scala)でDBアクセスをするときのめも
Play + ScalaでDBアクセスのめも
環境
DDLは↓
本来はEvolutionを利用して作るものだけど、今回は直接作成した・・・
CREATE TABLE `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `mail` varchar(255) NOT NULL, `password` varchar(255) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `mail_UNIQUE` (`mail`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
設定
SQLアクセスをするために、anormを使う
build.sbtの設定
必要なライブラリを追加
libraryDependencies ++= Seq( jdbc, anorm, cache, ws, "mysql" % "mysql-connector-java" % "5.1.34" )
application.confの設定
DB接続設定の追加 それぞれ以下の変数は自分の環境に適宜変更する
HOSTNAME, SCHEMANAME, USERNAME, PASSWORD
db.default.driver=com.mysql.jdbc.Driver db.default.url="jdbc:mysql://_HOSTNAME_/_SCHEMANAME_" db.default.user="_USERNAME_" db.default.password="_PASSWORD_"
実装
Scalaの場合、Javaと違ってモデルを扱うためのライブラリがないみたい
Slickというライブラリが時期バージョンでデフォルトになるとかならないとか・・・
初めはSlickを試していたけどうまく動いてくれなかったので断念して、 anormを利用してみたところ使い勝手が良かったのでanormを利用することにした
モデルは、Javaと同様にapp/models
以下に作成していく
anormではモデルを作成するパッケージなどに特に縛りはなく、 コントローラにSQLを書いたりしても問題ないが、アレだと思うので
app/models
以下に作成していく
実際のソース
https://github.com/yamashiro0110/Play-ScalaSample/blob/master/app/models/User.scala
ハマった点.1: ~
って何?
~
については、以下のページに解説があった
http://libro.tuyano.com/index3?id=1069003&page=5 ここでの「~」という記号は、Anorm特有の機能で、値をリスト化する働きをします。例えば、A~B~Cとすると、((A, B), C)というようにまとめられます。こうしてまとめたものを元にMydataオブジェクトを生成するのが、その後のmap部分です。
ハマった点.2:object User.data
が何なのかよくわからない
data
については、SQLの実行結果をオブジェクトにパースするためのものみたい
以下のコードだとSQL(SQL文).on(条件).as(パーサ.戻り値)
となっている
def findById(id: Long): Option[User] = { DB.withConnection { implicit c => val sql = "SELECT * FROM user WHERE id = {id}" SQL(sql) .on("id" -> id) .as(User.data.singleOpt) } }
戻り値をOption[User]
にしたのは、指定されたIDがテーブルに存在しない場合にエラーが発生したため
パーサ(data
)からOption[User]
を取得するためには、singleOpt
を呼び出せばいい
User
を取得したい場合は、single
でいける
User
モデルを呼び出している部分はapp/controllers/SampleController
になっている
変数usr
に、IDが1のUserを探して代入、存在しない場合はUser.notFound
を代入している
レスポンスはCall SampleController index!! ->
という文字列にusr.name
を追加して返しているだけ
def index = Action { val usr = User.findById(1).getOrElse(User.notFound) Ok("Call SampleController index!! -> " + usr.name) }
Play + JavaのEbeanがクソ便利だったので、 Play + Scalaにはなかったことを知ったとき(とSlickを断念したとき)はJavaに戻ろうかと考えたけど、 anormもなかなか使いやすかったので今後もPlay + Scalaを利用していきたいと思った
あと、今回のソースをGitHubに上げました^^;
参考にしたページm(__)m
Model(モデル)を使ってデータベースアクセスする[Scala編](1/7):Herokuで始める 初心者のためのPlay Framework入門
リーン・スタートアップを読んだ
印象にのこったところ
- 顧客にとっての価値のあるもの以外はすべて無駄である
- 起業とはマネジメントである
- 仮設と検証による学びを繰り返して、製品を価値あるものに成長させる
- ピボット(方向転換)
- MVP(実用最小限の製品)
- 小さなバッチサイズ
今まで起業については、「当たれば成功」「外れたら取り返しがつかないほどの失敗」といった 超ハイリスクなギャンブルのようなものだと思っていた。
この本を読むことで起業した場合に、 リーンスタートアップではどのように仕事を 進めるべきなのかが実例をもとに解説されているため、 起業はギャンブルであるという印象はなくなった。
ただ、起業して本当に成功するためには努力と情熱が必要だし、 ほかにもまだまだ知らなければならないことがあると感じた。
YahooBB With フレッツ光でインターネットに接続できなくなったときのめも
家のインターネット回線をauひかりから、YahooBB フレッツ光に乗り換えたのだけど オプション解約などするとネットにつながらなくなったので、そのときの対応をメモ・・・
つながらなくなった経緯
2015/03/26に自動音声案内にそって、すべてのオプション解約手続きをしました。 (てかサポートがまじで電話とらん、ネット上では8時間掛けっぱなしにしても取らなかった人もいるとか・・・)
以下のページに記載の番号 http://ybb.softbank.jp/support/inquiry/hikari/301i.html
月が変わって、4/1に・・・
朝、スマホでFacebookやらInstagramのアプリを開くとネットワーク接続エラー・・・
ルータを再起動したりしてみるも、変わらず・・・
対応したこと
とりあえずルータにログイン(ルータはフレッツ光のもの)
自分のとこでは、http://192.168.1.1へアクセスするとBasic認証が行われたが、 メッセージにID,PWらしきものが記載されてたので、それでログインできた
"情報" > "障害ログ"とリンクをたどると、ルータのログがあった
以下ようなメッセージがあった
66. 2015/04/02 20:11:31 PPPの認証失敗[メインセッション] 67. 2015/04/02 20:11:31 PPP-LCPの確立[メインセッション] 68. 2015/04/02 20:11:31 PPPoE セッション開始成功[メインセッション] 69. 2015/04/02 20:11:31 PPPoE AC発見成功[メインセッション]
PPPの認証失敗だと・・・!? (PPP接続の認証情報とか見覚えがないし・・・)
家のPCでは、ネットがつながらないのでひたすらスマホでググってると PPPoE接続のID・パスワードの変更を行えるページにヒット(この間、約2日・・・)
https://ybb.softbank.jp/member/yf/index.php このページを表示するにも、契約時に発行されたYahooIDでのログインが必要
今回はPWがわからなかったので、PWだけ変更
変更が完了したら再度ルータの設定画面へ行き、PPPoE接続の設定を行う
基本設定 > 接続先設定(IPv4 PPPoE) > メインセッション
PPPoEのIDが'xxxxxxxxxxxx@sbb.ne.jp'のようになってたので、以下のように設定
接続先名:xxxxxxxxxxxx(IDがメールアドレスになってたのでアカウント部分を設定) 接続先ユーザー名:xxxxxxxxxxxx@sbb.ne.jp 接続パスワード:xxxxxxxx(先ほど設定したPW)
入力したら"設定"ボタンを押す
再度、"障害ログ"を見ると以下のログが・・・
1. 2015/04/02 20:15:37 PPP-IPCPの確立[メインセッション] 2. 2015/04/02 20:15:37 PPPの認証成功[メインセッション] 3. 2015/04/02 20:15:37 PPP-LCPの確立[メインセッション] 4. 2015/04/02 20:15:37 PPPoE セッション開始成功[メインセッション] 5. 2015/04/02 20:15:37 PPPoE AC発見成功[メインセッション]
認証成功キタ━━━━(゚∀゚)━━━━!!
https://www.google.co.jp/にアクセスすると、表示された!
一件落着( ´ー`)フゥー...
まとめ
YahooBBのオプションである光BBユニットを解約すると(?) PPPoEの認証設定を変更しないといけないぽい・・・
ネットつながらないから、サポートに電話してるってのに 全然とらないってどういうことだってばよ・・・ (WEBで手続き出来ますとか言ってるし)
光BBユニット解約したら認証設定必要とか聞いてないし、 オプション解約時の影響とか手元の資料見ても全然わからんし・・・ (この辺は確認不足もあるかも)
おかげで、スマホの通信料を無駄遣いしてしまった・・・
いろいろと文句が多くなっていますが、 同じような現象で困っている人の助けになれば幸いです(-_-;)
Written with StackEdit.
PlayFrameworkインストールめも
Play2.3を対象にしてます
言語はJava
環境
$ sw_vers ProductName: Mac OS X ProductVersion: 10.10.1 BuildVersion: 14B25
$ java -version java version "1.7.0_51" Java(TM) SE Runtime Environment (build 1.7.0_51-b13) Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)
Activatorのインストール
ここからDL
今回は/Application
以下に配置
以下のファイルにパスを通す
/Applications/activator-1.2.2-minimal/activator
プロジェクトを作成
プロジェクト用のディレクトリ作成&移動
mkdir /path/to/play && cd /path/to/play
プロジェクト作成
activator new
対話式で進んでいくので、質問に答えていけば問題なく作成されるはず 今回は
play-java
を選択
起動してみる
cd /path/to/play
activator run
初回実行だからか、ライブラリのDLが始まった 30分くらいかかった気がする・・・
ブラウザで以下のURLにアクセスしてみる
参考
https://www.playframework.com/documentation/ja/2.3.x/Installing
CakePHPのインストールめも
CakePHPの環境構築のめも(ちょっとハマった・・・)
環境
$ sw_vers ProductName: Mac OS X ProductVersion: 10.10.1 BuildVersion: 14B25
Server version: Apache/2.4.9 (Unix) Server built: Sep 9 2014 14:48:20
CakePHP 2.6.1
インストール
CakePHPのダウンロード
Gitでclone
$ cd /path/to/CakePHP
$ git clone git://github.com/cakephp/cakephp.git
Apacheの設定
ここでドキュメント通りにやってもうまく行かなかったためCakePHP用に以下の設定を行う
- ポートを
10080
に設定
Listen 127.0.0.1:10080 <VirtualHost 127.0.0.1:10080> # CakePHPを'git clone'したディレクトリの'app/webroot'を指定 DocumentRoot /path/to/CakePHP/cakephp/app/webroot ServerName 127.0.0.1:10080 ServerAdmin webmaster@host.example.com <IfModule php5_module> AddType application/x-httpd-php .php </IfModule> <IfModule dir_module> DirectoryIndex index.php </IfModule> # CakePHPの公開用ディレクトリ'app/webroot'を'/'にマッピング Alias / /path/to/CakePHP/cakephp/app/webroot/ <Directory "/path/to/CakePHP/cakephp/app/webroot/"> AllowOverride None Options All Require all granted </Directory> </VirtualHost>
2015/01/27 追記
DocumentRootには、Cakeの
app/webroot
を指定することコントローラを作成したときに、そのコントローラのURLにアクセスできなかったため
上記、設定後にApache再起動
以下のURLにアクセス
http://localhost:10080/
公式のチュートリアルだと、以下のように記述されていたのですが これだとリダイレクトループが発生するためエラーが発生していました
<IfModule mod_rewrite.c> RewriteEngine on RewriteRule ^$ app/webroot/ [L] RewriteRule (.*) app/webroot/$1 [L] </IfModule>
参考