Java下IP地址解析

原文地址

原文链接

前言

ip地址解析需要ip地址数据以及查询工具,所以也可以使用数据进行存储,但是我们这里就不造轮子了,直接去拿现有工具,使用ip2region,这个工具支持多种查询方法选择

  • 现读现查的
  • 全部读入内存
  • 读入索引到内存

我们这里选择第三种折中方案

使用

具体参数以及使用方法以官方文档为主

引包

<dependency>
    <groupId>org.lionsoul</groupId>
    <artifactId>ip2region</artifactId>
    <version>${version}</version>
</dependency>

数据

引用完包之后,查询工具的文件解决了,但是数据还是没有,如果手上没有合适的可以使用ip2Region给的默认数据源

工具类

这里由于源码这里loadVectorIndexFromFile使用的是RandomAccessFile读入文件,而RandomAccessFile是不能直接读入资源文件的,所以这里我们需要将资源文件转化为普通文件,然后再行读入,当然你也可以在服务器上存入数据源,但是这样来说和服务器就有耦合性了,不是特别大的数据源或者有专门的运维不建议这么做

@Service
@Slf4j
public class IpSearchUtils {

    @Resource
    private ResourceLoader resourceLoader;

    private static String REGION_PATH;

    private static byte[] REGION_INDEX;

    @PostConstruct
    public void init() {
        try {
            InputStream in = resourceLoader.getResource("classpath:xdb/ip2region.xdb").getInputStream();
            File localIp2RegFile = FileUtil.writeFromStream(in, "localIp2Reg.xdb");
            in.close();
            REGION_PATH = localIp2RegFile.getPath();
            REGION_INDEX = Searcher.loadVectorIndexFromFile(REGION_PATH);
        } catch (Exception ex) {
            log.error("[op:IpSearchUtils:init] ip package builder fail");
            ex.printStackTrace();
        }
    }

    public static String getIpName(String ip) {
        Searcher searcher = null;
        try {
            searcher = Searcher.newWithVectorIndex(REGION_PATH, REGION_INDEX);
            String region = searcher.search(ip);
            searcher.close();
            IpAddressObj ipAddressObj = new IpAddressObj(region);
            if ("中国".equals(ipAddressObj.getCountry())) {
                return ipAddressObj.getProvince() + ipAddressObj.getCity();
            } else {
                return ipAddressObj.getCountry();
            }
        } catch (Exception ex) {
            log.error("[op:IpSearchUtils:init] ip [{}] convert fail", ip);
            ex.printStackTrace();
            if (null != searcher) {
                try {
                    searcher.close();
                } catch (IOException exception) {
                    log.error("[op:IpSearchUtils:init] ip package builder close fail");
                    exception.printStackTrace();
                }
            }
        }
        return null;
    }

}

读入对象类

@Data
public class IpAddressObj {

    private final static String SPLIT_SYMBOL = "\\|";

    /**
     * country
     */
    private String country;

    /**
     * region
     */
    private String region;

    /**
     * province
     */
    private String province;

    /**
     * city
     */
    private String city;

    /**
     * operator
     */
    private String operator;


    public IpAddressObj(String detail) {
        if (!ObjectUtils.isEmpty(detail)) {
            String[] values = detail.split(SPLIT_SYMBOL);
            this.country = convertEmptyStr(values[0]);
            this.region = convertEmptyStr(values[1]);
            this.province = convertEmptyStr(values[2]);
            this.city = convertEmptyStr(values[3]);
            this.operator = convertEmptyStr(values[4]);
        }
    }

    private String convertEmptyStr(String str) {
        return "0".equals(str) ? "" : str;
    }
}

其他说明

  1. IP获取

    这里在nginx配置中,获取实际地址(当然,如果对方使用代理那么确实无法定位真实地址),然后写入请求头中带到后端即可

            #...
            location / {
                    proxy_pass  http://localhost:9527;
                    #保留原始访问信息
                    proxy_set_header Host $host;
                    proxy_set_header your_set_forwarded_in_ngin $proxy_add_x_forwarded_for;
                    proxy_set_header your_set_real_ip_key_in_nginx $remote_addr;
                    proxy_set_header your_set_scheme_in_nginx $scheme;
            }
            #...
    
  2. 自动注入

    这里我们使用继承进行自动注入,不使用AOP+注解的方式,如果需要参数中带有地址直接继承IpAddressParam即可

    @Data
    public class IpAddressParam {
    
        private final static String NGINX_SET_REAL_IP_KEY = "your_set_real_ip_key_in_nginx";
    
        /**
         * ip地址
         */
        private String ipAddress;
    
        /**
         * ip位置
         */
        private String ipAddressName;
    
        public IpAddressParam() {
            HttpServletRequest request = ((ServletRequestAttributes)
                    RequestContextHolder.currentRequestAttributes()).getRequest();
            String ip = request.getHeader(NGINX_SET_REAL_IP_KEY);
            if (!ObjectUtils.isEmpty(ip)) {
                this.ipAddress = ip;
                this.ipAddressName = IpSearchUtils.getIpName(ip);
            }
        }
    }
    

原文地址

原文链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值