JavaでのIPによるジオロケーション
1. 序章
この記事では、無料のGeoLite2データベースでMaxMind GeoIP2 Java APIを使用して、IPアドレスから地理的位置データを取得する方法について説明します。
また、単純なSpringMVCWebデモアプリケーションを使用してこれが実際に動作することを確認します。
2. 入門
開始するには、MaxMindからGeoIP2APIとGeoLite2データベースをダウンロードする必要があります。
2.1. Mavenの依存関係
MaxMind GeoIP2 APIをMavenプロジェクトに含めるには、pom.xmlファイルに以下を追加します。
<dependency>
<groupId>com.maxmind.geoip2</groupId>
<artifactId>geoip2</artifactId>
<version>2.8.0</version>
</dependency>
APIの最新バージョンを入手するには、 MavenCentralで入手できます。
2.2. データベースのダウンロード
次に、GeoLite2データベースをダウンロードする必要があります。 このチュートリアルでは、GeoLite2Cityデータベースのバイナリgzip圧縮バージョンを使用しています。
アーカイブを解凍すると、GeoLite2-City.mmdbという名前のファイルが作成されます。 これは、独自のMaxMindバイナリ形式のIPから場所へのマッピングのデータベースです。
3. GeoIP2JavaAPIの使用
GeoIP2 Java APIを使用して、データベースから特定のIPアドレスの位置データをフェッチしてみましょう。 まず、 DatabaseReader を作成して、データベースにクエリを実行しましょう。
File database = new File(dbLocation);
DatabaseReader dbReader = new DatabaseReader.Builder(database).build();
次に、 city()メソッドを使用して、IPアドレスの都市データを取得しましょう。
CityResponse response = dbReader.city(ipAddress);
CityResponse オブジェクトには、都市名以外のいくつかの情報が含まれています。 これは、データベースを開き、IPアドレスの都市情報を取得し、CityResponseからこの情報を抽出する方法を示すサンプルのJUnitテストです。
@Test
public void givenIP_whenFetchingCity_thenReturnsCityData()
throws IOException, GeoIp2Exception {
String ip = "your-ip-address";
String dbLocation = "your-path-to-mmdb";
File database = new File(dbLocation);
DatabaseReader dbReader = new DatabaseReader.Builder(database)
.build();
InetAddress ipAddress = InetAddress.getByName(ip);
CityResponse response = dbReader.city(ipAddress);
String countryName = response.getCountry().getName();
String cityName = response.getCity().getName();
String postal = response.getPostal().getCode();
String state = response.getLeastSpecificSubdivision().getName();
}
4. WebアプリケーションでのGeoIPの使用
ユーザーのパブリックIPアドレスからジオロケーションデータを取得し、その場所を地図上に表示するサンプルWebアプリケーションを見てみましょう。
基本的なSpringWebMVCアプリケーションから始めます。 次に、POSTリクエストでIPアドレスを受け取り、GeoIP2 APIから推定された都市、緯度、経度を含むJSON応答を返すコントローラーを記述します。
最後に、ユーザーのパブリックIPアドレスをフォームに読み込んで Controller にAjaxPOSTリクエストを送信し、結果をGoogleマップに表示するHTMLとJavaScriptを記述します。
4.1. 応答エンティティクラス
ジオロケーション応答を保持するクラスを定義することから始めましょう:
public class GeoIP {
private String ipAddress;
private String city;
private String latitude;
private String longitude;
// constructors, getters and setters...
}
4.2. サービスクラス
次に、GeoIP2JavaAPIとGeoLite2データベースを使用してジオロケーションデータをフェッチするサービスクラスを作成しましょう。
public class RawDBDemoGeoIPLocationService {
private DatabaseReader dbReader;
public RawDBDemoGeoIPLocationService() throws IOException {
File database = new File("your-mmdb-location");
dbReader = new DatabaseReader.Builder(database).build();
}
public GeoIP getLocation(String ip)
throws IOException, GeoIp2Exception {
InetAddress ipAddress = InetAddress.getByName(ip);
CityResponse response = dbReader.city(ipAddress);
String cityName = response.getCity().getName();
String latitude =
response.getLocation().getLatitude().toString();
String longitude =
response.getLocation().getLongitude().toString();
return new GeoIP(ip, cityName, latitude, longitude);
}
}
4.3. スプリングコントローラー
ジオロケーション応答データを取得するために「ipAddress」リクエストパラメータをサービスクラスに送信するSpringMVCのControllerを見てみましょう。
@RestController
public class GeoIPTestController {
private RawDBDemoGeoIPLocationService locationService;
public GeoIPTestController() throws IOException {
locationService = new RawDBDemoGeoIPLocationService();
}
@PostMapping("/GeoIPTest")
public GeoIP getLocation(
@RequestParam(value="ipAddress", required=true) String ipAddress
) throws Exception {
GeoIPLocationService<String, GeoIP> locationService
= new RawDBDemoGeoIPLocationService();
return locationService.getLocation(ipAddress);
}
}
4.4. HTMLフォーム
Spring Controller、を呼び出すフロントエンドコードを追加して、IPアドレスを含むHTMLフォームで始めましょう。
<body>
<form id="ipForm" action="GeoIPTest" method="POST">
<input type="text" name = "ipAddress" id = "ip"/>
<input type="submit" name="submit" value="submit" />
</form>
...
</body>
4.5. クライアントにパブリックIPアドレスをロードする
次に、jQueryと ipify.org JavaScript APIを使用して、「ipAddress」テキストフィールドにユーザーのパブリックIPアドレスを事前入力しましょう。
<script src
="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js">
</script>
<script type="text/javascript">
$(document).ready (function () {
$.get( "https://api.ipify.org?format=json",
function( data ) {
$("#ip").val(data.ip) ;
});
...
</script>
4.6. AjaxPOSTリクエストの送信
フォームが送信されると、Spring ControllerにAjaxPOSTリクエストを送信して、ジオロケーションデータを含むJSONレスポンスを取得します。
$( "#ipForm" ).submit(function( event ) {
event.preventDefault();
$.ajax({
url: "GeoIPTest",
type: "POST",
contentType:
"application/x-www-form-urlencoded; charset=UTF-8",
data: $.param( {ipAddress : $("#ip").val()} ),
complete: function(data) {},
success: function(data) {
$("#status").html(JSON.stringify(data));
if (data.ipAddress !=null) {
showLocationOnMap(data);
}
},
error: function(err) {
$("#status").html("Error:"+JSON.stringify(data));
},
});
});
4.7. サンプルJSON応答
Spring ControllerからのJSON応答の形式は次のとおりです。
{
"ipAddress":"your-ip-address",
"city":"your-city",
"latitude":"your-latitude",
"longitude":"your-longitude"
}
4.8. Googleマップに場所を表示する
Googleマップに場所を表示するには、HTMLコードにGoogleMapsAPIを含める必要があります。
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR-API-KEY"
async defer></script>
Google Developer Consoleを使用して、GoogleマップのAPIキーを取得できます。
HTMLも定義する必要があります
<div id="map" style="height: 500px; width:100%; position:absolute"></div>
次のJavaScript関数を使用して、Googleマップに座標を表示できます。
function showLocationOnMap (location) {
var map;
map = new google.maps.Map(document.getElementById('map'), {
center: {
lat: Number(location.latitude),
lng: Number(location.longitude)},
zoom: 15
});
var marker = new google.maps.Marker({
position: {
lat: Number(location.latitude),
lng: Number(location.longitude)},
map: map,
title:
"Public IP:"+location.ipAddress
+" @ "+location.city
});
}
Webアプリケーションを起動した後、マップページのURLを開きます。
http://localhost:8080/spring-mvc-xml/GeoIpTest.jsp
接続の現在のパブリックIPアドレスがテキストボックスに読み込まれます。
GeoIP2とipifyはどちらも、IPv6アドレスだけでなくIPv4アドレスもサポートしていることに注意してください。
フォームを送信すると、パブリックIPアドレスに対応する都市、緯度、経度を含むJSON応答テキストが表示され、その下に、現在地を指すGoogleマップが表示されます。
5. 結論
このチュートリアルでは、JUnitテストを使用してMaxMind GeoIP2JavaAPIと無料のMaxMindGeoLite2Cityデータベースの使用法を確認しました。
次に、Spring MVC Controller とサービスを構築して、IPアドレスから地理位置データ(都市、緯度、経度)を取得しました。
最後に、HTML / JavaScriptフロントエンドを構築して、この機能を使用してGoogleマップにユーザーの場所を表示する方法を示しました。
この製品には、MaxMindによって作成されたGeoLite2データが含まれており、http://www.maxmind.comから入手できます。
このチュートリアルのコードは、Githubサイトにあります。