SpringBoot項目中獲取IP地址的實現(xiàn)示例
前言
OkHttp 是一個由 Square 開發(fā)的高效、現(xiàn)代的 HTTP 客戶端庫,用于 Android 和 Java 應(yīng)用程序。它支持 HTTP/2 和 SPDY 等現(xiàn)代網(wǎng)絡(luò)協(xié)議,并提供了多種功能和優(yōu)化,使其成為處理網(wǎng)絡(luò)請求的流行選擇。這次項目中我將會使用OkHttp來發(fā)送網(wǎng)絡(luò)請求
一、OkHttp是什么?
OkHttp 是一個由 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 {
/**
* 請求超時時間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 請求超時,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 請求超時,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地址
代碼如下(示例):這個代碼只能獲取到省份地址,具體信息請看下面的詳細(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地址可能通過多個代理層轉(zhuǎn)發(fā),因此需要檢查多個HTTP頭字段以獲取真實IP。
* 此方法首先檢查“x-forwarded-for”頭,這是最常用的代理頭,然后嘗試其他不那么常見的頭字段。
* 如果所有嘗試都失敗,則回退到使用請求的遠(yuǎn)程地址。
*
* @param request HttpServletRequest對象,用于獲取客戶端IP地址。
* @return 客戶端的IP地址字符串。如果無法確定客戶端IP,則返回請求的遠(yuǎn)程地址。
*/
protected String getIpAddr(HttpServletRequest request) {
// 嘗試獲取“x-forwarded-for”頭,這是最常用的代理頭字段。
String ip = request.getHeader("x-forwarded-for");
// 檢查“x-forwarded-for”頭是否有效,并提取第一個IP地址。
if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
// 多次反向代理后會有多個ip值,第一個ip才是真實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;
}
獲取信息如上,可以自行獲取其他信息
到此這篇關(guān)于SpringBoot項目中獲取IP地址的實現(xiàn)示例的文章就介紹到這了,更多相關(guān)SpringBoot獲取IP地址內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis中Collection集合標(biāo)簽的使用詳解
這篇文章主要介紹了Mybatis中Collection集合標(biāo)簽的使用詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06
Spring MVC+FastJson+Swagger集成的完整實例教程
這篇文章主要給大家分享介紹了關(guān)于Spring MVC+FastJson+Swagger集成的完整實例教程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2018-04-04
Java Map 按key排序和按Value排序的實現(xiàn)方法
下面小編就為大家?guī)硪黄狫ava Map 按key排序和按Value排序的實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-08-08

