SIBYL System

Play framework Advent Calendar 2014 6日目 位置情報を使ってみよう

この記事はPlay framework Advent Calendar 2014の6日目として書いたものです。

最近位置情報系を使ったアプリとか多いですよね。Google MapとかIngressとか。趣味で位置情報を扱うものを作っていたのですが、サーバーサイドで位置情報、空間情報をどう扱うかで迷っていました。Playを使うとなると更に情報量が減るので情報を探すのが大変でした。

なので調べた内容を適当に書いておきます。

今回の目標

  1. DBにいくつか都市などの位置情報を入れておく
  2. 指定した位置から最も近い順に都市の情報をJson形式で出力する

使うもの

  1. jdk1.7
  2. play2(2.1) java使います
  3. postgresql・・・mysqlも位置情報を扱う属性はあるようですが、細かい機能を見ると機能的にpostgresql(+postGIS)に劣るようでしたのでpostgresqlを選択しました。
  4. postGIS
  5. Hibernate・・・ebeanは私には扱いきれないじゃじゃ馬でした。
  6. CentOS 7・・・ここらへんはお好みで。

postgresqlの準備

postGISの準備

それっぽいテーブルを作成する

それっぽいテーブルを作成します。postGISを入れててtemplateでpostgisなテンプレートを選択するとgeometryカラムなどなど位置情報系を扱うことが出来るようになっています。

 データを入れる

SQL文で検索もやってみましょう。長崎から近い順をのレコードを検索します。

WHERE句では長崎の座標である(32.76525212, 129.8718717)から周辺(<1000)にあるレコードを取り出しています。レコードが増加した場合、検索の範囲を狭める事は重要ですが、今回はたったの4レコードですのでコメントアウトしています。

ORDER BY句では長崎の座標(32.76525212, 129.8718717)から最も近い順のレコードを取り出しています。

結果は以下。長崎から近い順に結果が表示されています。日本地図と世界地図がなんとなく頭に入っている方なら正しい結果であることがわかると思います。

Playframework2(Java)なアプリを作る

さて、ここからがメインです。

eclipse使うのでactivator eclipseを実行

eclipseを起動して作ったプロジェクトをインポート。とりあえずrunして動くことを確認。めちゃくちゃ時間かかるのでモンハンをして待ちます。

起動したらアクセスできるところまで確認します。この流れはお決まり。

まずはpostgresqlとhibernate、geometryが使えるようにライブラリの追加します。

次にlibsディレクトリを作成して、ファイルをいくつか配置します。またeclipseを使ってプロジェクトディレクタリに「lib」ディレクトリを作成して以下のファイルを配置。更にプロパティの「Java Build Path → Add Jars」からインポートしておきましょう。

(「libs」とか「library」とかてきとーなディレクトリ名ではダメです。playframeworkのコンパイル時に「lib」ディレクトリの中身だけは管理外依存[unmanaged]として扱ってくれます。)

  1. hibernate-spatial-4.0-M1.jar
  2. jts-1.8.jar
  3. jtsio-1.8.jar
  4. mapfish-geo-lib-1.3-SNAPSHOT.jar
  5. postgis-jdbc-2.0.0.jar

主にGeometry型をJavaで扱うのに必要(らしい)もの一式です。

次にapplication.confにDBの設定を追加します。ユーザー名とパスワードは適宜置き換えてください。

次にpersistence.xmlを配置します。confディレクトリの中にMETA-INFディレクトリを作成して、その中に以下が記述されたpersistence.xmlを配置しましょう。

次にdto(entites)ファイルを作成します。先ほど作成したテーブル定義に合わせます。以下はimport文やGetter/Setterなんかは省いています。

次にSQLを実行するDaoクラスを作成します。(setParameterを使うと何故かExceptionを吐いてくれるので今回は雑な書き方になってます。)

次にroutesの設定、GETメソッドでアクセスがあったらそれっぽい値をjsonで返すようにしたいと思います。

最後に対応するコントローラーを追加します。Geometry型はJson.perseで変換できませんのでJsonに変換するメソッドを作成しました。(実際はModelに書いたほうが良いかもしれません。)

アクセスしてみます。座標は東京付近です。

以下が取得出来ました

入力が東京付近の座標に対して結果は「東京→名古屋→大阪→ニューヨーク」と順に出力されていますね。

位置情報に関しては本当に広くて深い分野で、なかなか難しい部分もありますが、Play+位置情報処理の初めの一歩として参考にしていただければと思います。

それでは。

モバイルバージョンを終了