SpringBoot項(xiàng)目中使用OkHttp獲取IP地址的示例代碼
前言
OkHttp 是一個(gè)由 Square 開發(fā)的高效、現(xiàn)代的 HTTP 客戶端庫,用于 Android 和 Java 應(yīng)用程序。它支持 HTTP/2 和 SPDY 等現(xiàn)代網(wǎng)絡(luò)協(xié)議,并提供了多種功能和優(yōu)化,使其成為處理網(wǎng)絡(luò)請求的流行選擇。這次項(xiàng)目中我將會(huì)使用OkHttp來發(fā)送網(wǎng)絡(luò)請求
一、OkHttp是什么?
OkHttp 是一個(gè)由 Square 開發(fā)的高效、現(xiàn)代的 HTTP 客戶端庫,用于 Android 和 Java 應(yīng)用程序。
二、使用步驟
1.OkHttp請求代碼
package com.easybbs.utils; import com.easybbs.entity.enums.ResponseCodeEnum; import com.easybbs.exception.BusinessException; import okhttp3.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.io.IOException; import java.net.ConnectException; import java.net.SocketTimeoutException; import java.security.SecureRandom; import java.security.cert.X509Certificate; import java.util.Map; import java.util.concurrent.TimeUnit; public class OKHttpUtils { /** * 請求超時(shí)時(shí)間5秒 */ private static final int TIME_OUT_SECONDS = 5; private static Logger logger = LoggerFactory.getLogger(OKHttpUtils.class); private static OkHttpClient.Builder getClientBuilder() { OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().followRedirects(false).addInterceptor(new RedirectInterceptor()).retryOnConnectionFailure(false); clientBuilder.connectTimeout(TIME_OUT_SECONDS, TimeUnit.SECONDS).readTimeout(TIME_OUT_SECONDS, TimeUnit.SECONDS); clientBuilder.sslSocketFactory(createSSLSocketFactory()).hostnameVerifier((hostname, session) -> true); return clientBuilder; } private static Request.Builder getRequestBuilder(Map<String, String> header) { Request.Builder requestBuilder = new Request.Builder(); if (null != header) { for (Map.Entry<String, String> map : header.entrySet()) { String key = map.getKey(); String value; if (map.getValue() == null) { value = ""; } else { value = map.getValue(); } requestBuilder.addHeader(key, value); } } return requestBuilder; } private static FormBody.Builder getBuilder(Map<String, String> params) { FormBody.Builder builder = new FormBody.Builder(); if (params == null) { return builder; } for (Map.Entry<String, String> map : params.entrySet()) { String key = map.getKey(); String value; if (map.getValue() == null) { value = ""; } else { value = map.getValue(); } builder.add(key, value); } return builder; } public static String getRequest(String url) throws BusinessException { ResponseBody responseBody = null; try { OkHttpClient.Builder clientBuilder = getClientBuilder(); Request.Builder requestBuilder = getRequestBuilder(null); OkHttpClient client = clientBuilder.build(); Request request = requestBuilder.url(url).build(); Response response = client.newCall(request).execute(); responseBody = response.body(); return responseBody.string(); } catch (SocketTimeoutException | ConnectException e) { logger.error("OKhttp POST 請求超時(shí),url:{}", url, e); throw new BusinessException(ResponseCodeEnum.CODE_900); } catch (Exception e) { logger.error("OKhttp GET 請求異常", e); return null; } finally { if (responseBody != null) { responseBody.close(); } } } public static String postRequest(String url, Map<String, String> header, Map<String, String> params) throws BusinessException { ResponseBody responseBody = null; try { OkHttpClient.Builder clientBuilder = getClientBuilder(); Request.Builder requestBuilder = getRequestBuilder(header); FormBody.Builder builder = getBuilder(params); OkHttpClient client = clientBuilder.build(); RequestBody requestBody = builder.build(); Request request = requestBuilder.url(url).post(requestBody).build(); Response response = client.newCall(request).execute(); responseBody = response.body(); String responseStr = responseBody.string(); return responseStr; } catch (SocketTimeoutException | ConnectException e) { logger.error("OKhttp POST 請求超時(shí),url:{}", url, e); throw new BusinessException(ResponseCodeEnum.CODE_900); } catch (Exception e) { logger.error("OKhttp POST 請求異常,url:{}", url, e); return null; } finally { if (responseBody != null) { responseBody.close(); } } } private static SSLSocketFactory createSSLSocketFactory() { SSLSocketFactory ssfFactory = null; try { SSLContext sc = SSLContext.getInstance("TLSv1.2"); sc.init(null, new TrustManager[]{new TrustAllCerts()}, new SecureRandom()); ssfFactory = sc.getSocketFactory(); } catch (Exception e) { e.printStackTrace(); } return ssfFactory; } } class TrustAllCerts implements X509TrustManager { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) { } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } } class RedirectInterceptor implements Interceptor { private static Logger logger = LoggerFactory.getLogger(RedirectInterceptor.class); @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); Response response = chain.proceed(request); int code = response.code(); if (code == 307 || code == 301 || code == 302) { //獲取重定向的地址 String location = response.headers().get("Location"); logger.info("重定向地址,location:{}", location); //重新構(gòu)建請求 Request newRequest = request.newBuilder().url(location).build(); response = chain.proceed(newRequest); } return response; } }
2.獲取Ip地址
代碼如下(示例):這個(gè)代碼只能獲取到省份地址,具體信息請看下面的詳細(xì)訪問
public String getIpAddress(String ip){ try { String url = "http://whois.pconline.com.cn/ipJson.jsp?json=true&ip=" + ip; String responseJson = OKHttpUtils.getRequest(url); if(null == responseJson){ return Constants.NO_ADDRESS; } Map<String,String> addressInfo = JsonUtils.convertJson2Obj(responseJson,Map.class); return addressInfo.get("pro"); }catch (Exception e){ logger.error("獲取ip地址失敗",e); } return Constants.NO_ADDRESS; }
3.Controller層獲取Ip地址
@RequestMapping("/login") public String login(HttpServletRequest request){ String ip = getIpAddr(request) return getIpAddress(ip); } /** * 獲取客戶端IP地址 * 由于客戶端的IP地址可能通過多個(gè)代理層轉(zhuǎn)發(fā),因此需要檢查多個(gè)HTTP頭字段以獲取真實(shí)IP。 * 此方法首先檢查“x-forwarded-for”頭,這是最常用的代理頭,然后嘗試其他不那么常見的頭字段。 * 如果所有嘗試都失敗,則回退到使用請求的遠(yuǎn)程地址。 * * @param request HttpServletRequest對(duì)象,用于獲取客戶端IP地址。 * @return 客戶端的IP地址字符串。如果無法確定客戶端IP,則返回請求的遠(yuǎn)程地址。 */ protected String getIpAddr(HttpServletRequest request) { // 嘗試獲取“x-forwarded-for”頭,這是最常用的代理頭字段。 String ip = request.getHeader("x-forwarded-for"); // 檢查“x-forwarded-for”頭是否有效,并提取第一個(gè)IP地址。 if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) { // 多次反向代理后會(huì)有多個(gè)ip值,第一個(gè)ip才是真實(shí)ip if (ip.indexOf(",") != -1) { ip = ip.split(",")[0]; } } // 如果“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.getHeader("HTTP_CLIENT_IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_X_FORWARDED_FOR"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("X-Real-IP"); } // 如果所有代理頭字段都無效,回退到使用請求的遠(yuǎn)程地址作為客戶端IP。 if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } // 返回獲取到的IP地址,無論它是通過代理頭還是直接從請求中獲取。 return ip; }
獲取信息如上,可以自行獲取其他信息
總結(jié)
本次項(xiàng)目總結(jié)如何獲取Ip地址
到此這篇關(guān)于SpringBoot項(xiàng)目中使用OkHttp獲取IP地址的示例代碼的文章就介紹到這了,更多相關(guān)SpringBoot OkHttp獲取IP地址內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot發(fā)送郵件功能 驗(yàn)證碼5分鐘過期
這篇文章主要為大家詳細(xì)介紹了SpringBoot發(fā)送郵件功能,驗(yàn)證碼5分鐘過期,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-03-03SpringMVC 通過commons-fileupload實(shí)現(xiàn)文件上傳功能
這篇文章主要介紹了SpringMVC 通過commons-fileupload實(shí)現(xiàn)文件上傳,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02Java實(shí)現(xiàn)遞歸查詢樹結(jié)構(gòu)的示例代碼
我們在實(shí)際開發(fā)中,肯定會(huì)用到樹結(jié)構(gòu),如部門樹、菜單樹等等。Java后臺(tái)利用遞歸思路進(jìn)行構(gòu)建樹形結(jié)構(gòu)數(shù)據(jù),返回給前端,能以下拉菜單等形式進(jìn)行展示。今天,咱們就來說說怎么樣將List集合轉(zhuǎn)換成TreeList2022-11-11Java中Stream實(shí)現(xiàn)List排序的六個(gè)核心技巧總結(jié)
這篇文章主要介紹了Java中Stream實(shí)現(xiàn)List排序的六個(gè)核心技巧,分別是自然序排序、反向排序、空值安全處理、多字段組合排序、并行流加速、原地排序等,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-04-04JDK動(dòng)態(tài)代理之ProxyGenerator生成代理類的字節(jié)碼文件解析
這篇文章主要為大家詳細(xì)介紹了JDK動(dòng)態(tài)代理之ProxyGenerator生成代理類的字節(jié)碼文件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02