Java使用ip2region獲取用戶的ip歸屬地的詳細(xì)步驟
1. ip2region 簡介
ip2region 是一個離線IP地址定位庫和IP定位數(shù)據(jù)管理框架,能實現(xiàn)10微秒級別的查詢效率,提供了眾多主流編程語言的xdb數(shù)據(jù)生成和查詢客戶端實現(xiàn)。
每個 ip 數(shù)據(jù)段的 region 信息都固定了格式:國家|區(qū)域|省份|城市|ISP,只有中國的數(shù)據(jù)絕大部分精確到了城市,其他國家部分?jǐn)?shù)據(jù)只能定位到國家,后前的選項全部是0。
2. 使用步驟
2.1 下載資源
下載 ip2region 后,將ip2region.xdb (如下圖)復(fù)制到項目的resources/ipdb
文件夾下。
2.2 引入依賴
<dependency> <groupId>org.lionsoul</groupId> <artifactId>ip2region</artifactId> <version>2.6.5</version> </dependency>
2.3 編寫工具類
2.3.1 獲取 IP 地址
根據(jù)用戶請求獲取用戶真實 IP 地址:
/** * 在 Nginx 等代理之后獲取用戶真實 IP 地址 * @return 用戶的真實 IP 地址 */ public static String getIpAddress(HttpServletRequest request) { if (request == null) { return null; } String ip = request.getHeader("x-forwarded-for"); if (isIpaddress(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (isIpaddress(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (isIpaddress(ip)) { ip = request.getHeader("HTTP_CLIENT_IP"); } if (isIpaddress(ip)) { ip = request.getHeader("HTTP_X_FORWARDED_FOR"); } if (isIpaddress(ip)) { ip = request.getRemoteAddr(); if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) { //根據(jù)網(wǎng)卡取本機配置的IP try { InetAddress inet = InetAddress.getLocalHost(); ip = inet.getHostAddress(); } catch (UnknownHostException e) { e.printStackTrace(); } } } return ip; }
如果有使用 Nginx 等代理服務(wù)器則需進行配置[云筆記系統(tǒng)沒有配置也可以正常使用],例如在nginx.conf
文件中進行如下配置:
location / { proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; }
其中
- Host:獲取客戶端(client)的真實域名和端口號
- X-Real-IP:獲取客戶端真實 IP 地址
- X-Forwarded-For:也是獲取客戶端真實 IP 地址,如果有多層代理時會獲取客戶端真實 IP 及每層代理服務(wù)器的 IP 地址
- X-Forwarded-Proto:獲取客戶端的真實協(xié)議(如 http、https)
getRemoteAddr()
用于獲取沒有代理服務(wù)器情況下用戶的 IP 地址- 當(dāng)用戶的請求經(jīng)過一個代理服務(wù)器后到達(dá)最終服務(wù)器,此時在最終服務(wù)器端通過
getRemoteAddr()
只能得到代理服務(wù)器的 IP 地址,通過在代理服務(wù)器中配置proxy_set_header X-Real-IP $remote_addr
,最終的服務(wù)器可以通過X-Real-IP
獲取用戶的真實 IP 地址。 - 當(dāng)用戶的請求經(jīng)過多個代理服務(wù)器后到達(dá)最終服務(wù)器時,配置
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for
后可通過X-Forwarded-For
獲取用戶真實 IP 地址(請求通過第一臺 nginx時:X-Forwarded-For = X-Real-IP = 用戶真實 IP 地址;請求通過第二臺 nginx 時:X-Forwarded-For = 用戶真實 IP 地址, X-Real-IP = 上一臺 nginx 的 IP 地址 )。 - 獲取客戶端的IP地址不僅可以通過
proxy_set_header X-real-ip $remote_addr;
獲取,也可以通過proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
獲取。
2.3.2 根據(jù) IP 地址獲取 IP 歸屬地
/** * 根據(jù) IP 地址返回歸屬地,國內(nèi)返回但省份,國外返回到國家 * @param ip IP 地址 * @return IP 歸屬地 */ public static String getIpRegion(String ip) { initIp2regionResource(); HashMap<String, String> cityInfo = new HashMap<>(); String searchIpInfo = getCityInfo(ip); //------------------------------------------------------- //searchIpInfo 的數(shù)據(jù)格式: 國家|區(qū)域|省份|城市|ISP //192.168.31.160 0|0|0|內(nèi)網(wǎng)IP|內(nèi)網(wǎng)IP //47.52.236.180 中國|0|香港|0|阿里云 //220.248.12.158 中國|0|上海|上海市|聯(lián)通 //164.114.53.60 美國|0|華盛頓|0|0 //------------------------------------------------------- String[] splitIpInfo = searchIpInfo.split("\\|"); cityInfo.put("ip",ip); cityInfo.put("searchInfo", searchIpInfo); cityInfo.put("country",splitIpInfo[0]); cityInfo.put("region",splitIpInfo[1]); cityInfo.put("province",splitIpInfo[2]); cityInfo.put("city",splitIpInfo[3]); cityInfo.put("ISP",splitIpInfo[3]); //--------------國內(nèi)屬地返回省份-------------- if ("中國".equals(cityInfo.get("country"))){ return cityInfo.get("province"); } //------------------內(nèi)網(wǎng) IP---------------- if ("0".equals(cityInfo.get("country"))){ if ("內(nèi)網(wǎng)IP".equals(cityInfo.get("ISP"))){ return ""; } else return ""; } //--------------國外屬地返回國家-------------- else { return cityInfo.get("country"); } }
2.3.3 完整代碼
IPUtils.java3:
import org.lionsoul.ip2region.xdb.Searcher; import org.springframework.core.io.ClassPathResource; import org.springframework.stereotype.Component; import org.springframework.util.FileCopyUtils; import javax.annotation.PostConstruct; import javax.servlet.http.HttpServletRequest; import java.io.InputStream; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.HashMap; @Component public class IPUtils { private static Searcher searcher; /** * 在 Nginx 等代理之后獲取用戶真實 IP 地址 * @return 用戶的真實 IP 地址 */ public static String getIpAddress(HttpServletRequest request) { if (request == null) { return null; } String ip = request.getHeader("x-forwarded-for"); if (isIpaddress(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (isIpaddress(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (isIpaddress(ip)) { ip = request.getHeader("HTTP_CLIENT_IP"); } if (isIpaddress(ip)) { ip = request.getHeader("HTTP_X_FORWARDED_FOR"); } if (isIpaddress(ip)) { ip = request.getRemoteAddr(); if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) { //根據(jù)網(wǎng)卡取本機配置的IP try { InetAddress inet = InetAddress.getLocalHost(); ip = inet.getHostAddress(); } catch (UnknownHostException e) { e.printStackTrace(); } } } return ip; } /** * 判斷是否為 IP 地址 * @param ip IP 地址 */ public static boolean isIpaddress(String ip) { return ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip); } /** * 獲取本地 IP 地址 * @return 本地 IP 地址 */ public static String getHostIp() { try { return InetAddress.getLocalHost().getHostAddress(); } catch (UnknownHostException e) { e.printStackTrace(); } return "127.0.0.1"; } /** * 獲取主機名 * @return 本地主機名 */ public static String getHostName() { try { return InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException e) { e.printStackTrace(); } return "未知"; } /** * 根據(jù) IP 地址從 ip2region.db 中獲取地理位置 * @param ip IP 地址 * @return IP歸屬地 */ public static String getCityInfo(String ip) { try { return searcher.search(ip); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 在服務(wù)啟動時加載 ip2region.db 到內(nèi)存中 * 解決打包 jar 后找不到 ip2region.db 的問題 * @throws Exception 出現(xiàn)異常應(yīng)該直接拋出終止程序啟動,避免后續(xù) invoke 時出現(xiàn)更多錯誤 */ @PostConstruct private static void initIp2regionResource() { try { InputStream inputStream = new ClassPathResource("/ipdb/ip2region.xdb").getInputStream(); byte[] dbBinStr = FileCopyUtils.copyToByteArray(inputStream); // 創(chuàng)建一個完全基于內(nèi)存的查詢對象 searcher = Searcher.newWithBuffer(dbBinStr); } catch (Exception e) { e.printStackTrace(); } } /** * 根據(jù) IP 地址返回歸屬地,國內(nèi)返回但省份,國外返回到國家 * @param ip IP 地址 * @return IP 歸屬地 */ public static String getIpRegion(String ip) { initIp2regionResource(); HashMap<String, String> cityInfo = new HashMap<>(); String searchIpInfo = getCityInfo(ip); //------------------------------------------------------- //searchIpInfo 的數(shù)據(jù)格式: 國家|區(qū)域|省份|城市|ISP //192.168.31.160 0|0|0|內(nèi)網(wǎng)IP|內(nèi)網(wǎng)IP //47.52.236.180 中國|0|香港|0|阿里云 //220.248.12.158 中國|0|上海|上海市|聯(lián)通 //164.114.53.60 美國|0|華盛頓|0|0 //------------------------------------------------------- String[] splitIpInfo = searchIpInfo.split("\\|"); cityInfo.put("ip",ip); cityInfo.put("searchInfo", searchIpInfo); cityInfo.put("country",splitIpInfo[0]); cityInfo.put("region",splitIpInfo[1]); cityInfo.put("province",splitIpInfo[2]); cityInfo.put("city",splitIpInfo[3]); cityInfo.put("ISP",splitIpInfo[3]); //--------------國內(nèi)屬地返回省份-------------- if ("中國".equals(cityInfo.get("country"))){ return cityInfo.get("province"); } //------------------內(nèi)網(wǎng) IP---------------- if ("0".equals(cityInfo.get("country"))){ if ("內(nèi)網(wǎng)IP".equals(cityInfo.get("ISP"))){ return ""; } else return ""; } //--------------國外屬地返回國家-------------- else { return cityInfo.get("country"); } } }
2.4 結(jié)果測試
測試代碼:
@Test public void test04(){ System.out.println(IPUtils.getIpRegion("117.28.182.162")); }
測試結(jié)果:
福建省
到此這篇關(guān)于Java使用ip2region獲取用戶的ip歸屬地的詳細(xì)步驟的文章就介紹到這了,更多相關(guān)Java ip2region獲取IP歸屬地內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot應(yīng)用啟動內(nèi)置Tomcat的過程源碼分析
這篇文章主要介紹了SpringBoot應(yīng)用啟動內(nèi)置Tomcat的過程分析,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-07-07JetBrains IntelliJ IDEA 2020安裝與使用教程詳解
這篇文章主要介紹了JetBrains IntelliJ IDEA 2020安裝與使用教程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-06-06基于spring boot排除掃描類的三種方式小結(jié)
這篇文章主要介紹了spring boot排除掃描類的三種方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08JAVA PDF操作之實現(xiàn)截取N頁和多個PDF合并
這篇文章主要為大家詳細(xì)介紹了java關(guān)于PDF的一些操作,例如截取N頁并生成新文件,轉(zhuǎn)圖片以及多個PDF合并,文中的示例代碼講解詳細(xì),感興趣的可以了解下2025-01-01SpringBoot之@ConditionalOnProperty注解使用方法
在平時業(yè)務(wù)中,我們需要在配置文件中配置某個屬性來決定是否需要將某些類進行注入,讓Spring進行管理,而@ConditionalOnProperty能夠?qū)崿F(xiàn)該功能,文中有詳細(xì)的代碼示例,需要的朋友可以參考下2023-05-05maven的settings.xml、pom.xml配置文件使用詳解
本文詳解了Maven中的配置文件settings.xml和pom.xml,闡述了它們的作用、配置項以及優(yōu)先級順序,settings.xml存在于Maven安裝目錄和用戶目錄下,分別作用于全局和當(dāng)前用戶,pom.xml位于項目根路徑下2024-09-09Elasticsearch?percolate?查詢示例詳解
這篇文章主要為大家介紹了Elasticsearch?percolate?查詢示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-01-01Java畢業(yè)設(shè)計之多用戶宿舍管理系統(tǒng)的實現(xiàn)
這篇文章主要介紹了基于Java實現(xiàn)的多用戶宿舍管理系統(tǒng),本文采用了jsp、servlet、jdbc等技術(shù),文中示例代碼講解詳細(xì),需要的可以參考一下2022-02-02