Определение страны и города по IP-адресу на Java/Scala
4 декабря 2015
Задача определения города и страны по IP-адресу встречается довольно часто. Когда пользователь заходит на сайт, желательно сразу показать ему интерфейс на том языке, который пользователь с наибольшей вероятностью понимает. А зная приблизительные координаты пользователя, можно перенаправить его запросы на ближайший сервер, уменьшив тем самым время ответа. В этой небольшой заметке мы посмотрим, как эта задача может быть решена на Scala или любом другом JVM-языке.
Не будем ходить вокруг да около. Тут можно скачать базу, а здесь — посмотреть исходники клиента к ней.
Качаем и распаковываем бесплатную версию базу:
gunzip GeoLiteCity.dat.gz
Запускаем REPL с подгруженной зависимостью:
… где screpl — это вот такой скрипт, лежащий где-то в $PATH:
/usr/bin/sbt -Dsbt.version=0.13.7 -Dsbt.main.class=sbt.ConsoleMain "$@"
Примечание: Кстати, когда я изучал Scala, почему-то для меня было большой проблемой понять, как использовать зависимости в REPL. Сделать это можно как описано выше, или, если вы не просто экспериментируете с библиотекой, а работаете над полноценным проектом, командой sbt console
. Если же вы пользуетесь возможностью SBT создавать много проектов внутри одного (multi project builds), то команда будет sbt myproject/console
. Кроме того, это возможно через Scala Console в IntelliJ IDEA. При использованием multi project builds опять-таки важно указать правильный проект.
Инициализируем клиент:
import com.maxmind.geoip._
scala> val srv = {
| new LookupService("./GeoLiteCity.dat",
| LookupService.GEOIP_MEMORY_CACHE)
| }
Получаем информацию об IP:
Смотрим в интересующие нас поля:
res0: String = RU
scala> loc.countryName
res1: String = Russian Federation
scala> loc.city
res2: String = Moscow
scala> loc.latitude
res3: Float = 55.752197
scala> loc.longitude
res4: Float = 37.6156
Важно! Приведенные выше значения могут быть и null, поэтому в боевом коде обязательно оборачивайте их в Option.
Как видите, все предельно просто.
Правда, не совсем понятно, как правильно доставлять базу на сервера. Все-таки 12 Мб в сжатом виде — достаточно большой размер для упаковки в deb- или rpm-пакет, а полная (не lite) версия базы весит еще больше. Как бы вы предложили решить эту проблему?
Метки: Scala, Функциональное программирование.
Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.