欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot輕松實現(xiàn)ip解析(含源碼)

 更新時間:2023年10月23日 09:39:21   作者:fking86  
IP地址一般以數(shù)字形式表示,如192.168.0.1,IP解析是將這個數(shù)字IP轉(zhuǎn)換為包含地區(qū)、城市、運營商等信息的字符串形式,如“廣東省深圳市 電信”,這樣更方便人理解和使用,本文給大家介紹了SpringBoot如何輕松實現(xiàn)ip解析,需要的朋友可以參考下

應用場景

(1)網(wǎng)站訪問分析

可以解析用戶IP地址,分析網(wǎng)站訪問量的地域分布,以便進行針對性推廣。

(2)欺詐風險控制

某地區(qū)IP地址多次進行惡意刷單、刷票等行為,可以通過IP地址解析加以攔截。

(3)限制服務區(qū)域

解析用戶IP地址,限制僅為某地區(qū)的用戶提供服務。

(4)顯示訪問者來源

在博客、論壇等,解析并顯示每個帖子的發(fā)帖人來自哪個地區(qū)。

下面帶大家實踐在spring boot 項目中獲取請求的ip與詳細地址。

示例

前期準備

引用框架:Ip2region

下載地址: https://gitee.com/lionsoul/ip2region.git

注意:如果需要離線獲取需要下載 /data/ip2region.xdb 文件

Ip2region 特性

1、IP 數(shù)據(jù)管理框架

xdb 支持億級別的 IP 數(shù)據(jù)段行數(shù),默認的 region 信息都固定了格式:國家|區(qū)域|省份|城市|ISP,缺省的地域信息默認是0。 region 信息支持完全自定義,例如:你可以在 region 中追加特定業(yè)務需求的數(shù)據(jù),例如:GPS信息/國際統(tǒng)一地域信息編碼/郵編等。也就是你完全可以使用 ip2region 來管理你自己的 IP 定位數(shù)據(jù)。

2、數(shù)據(jù)去重和壓縮

xdb 格式生成程序會自動去重和壓縮部分數(shù)據(jù),默認的全部 IP 數(shù)據(jù),生成的 ip2region.xdb 數(shù)據(jù)庫是 11MiB,隨著數(shù)據(jù)的詳細度增加數(shù)據(jù)庫的大小也慢慢增大。

3、極速查詢響應

即使是完全基于 xdb 文件的查詢,單次查詢響應時間在十微秒級別,可通過如下兩種方式開啟內(nèi)存加速查詢:

  1. vIndex 索引緩存 :使用固定的 512KiB 的內(nèi)存空間緩存 vector index 數(shù)據(jù),減少一次 IO 磁盤操作,保持平均查詢效率穩(wěn)定在10-20微秒之間。
  2. xdb 整個文件緩存:將整個 xdb 文件全部加載到內(nèi)存,內(nèi)存占用等同于 xdb 文件大小,無磁盤 IO 操作,保持微秒級別的查詢效率。

版本依賴

框架名版本號
SpringBoot3.1.4
jdk17
tomcat-embed-core10.1.8
lombok1.18.26
fastjson1.2.73
ip2region2.7.0

導入庫

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

<!--ip庫-->
<dependency>
    <groupId>org.lionsoul</groupId>
    <artifactId>ip2region</artifactId>
    <version>2.7.0</version>
</dependency>
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-core</artifactId>
    <version>10.1.8</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.26</version>
    <scope>compile</scope>
</dependency>

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.73</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
</dependency>

具體代碼

Constant

public interface Constant {

    // IP地址查詢
    public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
    /**
     * 本地ip
     */
    public static final String LOCAL_IP = "127.0.0.1";


    /**
     * 數(shù)據(jù)庫訪問地址
     */
    public static final String DB_PATH = "springboot-ip/src/main/resources/ip2region/ip2region.xdb";
}

AddressUtils(在線解析)

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;

import static com.example.springbootip.constant.Constant.IP_URL;
import static com.example.springbootip.constant.Constant.LOCAL_IP;

/**
 * @author coderJim
 * @date 2023-10-16 14:07
 */
@Slf4j
public class AddressUtils {

    // 未知地址
    public static final String UNKNOWN = "XX XX";

    public static String getRealAddressByIP(String ip) {
        String address = UNKNOWN;
        // 內(nèi)網(wǎng)不查詢
        if (ip.equals(LOCAL_IP)) {
            return "內(nèi)網(wǎng)IP";
        }
        if (true) {
            try {
                String rspStr = sendGet(IP_URL, "ip=" + ip + "&json=true" ,"GBK");
                if (StringUtils.isEmpty(rspStr)) {
                    log.error("獲取地理位置異常 {}" , ip);
                    return UNKNOWN;
                }
                JSONObject obj = JSONObject.parseObject(rspStr);
                String region = obj.getString("pro");
                String city = obj.getString("city");
                return String.format("%s %s" , region, city);
            } catch (Exception e) {
                log.error("獲取地理位置異常 {}" , ip);
            }
        }
        return address;
    }

