JAVA服务器端获取客户端远程地址,根据IP获取远程地址,各IP地址查询接口比较
来源:互联网 发布:网络游戏排行榜 知乎 编辑:程序博客网 时间:2024/05/02 01:20
废话少说,先整代码:
一、根据远程请求,获取远程IP
/** * Copyright (c) 2016,sunnybs. * All Rights Reserved. * * Project Name:sunego-commerce-common * Package Name:com.sunego.commerce.common.http * File Name:IPUtils.java * Date:2016年4月28日 上午11:23:53 * */package com.sunego.commerce.common.http;import javax.servlet.http.HttpServletRequest;/** * ClassName: IPUtils <br/> * Description: IP查询工具 <br/> * Date: 2016年4月28日 上午11:23:53 <br/> * <br/> * * @author Administrator(邮箱) * * 修改记录 * @version 产品版本信息 yyyy-mm-dd 姓名(邮箱) 修改信息<br/> * */public class IPUtils { public static Address address; /** * * getRemoteIP:获取远程请求客户端的外网IP <br/> * * @param request * 请求实体对象 * @return ip 外网ip<br/> */ public static String getRemoteIP(HttpServletRequest request) { String ip = request.getHeader("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.getRemoteAddr(); } return ip; } /** * * getAddresses:根据外网ip,判断该ip所在的地理位置 <br/> * * @param ip * 外网ip * @return 该ip所在的地理位置 <br/> */ public static String getAddresses(String ip) { return Address.getSingleInstance().getAddresses(ip); }}
二、根据远程IP,获取远程物理地址
/** * Copyright (c) 2016,sunnybs. * All Rights Reserved. * * Project Name:sunego-commerce-common * Package Name:com.sunego.commerce.common.http * File Name:Address.java * Date:2016年4月28日 上午11:51:05 * */package com.sunego.commerce.common.http;import java.util.HashMap;import java.util.Map;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import org.apache.commons.lang3.StringUtils;import com.sunego.commerce.common.json.JsonUtils;import com.sunego.commerce.common.log.LogUtils;/** * ClassName: Address <br/> * Description: TODO <br/> * Date: 2016年4月28日 上午11:51:05 <br/> * <br/> * * @author Administrator(邮箱) * * 修改记录 * @version 产品版本信息 yyyy-mm-dd 姓名(邮箱) 修改信息<br/> * */public class Address { /** 多线程公共变量,key=ip,value=address */ static final Map<String, String> ipAddressMap = new HashMap<String, String>(); /** 线程池线程数 */ static final Integer threadSize = 3; /** 太平洋ip地址查询接口 */ static final String urlPcOnline = "http://whois.pconline.com.cn/ipJson.jsp?ip={ip}&timeStamp={timeStamp}"; /** 淘宝ip地址查询接口 */ static final String urlTaobao = "http://ip.taobao.com/service/getIpInfo.php?ip={ip}&timeStamp={timeStamp}"; /** 百度ip地址查询接口 */ static final String urlBaidu = "http://opendata.baidu.com/api.php?resource_id=6006&format=json&query={ip}&timeStamp={timeStamp}"; /** * 私有化构造方法 */ private Address() { }; private static Address address; /** * 单例模式 */ public static Address getSingleInstance() { if (null == address) { // 懒加载 synchronized (Address.class) { if (null == address) { address = new Address(); } } } return address; } /** * 根据远程ip,查询对应的物理地址<br/> * 只返回所查询到的地址的最后一级,例如address="北京市海淀区西二旗",则返回"西二旗"<br/> * 使用太平洋、淘宝、百度三个ip地址查询接口,多进程异步查询<br/> */ public String getAddresses(String ip) { // 清除上次查询结果 ipAddressMap.remove(ip); // 创建一个可以执行三个线程的线程池 ExecutorService pool = Executors.newFixedThreadPool(threadSize); // 记录起始查询时间,超时未查到就返回空 Long begin = System.currentTimeMillis(); // 设置时间戳,防止ip查询接口缓存数据 String timeStamp = String.valueOf(begin); // 太平洋ip接口查询 pool.execute(new AddressPcOnline(ip, timeStamp)); // 淘宝ip接口查询 pool.execute(new AddressTaobao(ip, timeStamp)); // 百度ip接口查询 pool.execute(new AddressBaidu(ip, timeStamp)); // 开始判断是否查询到结果 while (null == ipAddressMap.get(ip) && System.currentTimeMillis() - begin < 3000) { // 还未获得地址,且未超时(3秒),就等待(50毫秒) try { Thread.sleep(50); } catch (InterruptedException e) { // 返回空 return null; } } // 立即关闭所有进程 pool.shutdownNow(); // 返回查询到的结果 return ipAddressMap.get(ip); } public class AddressPcOnline implements Runnable { private String ip; private String timeStamp; String address; AddressPcOnline(String ip, String timeStamp) { this.ip = ip; this.timeStamp = timeStamp; } @Override public void run() { try { String result = NHttpPool.getString(urlPcOnline.replace("{ip}", ip).replace("{timeStamp}", timeStamp), NHttpPool.CHARSET_GBK); result = StringUtils.trim(result); result = result.substring(34, result.length() - 3); Map<?, ?> jsonResult = JsonUtils.toObject(result, Map.class); if (StringUtils.isNotBlank(ipAddressMap.get(ip))) { return; } LogUtils.LOG_BIZ_INFO.info("urlPcOnline | ip=" + ip + " | result=" + result); address = (String) jsonResult.get("region"); if (StringUtils.isNotEmpty(address)) { ipAddressMap.put(ip, address); return; } address = (String) jsonResult.get("city"); if (StringUtils.isNotEmpty(address)) { ipAddressMap.put(ip, address); return; } address = (String) jsonResult.get("pro"); ipAddressMap.put(ip, address); } catch (Exception e) { } } } public class AddressTaobao implements Runnable { private String ip; private String timeStamp; String address; AddressTaobao(String ip, String timeStamp) { this.ip = ip; this.timeStamp = timeStamp; } @Override public void run() { try { String result = NHttpPool.getString(urlTaobao.replace("{ip}", ip).replace("{timeStamp}", timeStamp), NHttpPool.CHARSET_GBK); result = result.substring(17, result.length() - 1); Map<?, ?> jsonResult = JsonUtils.toObject(result, Map.class); if (StringUtils.isNotBlank(ipAddressMap.get(ip))) { return; } LogUtils.LOG_BIZ_INFO.info("urlTaobao | ip=" + ip + " | result=" + result); address = (String) jsonResult.get("county"); if (StringUtils.isNotEmpty(address)) { ipAddressMap.put(ip, address); return; } address = (String) jsonResult.get("city"); if (StringUtils.isNotEmpty(address)) { ipAddressMap.put(ip, address); return; } address = (String) jsonResult.get("region"); ipAddressMap.put(ip, address); } catch (Exception e) { } } } public class AddressBaidu implements Runnable { private String ip; private String timeStamp; String address; AddressBaidu(String ip, String timeStamp) { this.ip = ip; this.timeStamp = timeStamp; } @Override public void run() { try { String result = NHttpPool.getString(urlBaidu.replace("{ip}", ip).replace("{timeStamp}", timeStamp), NHttpPool.CHARSET_GBK); result = result.substring(49, result.length() - 2); Map<?, ?> jsonResult = JsonUtils.toObject(result, Map.class); if (StringUtils.isNotBlank(ipAddressMap.get(ip))) { return; } LogUtils.LOG_BIZ_INFO.info("urlBaidu | ip=" + ip + " | result=" + result); address = (String) jsonResult.get("location"); if (address.indexOf(" ") > 0) { address = address.substring(0, address.indexOf(" ")); } if (address.indexOf("省") + 1 == address.length()) { ipAddressMap.put(ip, address); return; } if (address.indexOf("市") + 1 == address.length()) { address = address.substring(address.indexOf("省") + 1); ipAddressMap.put(ip, address); return; } address = address.substring(address.indexOf("市") + 1, address.length()); ipAddressMap.put(ip, address); } catch (Exception e) { } } }}
三、测试用例
/** * Copyright (c) 2016,sunnybs. * All Rights Reserved. * * Project Name:sunego-commerce-common * Package Name:com.sunego.commerce.common.price * File Name:PriceUtilsTest.java * Date:2016年2月20日 下午2:55:35 * */package com.sunego.commerce.common.price;import java.util.ArrayList;import java.util.List;import org.junit.Test;import com.sunego.commerce.common.http.IPUtils;/** * ClassName: PriceUtilsTest <br/> * Description: TODO <br/> * Date: 2016年2月20日 下午2:55:35 <br/> * <br/> * * @author WSP(邮箱) * * 修改记录 * @version 产品版本信息 yyyy-mm-dd 姓名(邮箱) 修改信息<br/> * */public class IPUtilsTest { @Test public void testIPUtils() { /** * 以下接口不可用 <br> * "http://www.hujuntao.com/api/ip/ip.php";<br> * "http://fw.qq.com/ipaddress";<br> * "http://pv.sohu.com/cityjson";// 仅支持js,不接受ip参数<br> * "http://j.maxmind.com/app/geoip.js";<br> * "http://www.youdao.com/smartresult-xml/search.s";<br> * "http://ip.ws.126.net/ipquery";// 仅支持js<br> * "http://app.hao123.com/ipquery/getcity.php?rtype=2";<br> * "http://w.1616.net/chaxun/iptolocal.php?ip=";// 太慢<br> */ List<String> ipList = new ArrayList<String>(); ipList.add("219.137.144.0");// 广东省广州市海珠区 ipList.add("1.85.35.131");// 陕西省西安市 电信 ipList.add("59.108.111.0");// 北京市北京市 方正宽带 ipList.add("59.104.167.0");// 台湾省 ipList.add("61.186.76.165");// 湖南省怀化市 电信 ipList.add("221.202.127.39");// 辽宁省葫芦岛市 联通 ipList.add("114.252.45.210");// 北京市北京市 联通 ipList.add("127.0.0.1");// 未分配或者内网 ipList.add("192.168.10.170");// 未分配或者内网 ipList.add("132.191.25.116:8080");// 辽宁省葫芦岛市 for (int i = 0; i < ipList.size(); i++) { String ip = ipList.get(i); String addresses = IPUtils.getAddresses(ip); System.out.println(ip + "==" + addresses); } System.err.println("\r\n\r\n***************************\r\n\r\n睡5秒\r\n\r\n***************************\r\n\r\n"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } for (int j = 63; j < 266; j += 63) { for (int k = 0; k < 266; k += 19) { for (int m = 0; m < 266; m += 13) { String ip = "60." + j + "." + k + "." + m; String address1 = IPUtils.getAddresses(ip); System.out.println(ip + "==" + address1); } } } }}
代码整完了,问题也解决了……
说明一下,
我最开始获取客户端地址,用的是在前端页面引入“http://ip.ws.126.net/ipquery”接口,
但此接口只支持js,无法写到Java后台去,
项目从http转https后该接口边便失效,又找不到https协议的ip查询接口,
因此只能在后台获取远程ip(LSB的话记得ip转换),便开始在后台使用淘宝的ip地址查询接口,
可是高频率访问时淘宝ip地址查询接口总是SocketTimeout,经过各种Httpclient优化无效,后来发现加上时间戳去缓存可以改善连接超时,
就这样用了一段时间后,频繁访问时还是会报SocketTimeoutException,
因此又调研了这许多接口,最终确定了三个比较高效、精确、稳定的接口,做成了多线程的方式随机访问。
0 0
- JAVA服务器端获取客户端远程地址,根据IP获取远程地址,各IP地址查询接口比较
- 获取远程客户端IP地址
- Java获取远程IP地址
- java服务器端根据ip获取客户端mac地址
- 获取远程客户端的真实IP地址
- java服务器端获取客户端IP地址
- 获取远程设备IP地址
- Java获取客户端ip以及根据ip查询到相应的ip地址
- Java 类中获取远程客户端的IP地址和Mac地址
- 根据IP获取地址
- 根据ip获取地址
- 根据ip获取地址
- 根据IP获取地址
- 服务器端获取webservice客户端IP地址
- 服务器端获取webservice客户端IP地址
- java 获取客户端ip地址
- Java获取客户端IP地址
- java获取客户端IP地址
- mpandroidchart地址
- Android-->回调(interface/abstract)的用法(通俗易懂)
- linux下实时查看tomcat运行日志
- IE浏览器怎样禁用js(javascript)
- c++ dll创建及使用 rundll32 测试
- JAVA服务器端获取客户端远程地址,根据IP获取远程地址,各IP地址查询接口比较
- 安卓面试题
- [伪]观察者设计模式(适用于像我这样看不太懂真正的观察者设计模式又想用观察者设计模式的小程序员)
- Jenkins进阶系列之——13修改Jenkins权限控制
- Kinect深度图与摄像头RGB的标定与配
- Tesseract-ocr
- pop第三方的基本用法
- 获取手机联系人并且向服务器发送JSON数据
- IOS使用ijkPlayer(转)