提示:文章寫完后,目錄可以自動生成,如何生成可參考右邊的幫助文檔
文章目錄
前言
OkHttp 是一個由 Square 開發的高效、現代的 HTTP 客戶端庫,用于 Android 和 Java 應用程序。它支持 HTTP/2 和 SPDY 等現代網絡協議,并提供了多種功能和優化,使其成為處理網絡請求的流行選擇。這次項目中我將會使用OkHttp來發送網絡請求
一、OkHttp是什么?
OkHttp 是一個由 Square 開發的高效、現代的 HTTP 客戶端庫,用于 Android 和 Java 應用程序。
二、使用步驟
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 {@Overridepublic void checkClientTrusted(X509Certificate[] chain, String authType) {}@Overridepublic void checkServerTrusted(X509Certificate[] chain, String authType) {}@Overridepublic X509Certificate[] getAcceptedIssuers() {return new X509Certificate[0];}
}class RedirectInterceptor implements Interceptor {private static Logger logger = LoggerFactory.getLogger(RedirectInterceptor.class);@Overridepublic 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);//重新構建請求Request newRequest = request.newBuilder().url(location).build();response = chain.proceed(newRequest);}return response;}
}
2.獲取Ip地址
代碼如下(示例):這個代碼只能獲取到省份地址,具體信息請看下面的詳細訪問
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地址可能通過多個代理層轉發,因此需要檢查多個HTTP頭字段以獲取真實IP。* 此方法首先檢查“x-forwarded-for”頭,這是最常用的代理頭,然后嘗試其他不那么常見的頭字段。* 如果所有嘗試都失敗,則回退到使用請求的遠程地址。** @param request HttpServletRequest對象,用于獲取客戶端IP地址。* @return 客戶端的IP地址字符串。如果無法確定客戶端IP,則返回請求的遠程地址。*/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才是真實ipif (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");}// 如果所有代理頭字段都無效,回退到使用請求的遠程地址作為客戶端IP。if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getRemoteAddr();}// 返回獲取到的IP地址,無論它是通過代理頭還是直接從請求中獲取。return ip;}
?獲取信息如上,可以自行獲取其他信息
總結
本次項目總結如何獲取Ip地址