JavaでのIPによるジオロケーション
1. 前書き
この記事では、MaxMind GeoIP2 Java APIと無料のGeoLite2データベースを使用して、IPアドレスから地理的位置データを取得する方法を探ります。
また、シンプルなSpring MVC Webデモアプリケーションを使用してこれを実際に見ていきます。
2. 入門
開始するには、MaxMindからGeoIP2APIとGeoLite2データベースをダウンロードする必要があります。
2.1. メーベン依存
MaxMind GeoIP2 APIをMavenプロジェクトに含めるには、pom.xmlファイルに以下を追加します。
com.maxmind.geoip2
geoip2
2.8.0
APIの最新バージョンを入手するには、Maven Centralで見つけることができます。
2.2. データベースのダウンロード
次に、GeoLite2 databaseをダウンロードする必要があります。 このチュートリアルでは、GeoLite2 Cityデータベースのバイナリgzip圧縮バージョンを使用しています。
アーカイブを解凍すると、GeoLite2-City.mmdbという名前のファイルが作成されます。 これは、独自のMaxMindバイナリ形式のIPからロケーションへのマッピングのデータベースです。
3. GeoIP2 JavaAPIの使用
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アプリケーションを見てみましょう。
basic Spring Web MVC Applicationから始めます。 次に、POSTリクエストでIPアドレスを受け入れ、GeoIP2 APIから推定された都市、緯度、経度を含むJSONレスポンスを返すControllerを記述します。
最後に、ユーザーのパブリックIPアドレスをフォームに読み込み、Ajax POSTリクエストをControllerに送信し、結果を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. サービスクラス
次に、GeoIP2 JavaAPIと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 locationService
= new RawDBDemoGeoIPLocationService();
return locationService.getLocation(ipAddress);
}
}
4.4. HTMLフォーム
IPアドレスを含むHTMLフォームで始まるSpringController,を呼び出すフロントエンドコードを追加しましょう。
...
4.5. クライアントにパブリックIPアドレスをロードする
次に、jQueryとipify.org JavaScript APIを使用して、「ipAddress」テキストフィールドにユーザーのパブリックIPアドレスを事前入力しましょう。
4.6. AjaxPOSTリクエストの送信
フォームが送信されると、SpringControllerにAjax POSTリクエストを送信して、ジオロケーションデータを含む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応答のサンプル
SpringControllerからのJSON応答は、次の形式になります。
{
"ipAddress":"your-ip-address",
"city":"your-city",
"latitude":"your-latitude",
"longitude":"your-longitude"
}
4.8. Googleマップに場所を表示する
Googleマップに場所を表示するには、HTMLコードにGoogle MapsAPIを含める必要があります。
Google Developer Consoleを使用して、GoogleマップのAPIキーを取得できます。
また、地図画像を含めるためにHTML<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は両方とも、IPv4アドレスとIPv6アドレスをサポートしていることに注意してください。
フォームを送信すると、パブリックIPアドレスに対応する都市、緯度、経度を含むJSON応答テキストが表示され、その下に、現在地を指すGoogleマップが表示されます。
5. 結論
このチュートリアルでは、JUnitテストを使用して、MaxMind GeoIP2 Java APIと無料のMaxMind GeoLite2 Cityデータベースの使用方法を確認しました。
次に、Spring MVCControllerとサービスを構築して、IPアドレスからジオロケーションデータ(都市、緯度、経度)を取得しました。
最後に、HTML / JavaScriptフロントエンドを構築して、この機能を使用してGoogleマップにユーザーの場所を表示する方法を示しました。
この製品には、MaxMindによって作成されたGeoLite2データが含まれており、http://www.maxmind.comから入手できます。
このチュートリアルのコードはGithub siteにあります。