java实现根据ip地址获取地理位置
最近项目某个功能需要根据ip地址从第三方接口获取详细的地理位置,从网上找了很多例子,主要接口有新浪的,淘宝的,腾讯的。试了淘宝的,如果是数量级小的还可以,如果数量级达到上十万级就速度慢了,会导致系统崩溃。下面例子是新浪的,例子不是适合每个项目,需要改一下.
/**
ipSearchUrl=http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=js&ip=(这是新浪的接口地址)
在项目中新浪的接口地址没有直接写死,而是去读属性文件。
*/
publicstaticStringgetIpInfoBySina(Stringip){
//读取属性文件(属性文件key-value和格式)
finalStringPROP_IPSEARCHURL="ipSearchUrl";
finalStringRET_SUCCESS="1";
finalStringRET="ret";
finalStringPROVINCE="province";
finalStringCITY="city";
finalStringDISTRICT="district";
finalStringISP="isp";
StringipAddress="";
if(StringUtils.isBlank(ip)){
returnnull;
}
Stringurl=SystemParamPropertyUtils.getSystemParamKeyValue(PROP_IPSEARCHURL);//这个是从属性文件中获取url,即新浪接口地址
if(StringUtils.isNotBlank(url)){
Stringpath=url+ip;//"http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=js&ip="+ip;
HttpClienthttpClient=newHttpClient();
Map<String,String>paramMap=newHashMap<String,String>();
StringremoteIpInfo="";
try{
remoteIpInfo=HttpClientUtil.request(httpClient,path,paramMap,"sina");
}catch(Exceptione){
e.printStackTrace();
}
if(StringUtils.isNotBlank(remoteIpInfo)){
String_ret=searchValue(remoteIpInfo,RET);
if(RET_SUCCESS.equals(_ret)){
StringprovinceName=searchValue(remoteIpInfo,PROVINCE);
StringcityName=searchValue(remoteIpInfo,CITY);
Stringdistrict=searchValue(remoteIpInfo,DISTRICT);
Stringisp=searchValue(remoteIpInfo,ISP);
ipAddress=provinceName+cityName+district+isp;
}
}
}
returnipAddress;
}
privatestaticStringsearchValue(StringremoteIpInfo,Stringkey){
String_value="";
if(StringUtils.isNotBlank(remoteIpInfo)){
_value=StringUtils.substringBetween(remoteIpInfo,"\""+key+"\":",",");
if(StringUtils.isNotBlank(_value)){
_value=UnicodeUtils.decodeUnicode(_value);
}
}
return_value;
}
读新浪的接口地址很快,我本人测试到了九万条左右,十分钟。淘宝的话一个多小时,五万多条。还有一个小技巧,就是把读到的ip存到map中,然后下次读的话就直接从map取出,这样快很多。这个会衍生出很多问题,当日志文件达到百万级,千万级,怎么解决。类似淘宝这样的,一秒多少订单,每个订单ip不一样。我不知道怎么解决。有大神知道回我一下。
下面是用淘宝的。
importjava.io.BufferedReader;
importjava.io.DataOutputStream;
importjava.io.IOException;
importjava.io.InputStreamReader;
importjava.io.UnsupportedEncodingException;
importjava.net.HttpURLConnection;
importjava.net.URL;
/**
*根据IP地址获取详细的地域信息
*@authorLwl
*@dateJan26,2016
*/
publicclassAddressUtils{
/**
*
*@paramcontent
*请求的参数格式为:name=xxx&pwd=xxx
*@paramencoding
*服务器端请求编码。如GBK,UTF-8等
*@return
*@throwsUnsupportedEncodingException
*/
publicStringgetAddresses(Stringcontent,StringencodingString)
throwsUnsupportedEncodingException{
//这里调用pconline的接口
StringurlStr="http://ip.taobao.com/service/getIpInfo.php";
//从http://whois.pconline.com.cn取得IP所在的省市区信息
StringreturnStr=this.getResult(urlStr,content,encodingString);
if(returnStr!=null){
//处理返回的省市区信息
System.out.println(returnStr);
String[]temp=returnStr.split(",");
if(temp.length<3){
return"0";//无效IP,局域网测试
}
Stringregion=(temp[5].split(":"))[1].replaceAll("\"","");
region=decodeUnicode(region);//省份
Stringcountry="";
Stringarea="";
//Stringregion="";
Stringcity="";
Stringcounty="";
Stringisp="";
for(inti=0;i<temp.length;i++){
switch(i){
case1:
country=(temp[i].split(":"))[2].replaceAll("\"","");
country=decodeUnicode(country);//国家
break;
case3:
area=(temp[i].split(":"))[1].replaceAll("\"","");
area=decodeUnicode(area);//地区
break;
case5:
region=(temp[i].split(":"))[1].replaceAll("\"","");
region=decodeUnicode(region);//省份
break;
case7:
city=(temp[i].split(":"))[1].replaceAll("\"","");
city=decodeUnicode(city);//市区
break;
case9:
county=(temp[i].split(":"))[1].replaceAll("\"","");
county=decodeUnicode(county);//地区
break;
case11:
isp=(temp[i].split(":"))[1].replaceAll("\"","");
isp=decodeUnicode(isp);//ISP公司
break;
}
}
System.out.println(country+area+region+city+county+isp);
returnnewStringBuffer(country).append(area).append(region).append(city).append(county).append(isp).toString();
}
returnnull;
}
/**
*@paramurlStr
*请求的地址
*@paramcontent
*请求的参数格式为:name=xxx&pwd=xxx
*@paramencoding
*服务器端请求编码。如GBK,UTF-8等
*@return
*/
privateStringgetResult(StringurlStr,Stringcontent,Stringencoding){
URLurl=null;
HttpURLConnectionconnection=null;
try{
url=newURL(urlStr);
connection=(HttpURLConnection)url.openConnection();//新建连接实例
connection.setConnectTimeout(2000);//设置连接超时时间,单位毫秒
connection.setReadTimeout(33000);//设置读取数据超时时间,单位毫秒
connection.setDoOutput(true);//是否打开输出流true|false
connection.setDoInput(true);//是否打开输入流true|false
connection.setRequestMethod("POST");//提交方法POST|GET
connection.setUseCaches(false);//是否缓存true|false
connection.connect();//打开连接端口
DataOutputStreamout=newDataOutputStream(connection.getOutputStream());//打开输出流往对端服务器写数据
out.writeBytes(content);//写数据,也就是提交你的表单name=xxx&pwd=xxx
out.flush();//刷新
out.close();//关闭输出流
BufferedReaderreader=newBufferedReader(newInputStreamReader(
connection.getInputStream(),encoding));//往对端写完数据对端服务器返回数据
//,以BufferedReader流来读取
StringBufferbuffer=newStringBuffer();
Stringline="";
while((line=reader.readLine())!=null){
buffer.append(line);
}
reader.close();
returnbuffer.toString();
}catch(IOExceptione){
e.printStackTrace();
}finally{
if(connection!=null){
connection.disconnect();//关闭连接
}
}
returnnull;
}
/**
*unicode转换成中文
*
*@authorfanhui2007-3-15
*@paramtheString
*@return
*/
publicstaticStringdecodeUnicode(StringtheString){
charaChar;
intlen=theString.length();
StringBufferoutBuffer=newStringBuffer(len);
for(intx=0;x<len;){
aChar=theString.charAt(x++);
if(aChar=='\\'){
aChar=theString.charAt(x++);
if(aChar=='u'){
intvalue=0;
for(inti=0;i<4;i++){
aChar=theString.charAt(x++);
switch(aChar){
case'0':
case'1':
case'2':
case'3':
case'4':
case'5':
case'6':
case'7':
case'8':
case'9':
value=(value<<4)+aChar-'0';
break;
case'a':
case'b':
case'c':
case'd':
case'e':
case'f':
value=(value<<4)+10+aChar-'a';
break;
case'A':
case'B':
case'C':
case'D':
case'E':
case'F':
value=(value<<4)+10+aChar-'A';
break;
default:
thrownewIllegalArgumentException(
"Malformedencoding.");
}
}
outBuffer.append((char)value);
}else{
if(aChar=='t'){
aChar='\t';
}elseif(aChar=='r'){
aChar='\r';
}elseif(aChar=='n'){
aChar='\n';
}elseif(aChar=='f'){
aChar='\f';
}
outBuffer.append(aChar);
}
}else{
outBuffer.append(aChar);
}
}
returnoutBuffer.toString();
}
//测试
publicstaticvoidmain(String[]args){
AddressUtilsaddressUtils=newAddressUtils();
//测试ip219.136.134.157中国=华南=广东省=广州市=越秀区=电信
Stringip="125.70.11.136";
Stringaddress="";
try{
address=addressUtils.getAddresses("ip="+ip,"utf-8");
}catch(UnsupportedEncodingExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
System.out.println(address);
//输出结果为:广东省,广州市,越秀区
}
}