Java根据ip获取经纬度

955 阅读3分钟

这是我网上找的教程,不记得作者是谁,如果发现了,一定联系我注明出处噢 话不多说,上代码

import com.alibaba.fastjson.JSON;
import com.maxmind.geoip2.DatabaseReader;
import net.sf.json.JSONArray;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.InetAddress;
import java.util.Arrays;

/**
 *
 * @description: 获取客户端IP地址
 */
public class IPUtil {
    private static Logger logger = LoggerFactory.getLogger(IPUtil.class);

    /**
     * 获取客户端IP地址
     *
     * 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址
     * 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址
     */
    public static String getIP(HttpServletRequest request) {
        String ip = null;
        try {
            ip = request.getHeader("x-forwarded-for");
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
        } catch (Exception e) {
            logger.error("IPUtils ERROR ", e);
        }
        return ip;
    }

    /**
     *
     * @description: 获得国家
     * @param reader
     * @param ip
     * @return
     * @throws Exception
     */
    public static String getCountry(DatabaseReader reader, String ip) throws Exception {
        return reader.city(InetAddress.getByName(ip)).getCountry().getNames().get("zh-CN");
    }

    /**
     *
     * @description: 获得省份
     * @param reader
     * @param ip
     * @return
     * @throws Exception
     */
    public static String getProvince(DatabaseReader reader, String ip) throws Exception {
        return reader.city(InetAddress.getByName(ip)).getMostSpecificSubdivision().getNames().get("zh-CN");
    }

    /**
     *
     * @description: 获得城市
     * @param reader
     * @param ip
     * @return
     * @throws Exception
     */
    public static String getCity(DatabaseReader reader, String ip) throws Exception {
        return reader.city(InetAddress.getByName(ip)).getCity().getNames().get("zh-CN");
    }

    /**
     *
     * @description: 获得经度
     * @param reader
     * @param ip
     * @return
     * @throws Exception
     */
    public static Double getLongitude(DatabaseReader reader, String ip) throws Exception {
        return reader.city(InetAddress.getByName(ip)).getLocation().getLongitude();
    }

    /**
     *
     * @description: 获得纬度
     * @param reader
     * @param ip
     * @return
     * @throws Exception
     */
    public static Double getLatitude(DatabaseReader reader, String ip) throws Exception {
        return reader.city(InetAddress.getByName(ip)).getLocation().getLatitude();
    }


    public static void main(String[] args) throws Exception {
//        String path = "/geoLite/GeoLite2-City.mmdb";
        ClassPathResource classPathResource = new ClassPathResource("/geoLite/GeoLite2-City.mmdb");
        // 创建 GeoLite2 数据库
        File database = new File(classPathResource.getURI());
        // 读取数据库内容
        DatabaseReader reader = new DatabaseReader.Builder(database).build();
        // 访问IP
//        String ip = "180.109.64.94";
        String ip = "113.87.130.106";
        Double site [] = new Double[2];
        site[0] = IPUtil.getLongitude(reader, ip);
        site[1] = IPUtil.getLatitude(reader, ip);
        String jsonList = JSON.toJSONString(site);
        System.out.println(jsonList);
//        System.out.println(site);
//        JSONArray jsonarray = JSONArray.fromObject(site);
//        System.out.println(jsonarray);
    }

    public static String getLongitudeAndLatitude(String ip) throws Exception {
//        如果是在本地的文件可以用这个
//        String path = "E:/GeoLite2-City.mmdb";
//        创建 GeoLite2 数据库
//        File database = new File(path);// 创建 GeoLite2 数据库

        ClassPathResource resource = new ClassPathResource("geoLite/GeoLite2-City.mmdb");
//         File database = new File(resource.getURI());如果不打包可以用这个
        InputStream inputStream = resource.getInputStream();

          // 读取数据库内容
        DatabaseReader reader = new DatabaseReader.Builder(inputStream).build();
        Double site [] = new Double[2];
        site[0] = IPUtil.getLongitude(reader, ip);
        site[1] = IPUtil.getLatitude(reader, ip);
        String jsonList = JSON.toJSONString(site);
        System.out.println(jsonList);
        return jsonList;
    }
}

输出结果是这样的:[113.7266,34.7725]

还需要一个文件,我放到百度云上,在我项目里面我是写的相对路径放在resources下

pan.baidu.com/s/1oCNPrG05… 提取码:01xw

最后说一下我在实现过程中遇到的坑吧😭😭😭,我用的是springboot项目,打包之后是jar包,
最开始的时候文件时放在我电脑本地的,直接根据本地地址去访问,

 String path = "E:/GeoLite2-City.mmdb";
 // 创建 GeoLite2 数据库
 File database = new File(path);// 创建 GeoLite2 数据库

因为项目要求所以放在了项目内,获取相对路径得到文件,

ClassPathResource resource = new ClassPathResource("geoLite/GeoLite2-City.mmdb");
File database = new File(resource.getURI());

发现在本地可以,但是一打包就出现无法找到url的错误,经过查询之后得知springboot项目打包后,file新建的时候获取不到url,只能获取到流,经过实测完全可以,发布到linux服务器也完全可以。

 ClassPathResource resource = new ClassPathResource("geoLite/GeoLite2-City.mmdb");
 InputStream inputStream = resource.getInputStream();