发现了一比较好的本地ip对应地址的库资源文件--做一下笔记。
官方网站 https://dev.maxmind.com/geoip/geoip2/geolite2/
这里提供了免费的库文件,还有很好的api支持。
(国内也用一个叫www.ipip.net 也有类似的)
第一、java 获取IP地址
public static String getRemortIP(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
if (ip.contains(",")) {
ip = ip.split(",")[0];
}
return ip;
}
第二、使用geoip2先引入他的jar
<dependency>
<groupId>com.maxmind.geoip2</groupId>
<artifactId>geoip2</artifactId>
<version>2.8.1</version>
</dependency>
第三、下载geoip2的库文件,并解压
下载库文件
解压后的文件
第四、上代码
public static void main(String[] args) {
try {
// 创建 GeoLite2 数据库
File database = new File("C:\\Users\\Administrator\\Desktop\\GeoLite2-City_20180306\\GeoLite2-City.mmdb");
// 读取数据库内容
DatabaseReader reader = new DatabaseReader.Builder(database).build();
InetAddress ipAddress = InetAddress.getByName("43.243.12.185");
// 获取查询结果
CityResponse response = reader.city(ipAddress);
System.out.println(JSONObject.fromObject(response));
// 获取国家信息
Country country = response.getCountry();
System.out.println(country.getIsoCode());
System.out.println(country.getName());
System.out.println(country.getNames().get("zh-CN"));
// 获取省份
Subdivision subdivision = response.getMostSpecificSubdivision();
System.out.println(subdivision.getName());
System.out.println(subdivision.getIsoCode());
System.out.println(subdivision.getNames().get("zh-CN"));
// 获取城市
City city = response.getCity();
System.out.println(city.getName());
Postal postal = response.getPostal();
System.out.println(postal.getCode());
System.out.println(city.getNames().get("zh-CN"));
//获取坐标
Location location = response.getLocation();
System.out.println(location.getLatitude());
System.out.println(location.getLongitude());
} catch (Exception e) {
// TODO: handle exception
}
}
第五、如果想在项目中使用可以将他封装成一个工具类
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.util.Arrays;
import java.util.concurrent.locks.ReentrantLock;
import com.maxmind.geoip2.DatabaseReader;
import com.maxmind.geoip2.model.CityResponse;
import com.maxmind.geoip2.record.City;
import com.maxmind.geoip2.record.Country;
import com.maxmind.geoip2.record.Subdivision;
public class IpAddress {
private static DatabaseReader reader;
private static ReentrantLock lock = new ReentrantLock();
static {
load();
}
public static String findOne(String ip) {
String[] ipAddrs = find(ip);
if (ipAddrs != null && ipAddrs.length > 0) {
StringBuilder addrBuilder = new StringBuilder();
for (String addr : ipAddrs) {
addrBuilder.append(addr);
}
return addrBuilder.toString();
}
return null;
}
public static String[] find(String ip) {
try {
String addr[] = new String[3];
InetAddress ipAddress = InetAddress.getByName(ip);
// 获取查询结果
CityResponse response = reader.city(ipAddress);
// 获取国家名称
Country country = response.getCountry();
addr[0] = country.getNames().get("zh-CN");
// 获取省分名称
Subdivision subdivision = response.getMostSpecificSubdivision();
addr[1] = subdivision.getNames().get("zh-CN");
// 获取城市名称
City city = response.getCity();
addr[2] = city.getNames().get("zh-CN");
return addr;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void load() {
lock.lock();
// 创建 GeoLite2 数据库
InputStream database = IpAddress.class
.getResourceAsStream("/files/GeoLite2-City.mmdb");
// 读取数据库内容
try {
reader = new DatabaseReader.Builder(database).build();
} catch (IOException e) {
e.printStackTrace();
} finally {
lock.unlock();
try {
if (null != database) {
database.close();
}
} catch (IOException e) {
}
}
}
public static void main(String args[]) {
Long st = System.nanoTime();
System.out.println(Arrays.toString(IpAddress.find("43.243.12.185")));
System.out.println(IpAddress.findOne("111.23.106.179"));
System.out.println(IpAddress.findOne("182.131.12.12"));
Long et = System.nanoTime();
System.out.println((et - st));
}
}
使用性能还是相当高的,一个查询基本是1ms内