How to Retrieve IP Geolocation in Java with ip2region – Step‑by‑Step Guide
This article explains how to obtain a user's IP address in Java, map it to its geographic location using the ip2region library, and integrate the solution into a backend project with Maven, complete code examples, and details on the library's three query algorithms.
Recently the platform added an IP location feature that shows the user's region when posting, commenting, or chatting. This tutorial demonstrates how to acquire the IP address in Java and convert it to geographic information.
Getting the IP Address
Use the
HttpServletRequest(or
ServerHttpRequest) to read the client IP from request headers. The typical headers are:
X-Forwarded-For : a chain of IPs added by proxies; the leftmost IP is the original client.
X-Real-IP : usually contains the real client IP.
Proxy-Client-IP : added by Apache when acting as a proxy.
WL-Proxy-Client-IP : added by WebLogic plugins.
The following utility class extracts the most reliable IP address:
<code>public class IpUtil {
public static String getIpAddr(ServerHttpRequest request) {
HttpHeaders headers = request.getHeaders();
String ipAddress = headers.getFirst("X-Forwarded-For");
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = headers.getFirst("Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = headers.getFirst("WL-Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getRemoteAddress().getAddress().getHostAddress();
if (ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")) {
try {
InetAddress inet = InetAddress.getLocalHost();
ipAddress = inet.getHostAddress();
} catch (UnknownHostException e) {
log.error("Failed to get local IP", e);
}
}
}
if (ipAddress != null && ipAddress.indexOf(",") > 0) {
ipAddress = ipAddress.split(",")[0];
}
return ipAddress;
}
}
</code>Choosing an IP Geolocation Library
The original Taobao IP service is no longer available, so the tutorial switches to ip2region , an offline database with 99.9% accuracy, millisecond‑level query speed, and a size of only a few megabytes. It supports many languages (Java, PHP, C, Python, Node.js, Go, C#) and offers three built‑in query algorithms.
ip2region Data and Algorithms
Data format:
_cityId|country|region|province|city|ISP_. For Chinese IPs the city field is filled; for other countries only the country may be present.
Memory : loads the whole database into memory; fastest (≈0.1 ms per query).
Binary : binary search on the file; no memory load required (≈0.x ms).
B‑tree : B‑tree search on the file; slightly faster than binary (≈0.x ms).
Integrating ip2region
Add the Maven dependency:
<code><dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
<version>1.7.2</version>
</dependency>
</code>Place the
ip2region.dbfile in the
resourcesdirectory and load it in a utility class:
<code>static {
dbPath = createFtlFileByFtlArray() + "ip2region.db";
try {
config = new DbConfig();
searcher = new DbSearcher(config, dbPath);
} catch (Exception e) {
e.printStackTrace();
}
}
</code>Query the database using the chosen algorithm (B‑tree shown here):
<code>public static String getCityInfo(String ip) {
if (StringUtils.isEmpty(dbPath)) {
log.error("Invalid ip2region.db file");
return null;
}
if (config == null || searcher == null) {
log.error("DbSearcher or DbConfig is null");
return null;
}
int algorithm = DbSearcher.BTREE_ALGORITHM;
try {
Method method = null;
switch (algorithm) {
case DbSearcher.BTREE_ALGORITHM:
method = searcher.getClass().getMethod("btreeSearch", String.class);
break;
case DbSearcher.BINARY_ALGORITHM:
method = searcher.getClass().getMethod("binarySearch", String.class);
break;
case DbSearcher.MEMORY_ALGORITYM:
method = searcher.getClass().getMethod("memorySearch", String.class);
break;
}
DataBlock dataBlock = (DataBlock) method.invoke(searcher, ip);
String ipInfo = dataBlock.getRegion();
if (!StringUtils.isEmpty(ipInfo)) {
ipInfo = ipInfo.replace("|0", "").replace("0|", "");
}
return ipInfo;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
</code>Wrap the result to return a user‑friendly location (province for China, country otherwise):
<code>/**
* Get IP location
*/
public static String getIpPossession(String ip) {
String cityInfo = getCityInfo(ip);
if (!StringUtils.isEmpty(cityInfo)) {
cityInfo = cityInfo.replace("|", " ");
String[] cityList = cityInfo.split(" ");
if (cityList.length > 0) {
if ("中国".equals(cityList[0])) {
if (cityList.length > 1) {
return cityList[1];
}
}
return cityList[0];
}
}
return "未知";
}
</code>Running the
mainmethod shows the correct province or country for the given IP address.
Project Link
GitHub repository: https://github.com/lionsoul2014/ip2region
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.