Перейти к основному содержимому

Геолокация по IP в Java

· 6 мин. чтения

1. Введение

В этой статье мы рассмотрим, как получить данные о географическом местоположении с IP-адреса с помощью Java API MaxMind GeoIP2 с бесплатной базой данных GeoLite2.

Мы также увидим это в действии, используя простое демонстрационное веб-приложение Spring MVC.

2. Начало работы

Для начала вам необходимо загрузить GeoIP2 API и базу данных GeoLite2 с сайта MaxMind.

2.1. Зависимость от Maven

Чтобы включить API MaxMind GeoIP2 в свой проект Maven, добавьте в файл pom.xml следующее :

<dependency>
<groupId>com.maxmind.geoip2</groupId>
<artifactId>geoip2</artifactId>
<version>2.8.0</version>
</dependency>

Чтобы получить последнюю версию API, вы можете найти ее на Maven Central .

2.2. Загрузка базы данных

Далее вам необходимо загрузить базу данных GeoLite2 . В этом руководстве мы используем двоичную версию базы данных GeoLite2 City, сжатую с помощью gzip.

После распаковки архива у вас будет файл с именем GeoLite2-City.mmdb . Это база данных сопоставлений IP-адресов и местоположений в проприетарном двоичном формате MaxMind.

3. Использование Java-API GeoIP2

Давайте воспользуемся Java API GeoIP2 для извлечения данных о местоположении для заданного IP-адреса из базы данных. Во-первых, давайте создадим DatabaseReader для запроса к базе данных:

File database = new File(dbLocation);
DatabaseReader dbReader = new DatabaseReader.Builder(database).build();

Далее воспользуемся методом city() для получения данных о городе для IP-адреса:

CityResponse response = dbReader.city(ipAddress);

Объект CityResponse содержит несколько фрагментов информации помимо названия города. Вот пример теста JUnit, показывающий, как открыть базу данных, получить информацию о городе для IP-адреса и извлечь эту информацию из CityResponse :

@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. Использование GeoIP в веб-приложении

Давайте рассмотрим пример веб-приложения, которое извлекает данные геолокации с общедоступного IP-адреса пользователя и отображает местоположение на карте.

Мы начнем с базового приложения Spring Web MVC . Затем мы напишем контроллер , который принимает IP-адрес в запросе POST и возвращает ответ JSON, содержащий город, широту и долготу, полученные из API GeoIP2.

Наконец, мы напишем HTML и JavaScript, которые будут загружать общедоступный IP-адрес пользователя в форму, отправлять запрос Ajax POST нашему контроллеру и отображать результат на Google Maps.

4.1. Класс объекта ответа

Начнем с определения класса, который будет содержать ответ геолокации:

public class GeoIP {
private String ipAddress;
private String city;
private String latitude;
private String longitude;
// constructors, getters and setters...
}

4.2. Класс обслуживания

Теперь давайте напишем сервисный класс, который извлекает данные геолокации с помощью Java API GeoIP2 и базы данных 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. Контроллер Spring

Давайте посмотрим на контроллер для Spring MVC, который отправляет параметр запроса «ipAddress» в наш класс обслуживания, чтобы получить данные ответа геолокации:

@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, начиная с HTML-формы, содержащей IP-адрес:

<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-адреса на клиенте

Теперь давайте предварительно заполним текстовое поле «ipAddress» общедоступным IP-адресом пользователя, используя jQuery и JavaScript API ipify.org :

<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. Отправка запроса Ajax POST

Когда форма будет отправлена, мы отправим запрос Ajax POST к контроллеру Spring , чтобы получить ответ 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

Ответ JSON от нашего контроллера Spring будет иметь следующий формат:

{
"ipAddress":"your-ip-address",
"city":"your-city",
"latitude":"your-latitude",
"longitude":"your-longitude"
}

4.8. Отображение местоположения на Google Maps

Чтобы отобразить местоположение на Картах Google, вам необходимо включить API Карт Google в свой HTML-код:

<script src="https://maps.googleapis.com/maps/api/js?key=YOUR-API-KEY" 
async defer></script>

Вы можете получить ключ API для Карт Google с помощью консоли разработчика Google.

Вам также потребуется определить HTML - тег <div> для размещения изображения карты:

<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
});
}

После запуска веб-приложения откройте URL-адрес страницы карты:

http://localhost:8080/spring-mvc-xml/GeoIpTest.jsp

Вы увидите текущий общедоступный IP-адрес для вашего подключения, загруженный в текстовое поле:

./891d239af816750dbaf96bfe30650fc2.jpg

Обратите внимание, что и GeoIP2, и ipify поддерживают адреса IPv4, а также адреса IPv6.

Когда вы отправите форму, вы увидите текст ответа JSON, включая город, широту и долготу, соответствующие вашему общедоступному IP-адресу, а ниже вы увидите карту Google, указывающую на ваше местоположение:

./0c35ce94a7e06025ff6a71b32ffee5d5.jpg

5. Вывод

В этом руководстве мы рассмотрели использование Java API MaxMind GeoIP2 и бесплатной базы данных MaxMind GeoLite2 City с использованием теста JUnit.

Затем мы создали контроллер Spring MVC и сервис для получения данных геолокации (город, широта, долгота) с IP-адреса.

Наконец, мы создали интерфейс HTML/JavaScript, чтобы продемонстрировать, как эту функцию можно использовать для отображения местоположения пользователя на Картах Google.

Этот продукт включает данные GeoLite2, созданные MaxMind, доступные на http://www.maxmind.com .

Код для этого туториала можно найти на сайте Github .