提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言

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 {
    @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);
            //重新构建请求
            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才是真实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");
        }
        // 如果所有代理头字段都无效,回退到使用请求的远程地址作为客户端IP。
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        // 返回获取到的IP地址,无论它是通过代理头还是直接从请求中获取。
        return ip;
    }

 获取信息如上,可以自行获取其他信息


总结

本次项目总结如何获取Ip地址

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部