主要是免费二字深的我心,直接使用支付宝的IP信息获取接口,获取到对应的IP信息。
接口访问地址如下:
http://ip.taobao.com/service/getIpInfo.php?ip=139.189.109.174
访问获取到的JSON数据如下:
{"code":0,"data":{"ip":"139.189.109.174","country":"中国","area":"","region":"海南","city":"海口","county":"XX","isp":"电信","country_id":"CN","area_id":"","region_id":"460000","city_id":"460100","county_id":"xx","isp_id":"100017"}}
使用Java接口封装方法如下:
HttpRequestUtils.java 请求接口封装
package com.seezoon.framework.common.http;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.util.StopWatch;
import com.alibaba.fastjson.JSON;
import com.seezoon.framework.common.context.exception.ServiceException;
/**
* 对性能和参数要求敏感,需要自行利用 HttpPoolClient 对象自行构造
*
* @author hdf 2018年4月23日
*/
public class HttpRequestUtils {
/**
* 日志对象
*/
private static Logger logger = LoggerFactory.getLogger(HttpRequestUtils.class);
private static String DEFAULT_CHARSET = "UTF-8";
private static HttpPoolClient defaultHttpPoolClient = new HttpPoolClient();
public static <T> T doGet(String url, Map<String, String> params, Class<T> clazz) {
return JSON.parseObject(doGet(url, params), clazz);
}
public static <T> T doPost(String url, Map<String, String> params, Class<T> clazz) {
return JSON.parseObject(doPost(url, params), clazz);
}
public static <T> T postJson(String url, Map<String, String> params, Class<T> clazz) {
return JSON.parseObject(postJson(url, params), clazz);
}
public static String postJson(String url, Map<String, String> params) {
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new StringEntity(JSON.toJSONString(params), ContentType.APPLICATION_JSON));
return execute(httpPost);
}
public static String postXml(String url,String content) {
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new StringEntity(content, ContentType.create("application/xml", "UTF-8")));
return execute(httpPost);
}
public static String doGet(String url, Map<String, String> params) {
Assert.hasLength(url, "请求地址为空");
try {
URIBuilder builder = new URIBuilder(url);
builder.setParameters(getNameValuePair(params));
HttpGet httpGet = new HttpGet(builder.toString());
String result = execute(httpGet);
return result;
} catch (Exception e) {
throw new ServiceException(e);
}
}
public static String doPost(String url, Map<String, String> params) {
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(getUrlEncodedFormEntity(params));
return execute(httpPost);
}
public static String execute(HttpRequestBase request) {
StopWatch watch = new StopWatch();
watch.start();
CloseableHttpResponse response = null;
try {
response = defaultHttpPoolClient.execute(request);
watch.stop();
String requestURI = request.getURI().toString();
logger.debug("http client:{} comleted use {} ms",requestURI,watch.getTotalTimeMillis());
int status = response.getStatusLine().getStatusCode();
if (HttpStatus.SC_OK == status) {// 成功
HttpEntity entity = response.getEntity();
if (null != entity) {
String result = EntityUtils.toString(entity, DEFAULT_CHARSET);
EntityUtils.consume(entity);
return result;
} else {
throw new ServiceException("请求无数据返回");
}
} else {
throw new ServiceException("请求状态异常失败");
}
} catch (Exception e) {
throw new ServiceException(request.getURI().toString() + "请求失败", e);
} finally {
if (null != response) {
try {
response.close();
} catch (IOException e) {
logger.error("CloseableHttpResponse close error", e);
}
}
}
}
private static UrlEncodedFormEntity getUrlEncodedFormEntity(Map<String, String> params) {
UrlEncodedFormEntity entity = null;
try {
entity = new UrlEncodedFormEntity(getNameValuePair(params), DEFAULT_CHARSET);
} catch (UnsupportedEncodingException e) {
}
return entity;
}
private static List<NameValuePair> getNameValuePair(Map<String, String> params){
List<NameValuePair> list = new ArrayList<NameValuePair>();
if (null != params && !params.isEmpty()) {
for (Entry<String, String> entry : params.entrySet()) {
list.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
}
return list;
}
public static void shutDown() {
defaultHttpPoolClient.shutdown();
}
}
使用到的HttpPoolClient.java
package com.seezoon.framework.common.http;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.ssl.TrustStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.seezoon.framework.common.context.exception.ServiceException;
/**
* 带连接池的http client 请勿频繁实例化
*
* @author hdf 2017年10月21日 doc @see
* http://hc.apache.org/httpcomponents-client-4.5.x/tutorial/pdf/httpclient-tutorial.pdf
* http://hc.apache.org/httpcomponents-client-4.5.x/examples.html
*/
public class HttpPoolClient {
/**
* 日志对象
*/
private static Logger logger = LoggerFactory.getLogger(HttpPoolClient.class);
private HttpClientConfig httpClientConfig;
private HttpClientConnectionManager httpClientConnectionManager;
private CloseableHttpClient httpClient;
public HttpPoolClient() {
this(new HttpClientConfig());
}
public HttpPoolClient(HttpClientConfig httpClientConfig) {
this.httpClientConfig = httpClientConfig;
httpClientConnectionManager = createHttpClientConnectionManager();
httpClient = createHttpClient(httpClientConnectionManager);
}
public CloseableHttpClient getHttpClient() {
return httpClient;
}
private CloseableHttpClient createHttpClient(HttpClientConnectionManager connectionManager) {
//HttpHost proxy = new HttpHost("127.0.0.1",8889);
RequestConfig requestConfig = RequestConfig.custom()
//.setProxy(proxy)
.setConnectionRequestTimeout(httpClientConfig.getConnectionRequestTimeout())// 获取连接等待时间
.setConnectTimeout(httpClientConfig.getConnectTimeout())// 连接超时
.setSocketTimeout(httpClientConfig.getSocketTimeout())// 获取数据超时
.build();
httpClient = HttpClients.custom().setConnectionManager(httpClientConnectionManager)
.setDefaultRequestConfig(requestConfig)
.setUserAgent(httpClientConfig.getUserAgent())
.disableContentCompression().disableAutomaticRetries()
.setConnectionTimeToLive(httpClientConfig.getConnTimeToLive(), TimeUnit.MILLISECONDS)// 连接最大存活时间
.setRetryHandler(new DefaultHttpRequestRetryHandler(httpClientConfig.getRetyTimes(), true))// 重试次数
.build();
return httpClient;
}
public HttpClientConnectionManager createHttpClientConnectionManager() {
SSLContext sslContext = null;
try {
sslContext = SSLContexts.custom().loadTrustMaterial(null, new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return false;
}
}).build();
} catch (Exception e) {
throw new RuntimeException(e);
}
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext,
NoopHostnameVerifier.INSTANCE);
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", sslSocketFactory)
.build();
PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(
socketFactoryRegistry);
// 最大连接数
poolingHttpClientConnectionManager.setMaxTotal(httpClientConfig.getMaxTotal());
// 单个站点最大连接数
poolingHttpClientConnectionManager.setDefaultMaxPerRoute(httpClientConfig.getMaxPerRoute());
// 长连接
poolingHttpClientConnectionManager.setDefaultSocketConfig(
SocketConfig.custom().setSoTimeout(httpClientConfig.getSocketTimeout()).setSoKeepAlive(true).build());
// 连接不活跃多久检查毫秒 并不是100 % 可信
poolingHttpClientConnectionManager.setValidateAfterInactivity(httpClientConfig.getValidateAfterInactivity());
// 空闲扫描线程
HttpClientIdleConnectionMonitor.registerConnectionManager(poolingHttpClientConnectionManager, httpClientConfig);
return poolingHttpClientConnectionManager;
}
public void shutdown() {
HttpClientIdleConnectionMonitor.removeConnectionManager(this.httpClientConnectionManager);
this.httpClientConnectionManager.shutdown();
}
public CloseableHttpResponse execute(HttpRequestBase request) {
try {
return httpClient.execute(request);
} catch (IOException e) {
request.abort();
throw new ServiceException(e);
}
}
public CloseableHttpResponse execute(HttpRequestBase request,HttpClientContext httpClientContext) {
try {
return httpClient.execute(request,httpClientContext);
} catch (IOException e) {
request.abort();
throw new ServiceException(e);
}
}
}
HttpClientConfig.java
package com.seezoon.framework.common.http;
/**
* Http client 的默认配置项
*
* @author hdf 2018年4月20日
*/
public class HttpClientConfig {
// 连接超时 ms
private int connectTimeout = 6 * 1000;
// 获取数据超时 ms
private int socketTimeout = 6 * 1000;
// 获取连接超时ms
private int connectionRequestTimeout = 10 * 1000;
// 最大线程数
private int maxTotal = 100;
// 站点最大连接数
private int maxPerRoute = maxTotal;
// 不活跃多久检查ms
private int validateAfterInactivity = 60 * 1000;
// 重试次数 0 不重试,
private int retyTimes = 0;
// 空闲时间多久销毁ms
private int idleTimeToDead = 60 * 1000;
// 连接最多存活多久ms
private int connTimeToLive = 60 * 1000;
//清理空闲线程
private int idleScanTime = 5 * 1000;
//默认请求头
private String userAgent = "seezoon-framework " + "(" +
System.getProperty("os.name") + "/" + System.getProperty("os.version") + "/" +
System.getProperty("os.arch") + ";" + System.getProperty("java.version") + ")";
public String getUserAgent() {
return userAgent;
}
public void setUserAgent(String userAgent) {
this.userAgent = userAgent;
}
public int getConnectTimeout() {
return connectTimeout;
}
public void setConnectTimeout(int connectTimeout) {
this.connectTimeout = connectTimeout;
}
public int getSocketTimeout() {
return socketTimeout;
}
public void setSocketTimeout(int socketTimeout) {
this.socketTimeout = socketTimeout;
}
public int getConnectionRequestTimeout() {
return connectionRequestTimeout;
}
public void setConnectionRequestTimeout(int connectionRequestTimeout) {
this.connectionRequestTimeout = connectionRequestTimeout;
}
public int getMaxTotal() {
return maxTotal;
}
public void setMaxTotal(int maxTotal) {
this.maxTotal = maxTotal;
}
public int getMaxPerRoute() {
return maxPerRoute;
}
public void setMaxPerRoute(int maxPerRoute) {
this.maxPerRoute = maxPerRoute;
}
public int getValidateAfterInactivity() {
return validateAfterInactivity;
}
public void setValidateAfterInactivity(int validateAfterInactivity) {
this.validateAfterInactivity = validateAfterInactivity;
}
public int getRetyTimes() {
return retyTimes;
}
public void setRetyTimes(int retyTimes) {
this.retyTimes = retyTimes;
}
public int getIdleTimeToDead() {
return idleTimeToDead;
}
public void setIdleTimeToDead(int idleTimeToDead) {
this.idleTimeToDead = idleTimeToDead;
}
public int getConnTimeToLive() {
return connTimeToLive;
}
public void setConnTimeToLive(int connTimeToLive) {
this.connTimeToLive = connTimeToLive;
}
public int getIdleScanTime() {
return idleScanTime;
}
public void setIdleScanTime(int idleScanTime) {
this.idleScanTime = idleScanTime;
}
}
ServiceException.java 方法
package com.seezoon.framework.common.context.exception;
/**
* 自定义异常方便后续扩展
*
* @author hdf 2018年4月20日
*/
public class ServiceException extends RuntimeException {
public ServiceException() {
super();
// TODO Auto-generated constructor stub
}
public ServiceException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
public ServiceException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
public ServiceException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
public ServiceException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
}
获取IP信息接口调用方法:
if (StringUtils.isNotEmpty(ip)) {
String ipInfo = HttpRequestUtils.doGet("http://ip.taobao.com/service/getIpInfo.php", Maps.newHashMap("ip",ip));
if (StringUtils.isNotEmpty(ipInfo)) {
JSONObject parseObject = JSON.parseObject(ipInfo);
if (parseObject.containsKey("data")) {
JSONObject data = parseObject.getJSONObject("data");
loginLog.setArea(data.getString("region") + data.getString("city"));
}
}
}