Backend Development 15 min read

How to Retrieve Client IP and Use ip2region for IP Geolocation in Java

This article explains how to obtain a user's IP address from an HttpServletRequest, introduces the ip2region offline IP‑location library, demonstrates Maven integration and multiple Java query implementations—including file‑only, vector‑index, and full‑memory caching—while providing benchmark and testing instructions.

Architecture Digest
Architecture Digest
Architecture Digest
How to Retrieve Client IP and Use ip2region for IP Geolocation in Java

Background – Many Chinese platforms now display a user's IP‑derived location, and developers often need to implement similar functionality. The article starts by describing why IP location is useful and what the overall goal is.

HttpServletRequest 获取 IP – A utility class NetworkUtil is provided to extract the real client IP from various request headers (x-forwarded-for, Proxy-Client-IP, WL-Proxy-Client-IP, HTTP_CLIENT_IP, HTTP_X_FORWARDED_FOR) and fall back to request.getRemoteAddr() . It also handles localhost cases and strips multiple IPs separated by commas.

import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;

/**
 * 常用获取客户端信息的工具
 */
public class NetworkUtil {
    /** 获取ip地址 */
    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        // ... (other header checks omitted for brevity) ...
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        // handle localhost
        if ("localhost".equalsIgnoreCase(ip) || "127.0.0.1".equalsIgnoreCase(ip) || "0:0:0:0:0:0:0:1".equalsIgnoreCase(ip)) {
            try {
                InetAddress inet = InetAddress.getLocalHost();
                ip = inet.getHostAddress();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
        }
        // keep only the first IP when multiple are present
        if (ip != null && ip.length() > 15 && ip.indexOf(',') > 15) {
            ip = ip.substring(0, ip.indexOf(','));
        }
        return ip;
    }

    /** 获取mac地址 */
    public static String getMacAddress() throws Exception {
        byte[] macAddressBytes = NetworkInterface.getByInetAddress(InetAddress.getLocalHost()).getHardwareAddress();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < macAddressBytes.length; i++) {
            if (i != 0) sb.append("-");
            String s = Integer.toHexString(macAddressBytes[i] & 0xFF);
            sb.append(s.length() == 1 ? "0" + s : s);
        }
        return sb.toString().trim().toUpperCase();
    }
}

Ip2region Introduction – ip2region is an open‑source offline IP‑location library (v2.0) that provides ~99.9% accuracy by aggregating data from multiple providers (Taobao, GeoIP, CZ88). It stores region info in the format country|region|province|city|ISP and offers XDB files of about 11 MiB for the full dataset.

Features of ip2region v2.0

Standardized data format.

Data deduplication and compression.

Microsecond‑level query latency.

Support for memory‑accelerated queries via vector‑index cache (≈512 KiB) or full‑file cache.

Scalable to billions of IP segments and customizable region fields.

Java Query Client Implementation

To use ip2region in a Java project, add the Maven dependency:

<dependency>
    <groupId>org.lionsoul</groupId>
    <artifactId>ip2region</artifactId>
    <version>2.6.4</version>
</dependency>

Four usage patterns are demonstrated:

File‑only searcher – creates a Searcher directly from the XDB file.

Vector‑index cache – loads the vector index once and reuses it for each searcher, reducing one disk I/O.

Full‑memory cache – loads the entire XDB content into a byte array and creates a memory‑only searcher, safe for concurrent use.

Benchmark and test utilities – command‑line search and bench modes to verify correctness and measure performance.

import org.lionsoul.ip2region.xdb.Searcher;
import java.io.*;
import java.util.concurrent.TimeUnit;

public class SearcherTest {
    public static void main(String[] args) {
        String dbPath = "ip2region.xdb file path";
        // 1. Create searcher (file only)
        Searcher searcher = null;
        try {
            searcher = Searcher.newWithFileOnly(dbPath);
        } catch (IOException e) {
            System.out.printf("failed to create searcher with `%s`: %s\n", dbPath, e);
            return;
        }
        // 2. Query
        try {
            String ip = "1.2.3.4";
            long sTime = System.nanoTime();
            String region = searcher.search(ip);
            long cost = TimeUnit.NANOSECONDS.toMicros(System.nanoTime() - sTime);
            System.out.printf("{region: %s, ioCount: %d, took: %d μs}\n", region, searcher.getIOCount(), cost);
        } catch (Exception e) {
            System.out.printf("failed to search(%s): %s\n", ip, e);
        }
        // Note: each thread should create its own Searcher instance.
    }
}

Similar code snippets are provided for the vector‑index and full‑memory approaches, showing how to load byte[] vIndex or byte[] cBuff and create the corresponding Searcher objects.

Testing in IDEA – The article includes screenshots of running the demo in IntelliJ IDEA, confirming that domestic IPs return province/city while foreign IPs return only the country.

Compilation and Execution – Use Maven to compile the Java binding ( mvn compile package ), then run the generated JAR with commands such as java -jar target/ip2region-2.6.0.jar search --db=../../data/ip2region.xdb for interactive queries, or java -jar ... bench --db=../data/ip2region.xdb --src=../data/ip.merge.txt for performance testing.

The article concludes that with the provided utility class and ip2region library, developers can easily obtain a user's IP address and map it to geographic information, and encourages readers to explore the GitHub repository for further details.

backendJavamavenHttpServletRequestIP Geolocationip2region
Architecture Digest
Written by

Architecture Digest

Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.