<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SpringBoot 快速實現(xiàn)IP地址解析

          共 7090字,需瀏覽 15分鐘

           ·

          2023-06-25 23:53


          如果使用本地ip 解析的話,我們將會借助ip2region,該項目維護(hù)了一份較為詳細(xì)的本地ip 地址對應(yīng)表,如果為了離線環(huán)境的使用,需要導(dǎo)入該項目依賴,并指定版本,不同版本的方法可能存在差異。

          <dependency>
          ????<groupId>org.lionsoulgroupId>
          ????<artifactId>ip2regionartifactId>
          ????<version>2.6.3version>
          dependency>

          官方gitee:gitee.com/lionsoul/ip…

          開發(fā)

          在使用時需要將 xdb 文件下載到工程文件目錄下,使用ip2region即使是完全基于 xdb 文件的查詢,單次查詢響應(yīng)時間在十微秒級別,可通過如下兩種方式開啟內(nèi)存加速查詢:

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

          /**
          ?*?ip查詢
          ?*/

          @Slf4j
          public?class?IPUtil?{

          ????private?static?final?String?UNKNOWN?=?"unknown";

          ????protected?IPUtil(){?}

          ????/**
          ?????*?獲取?IP地址
          ?????*?使用?Nginx等反向代理軟件,?則不能通過?request.getRemoteAddr()獲取?IP地址
          ?????*?如果使用了多級反向代理的話,X-Forwarded-For的值并不止一個,而是一串IP地址,
          ?????*?X-Forwarded-For中第一個非?unknown的有效IP字符串,則為真實IP地址
          ?????*/

          ????public?static?String?getIpAddr(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();
          ????????}
          ????????return?"0:0:0:0:0:0:0:1".equals(ip)???"127.0.0.1"?:?ip;
          ????}

          ????public?static??String?getAddr(String?ip){
          ????????String?dbPath?=?"src/main/resources/ip2region/ip2region.xdb";
          ????????// 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.searchByStr(ip);
          ????????????return?region;
          ????????}?catch?(Exception?e)?{
          ????????????log.info("failed?to?search(%s):?%s\n",?ip,?e);
          ????????}
          ????????return?null;
          ????}
          }

          這里我們將ip 解析封裝成一個工具類,包含獲取IP和ip 地址解析兩個方法,ip 的解析可以在請求中獲取。獲取到ip后,需要根據(jù)ip ,在xdb 中查找對應(yīng)的IP地址的解析,由于是本地數(shù)據(jù)庫可能存在一定的缺失,部分ip 存在無法解析的情況。

          在線解析

          如果想要獲取更加全面的ip 地址信息,可使用在線數(shù)據(jù)庫,這里提供的是 whois.pconline.com ?的IP解析,該IP解析在我的使用過程中表現(xiàn)非常流暢,而且只有少數(shù)的ip 存在無法解析的情況。

          @Slf4j
          public?class?AddressUtils?{
          ????//?IP地址查詢
          ????public?static?final?String?IP_URL?=?"http://whois.pconline.com.cn/ipJson.jsp";

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

          ????public?static?String?getRealAddressByIP(String?ip)?{
          ????????String?address?=?UNKNOWN;
          ????????//?內(nèi)網(wǎng)不查詢
          ????????if?(IpUtils.internalIp(ip))?{
          ????????????return?"內(nèi)網(wǎng)IP";
          ????????}
          ????????if?(true)?{
          ????????????try?{
          ????????????????String?rspStr?=?sendGet(IP_URL,?"ip="?+?ip?+?"&json=true"?,"GBK");
          ????????????????if?(StrUtil.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();
          ????}
          }

          場景

          那么在開發(fā)的什么流程獲取ip 地址是比較合適的,這里就要用到我們的攔截器了。攔截進(jìn)入服務(wù)的每個請求,進(jìn)行前置操作,在進(jìn)入時就完成請求頭的解析,ip 獲取以及ip 地址解析,這樣在后續(xù)流程的全環(huán)節(jié),都可以復(fù)用ip 地址等信息。


          /**
          ?*?對ip?進(jìn)行限制,防止IP大量請求
          ?*/

          @Slf4j
          @Configuration
          public?class?IpUrlLimitInterceptor?implements?HandlerInterceptor{

          ????@Override
          ????public?boolean?preHandle(HttpServletRequest?httpServletRequest,?HttpServletResponse?httpServletResponse,?Object?o)?{

          ????????//更新全局變量
          ????????Constant.IP?=?IPUtil.getIpAddr(httpServletRequest);
          ????????Constant.IP_ADDR?=?AddressUtils.getRealAddressByIP(Constant.IP);
          ????????Constant.URL?=?httpServletRequest.getRequestURI();
          ????????return?true;
          ????}

          ????@Override
          ????public?void?postHandle(HttpServletRequest?httpServletRequest,?HttpServletResponse?httpServletResponse,?Object?o,?ModelAndView?modelAndView)?{
          ????????//通過本地獲取
          ????????//????????獲得ip
          ????????//????????String?ip?=?IPUtil.getIpAddr(httpServletRequest);
          ????????//解析具體地址
          ????????//????????String?addr?=?IPUtil.getAddr(ip);

          ????????//通過在線庫獲取
          ????????//????????String?ip?=?IpUtils.getIpAddr(httpServletRequest);
          ????????//????????String?ipaddr?=?AddressUtils.getRealAddressByIP(ipAddr);
          ????????//????????log.info("IP?>>?{},Address?>>?{}",ip,ipaddr);
          ????}

          ????@Override
          ????public?void?afterCompletion(HttpServletRequest?httpServletRequest,?HttpServletResponse?httpServletResponse,?Object?o,?Exception?e)?{

          ????}
          }

          如果想要執(zhí)行我們的ip 解析攔截器,

          需要在spring boot的視圖層進(jìn)行攔截才會觸發(fā)我們的攔截器。

          @Configuration
          public?class?WebConfig?implements?WebMvcConfigurer?{
          ????@Autowired
          ????IpUrlLimitInterceptor?ipUrlLimitInterceptor;

          ????//執(zhí)行ip攔截器
          ????@Override
          ????public?void?addInterceptors(InterceptorRegistry?regivastry){
          ????????registry.addInterceptor(ipUrlLimitInterceptor)
          ????????????//?攔截所有請求
          ????????????.addPathPatterns("/**");
          ????}
          }

          來源:https://juejin.cn/post/7130544273421762573


          ·················END·················


          資料鏈接


          清華學(xué)姐自學(xué)的Linux筆記,天花板級別!
          新版鳥哥Linux私房菜資料
          阿里大佬總結(jié)的《圖解Java》火了,完整版PDF開放下載!
          Alibaba官方上線!SpringBoot+SpringCloud全彩指南
          國內(nèi)最強(qiáng)的SpringBoot+Vue全棧項目天花板,不接受反駁!


          瀏覽 102
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产毛片毛片毛片操逼视频 | 思思热在线观看视频 | 91丨国产丨精品丨丝袜 | 大香蕉网站在线 | 男人的天堂网2 |