    public static String sendGet(String url, String param, String contentType) {
        StringBuilder result = new StringBuilder();
        BufferedReader in = null;
        try {
            String urlNameString = url + "?" + param;
            log.info("sendGet - {}" , urlNameString);
            URL realUrl = new URL(urlNameString);
            URLConnection connection = realUrl.openConnection();
            connection.setRequestProperty("accept" , "*/*");
            connection.setRequestProperty("connection" , "Keep-Alive");
            connection.setRequestProperty("user-agent" , "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            connection.connect();
            in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
            log.info("recv - {}" , result);
        } catch (ConnectException e) {
            log.error("調(diào)用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
        } catch (SocketTimeoutException e) {
            log.error("調(diào)用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
        } catch (IOException e) {
            log.error("調(diào)用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);
        } catch (Exception e) {
            log.error("調(diào)用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception ex) {
                log.error("調(diào)用in.close Exception, url=" + url + ",param=" + param, ex);
            }
        }
        return result.toString();
    }
}

IpUtil(離線解析)

import static com.example.springbootip.constant.Constant.DB_PATH;
import static com.example.springbootip.constant.Constant.LOCAL_IP;

import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.lionsoul.ip2region.xdb.Searcher;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * @author coderJim
 * @date 2023-10-16 11:02
 */
@Slf4j
public class IpUtil {

    protected IpUtil(){ }

    /**
     * 獲取 IP地址
     * 使用 Nginx等反向代理軟件, 則不能通過 request.getRemoteAddr()獲取 IP地址
     * 如果使用了多級反向代理的話,X-Forwarded-For的值并不止一個,而是一串IP地址,
     * X-Forwarded-For中第一個非 unknown的有效IP字符串,則為真實IP地址
     */
    public static String getIpAddr(HttpServletRequest request) {
        String ipAddress;
        try {
            ipAddress = request.getHeader("x-forwarded-for");
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getRemoteAddr();
                if (ipAddress.equals(LOCAL_IP)) {
                    // 根據(jù)網(wǎng)卡取本機配置的IP
                    InetAddress inet = null;
                    try {
                        inet = InetAddress.getLocalHost();
                    } catch (UnknownHostException e) {
                        log.error(e.getMessage(), e);
                    }
                    ipAddress = inet.getHostAddress();
                }
            }
            // 對于通過多個代理的情況,第一個IP為客戶端真實IP,多個IP按照','分割
            if (ipAddress != null && ipAddress.length() > 15) { // "***.***.***.***".length()
                // = 15
                if (ipAddress.indexOf(",") > 0) {
                    ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
                }
            }
        } catch (Exception e) {
            ipAddress = "";
        }

        return ipAddress;
    }

    public static  String getAddr(String ip) {
        String project_dir = System.getProperty("user.dir") +"";
        String dbPath = project_dir + "/" + DB_PATH;
        // 1、從 dbPath 加載整個 xdb 到內(nèi)存。
        byte[] cBuff;
        try {
            cBuff = Searcher.loadContentFromFile(dbPath);
        } catch (Exception e) {
            log.info("failed to load content from `%s`: %s\n", dbPath, e);
            return null;
        }

        // 2、使用上述的 cBuff 創(chuàng)建一個完全基于內(nèi)存的查詢對象。
        Searcher searcher;
        try {
            searcher = Searcher.newWithBuffer(cBuff);
        } catch (Exception e) {
            log.info("failed to create content cached searcher: %s\n", e);
            return null;
        }
        // 3、查詢
        try {
            String region = searcher.search(ip);
            return region;
        } catch (Exception e) {
            log.info("failed to search(%s): %s\n", ip, e);
        }
        return null;
    }

}

IpController

import com.example.springbootip.util.AddressUtils;
import com.example.springbootip.util.IpUtil;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.*;

/**
 * @author coderJim
 */
@RestController
@RequestMapping("/demo")
public class IpController {
    
    @ResponseBody
    @GetMapping("/realAddress")
    public String realAddress(HttpServletRequest request){
        String ip = IpUtil.getIpAddr(request);
        //在線獲取
//        String realAddress = AddressUtils.getRealAddressByIP(ip);
        //離線獲取
        String realAddress = IpUtil.getAddr(ip);
        return "您的ip所在地為:"+ realAddress;
    }
}

執(zhí)行結(jié)果

運行請求 http://127.0.0.1:8080/demo/realAddress

如果執(zhí)行:

String realAddress = AddressUtils.getRealAddressByIP(ip);

顯示結(jié)果:

您的ip所在地為:浙江省 杭州市

如果執(zhí)行:

String realAddress = IpUtil.getAddr(ip);

顯示結(jié)果:

您的ip所在地為:中國|0|浙江省|杭州市|電信

總結(jié)

通過這樣的一套流程下來,我們就能實現(xiàn)對每一個請求進行ip 獲取、ip解析

以上就是SpringBoot輕松實現(xiàn)ip解析(含源碼)的詳細內(nèi)容,更多關于SpringBoot實現(xiàn)ip解析的資料請關注腳本之家其它相關文章!

相關文章

最新評論