获取请求IP以及IP解析成省份

news2024/12/24 21:06:00

某些业务需要获取请求IP以及将IP解析成省份之类的,于是我写了一个工具类,可以直接COPY

/**
 * IP工具类
 * @author xxl
 * @since 2023/11/9
 */
@Slf4j
public class IPUtils {
    /**
     * 过滤本地地址
     */
    public static final String LOCAL_ADDRESS = "127.0.0.1";
    public static final String LOOP_BACK_ADDRESS = "0:0:0:0:0:0:0:1";
    /**
     * 离线查询IP地址的数据文件,这个文件去ip2region GitHub官方仓库获取
     */
    private static  String IP_ADDRESS_FILE_PATH ;

    /**
     * 前从 xdb 文件中加载出来 VectorIndex 数据,然后全局缓存,
     * 每次创建 Searcher 对象的时候使用全局的 VectorIndex 缓存可以减少一次固定的 IO 操作,
     * 从而加速查询,减少 IO 压力。
     */
    private static  byte[] vIndex= null;
    private static Searcher searcher = null;
    
    static {
        try {
            //这个ip2region.xdb我是放在/resources/data/ip2region.xdb目录下的
            String fileName = "/data/ip2region.xdb";
            File existFile = FileUtil.file(FileUtil.getTmpDir() + FileUtil.FILE_SEPARATOR + fileName);
            if(!FileUtil.exist(existFile)) {
                InputStream resourceAsStream = IPUtils.class.getResourceAsStream(fileName);
                FileUtil.writeFromStream(resourceAsStream, existFile);
            }

            IP_ADDRESS_FILE_PATH = existFile.getPath();

            // 从 db 中预先加载 VectorIndex 缓存,并且把这个得到的数据作为全局变量,后续反复使用。
            vIndex = Searcher.loadVectorIndexFromFile(IP_ADDRESS_FILE_PATH);
            // 使用全局的 vIndex 创建带 VectorIndex 缓存的查询对象。
            searcher = Searcher.newWithVectorIndex(IP_ADDRESS_FILE_PATH, vIndex);
        } catch (Exception e) {
            throw new RuntimeException("IPUtils class load error", e);
        }
    }

    /**
     * 每个线程需要单独创建一个独立的 Searcher 对象,但是都共享全局的制度 vIndex 缓存。
     * @param ip IP
     * @return IP地址
     */
    public static String getCity(String ip)  {
        String search = null;
        try {
            search = searcher.search(ip);
        } catch (Exception e) {
            throw new RuntimeException("getCity fail",e);
        }
        return search;
    }

    /**
     * 获取 IP
     *
     * @param request 请求
     * @return 字符串
     */
    public static String getIp(HttpServletRequest request) {
        String ip = null;
        try {
            //解析IP
            ip = new ChainUtils<>(request.getHeader("X-Forwarded-For"))
                //多次反向代理后会有多个ip值,第一个ip才是真实ip
                .chain(re -> StrUtil.isNotBlank(re) ? (re.contains(DOT) ? re.substring(0, re.indexOf(DOT)) : EMPTY) : re)
                //依次查找IP
                .chain(re -> StrUtil.isNotBlank(re) ? re : request.getHeader("X-Real-IP"))
                .chain(re -> StrUtil.isNotBlank(re) ? re : request.getHeader("Proxy-Client-IP"))
                .chain(re -> StrUtil.isNotBlank(re) ? re : request.getHeader("WL-Proxy-Client-IP"))
                .chain(re -> StrUtil.isNotBlank(re) ? re : request.getHeader("HTTP_CLIENT_IP"))
                .chain(re -> StrUtil.isNotBlank(re) ? re : request.getHeader("HTTP_X_FORWARDED_FOR"))
                .chain(re -> StrUtil.isNotBlank(re) ? re : request.getRemoteAddr())
                //过滤本地地址
                .chain(re -> StrUtil.isNotBlank(re) ? (LOOP_BACK_ADDRESS.equals(re) ? LOCAL_ADDRESS : re) : re)
                .getValue(true);
        } catch (Exception e) {
            log.error("getIp fail", e);
        }
        return ip;
    }
}

使用以上工具类需要以下依赖和一个自定义工具类

<!--    解析IP    -->
<dependency>
    <groupId>org.lionsoul</groupId>
    <artifactId>ip2region</artifactId>
    <version>2.7.0</version>
</dependency>
<!--   hutool     -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.20</version>
</dependency>

ChainUtil:为什么写这个工具类在解析请求中的IP参考了https://blog.csdn.net/chwshuang/article/details/71940858此博客中部分代码如下图可以发现有很多if判断,很难看不好维护。于是就写了以下的工具类

/**
 * @author: xxl
 * @since: 2023/11/9
 * @description: 解决if,else地狱
 */
@AllArgsConstructor
public  class ChainUtil<T> {
    /**
     * 存储的值
     */
    private T value;

    public <E> ChainUtil<E> chain(Function<T,E> function) {
        return new ChainUtil<>(function.apply(value));
    }

    /**
     * 获取存储的值
     *
     * @param isNullForException 如果存储的值为null是否抛出异常
     * @return T
     */
    public T getValue(boolean isNullForException) {
        if (isNullForException) {
            Assert.notNull(value, () -> new RuntimeException("chain value is null"));
        }
        return value;
    }
}

if地狱

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1189588.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于SSM的演唱会购票系统的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue、HTML 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是…

Langchain-Chatchat实践详解

简介 本质上是在Langchain基础上封装的一层聊天服务&#xff0c;可以对接底层多种离线LLM和在线的LLM&#xff08;也可以对接自定义的在线LLM&#xff09;。提供基于知识库聊天功能相关的一系列API。 下载源码 源码地址&#xff1a; https://github.com/chatchat-space/Lang…

Apache Druid连接回收引发的血案

问题 线上执行大批量定时任务&#xff0c;发现SQL执行失败的报错&#xff1a; CommunicationsException, druid version 1.1.10, jdbcUrl : jdbc:mysql://xxx?useUnicodetrue&characterEncodingUTF-8&zeroDateTimeBehaviorconvertToNull,testWhileIdle true, idle …

《向经典致敬》第二届粤港澳大湾区著名歌唱家音乐会完美落幕

百年经典 歌坛盛会 “《向经典致敬》第二届粤港澳大湾区著名歌唱家音乐会暨2023福田人才之夜”完美落幕 2023年11月4日&#xff0c;阳光普照&#xff0c;秋意正浓&#xff0c;由中共深圳市福田区委宣传部、深圳市福田区文学艺术界联合会主办&#xff0c;深圳歌唱家协会承办&…

数据结构与算法C语言版学习笔记(3)-线性表的链式结构:链表

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言&#xff1a;回顾顺序表的优缺点&#xff1a;为什么要引入链式结构的线性表&#xff1f; 一、什么是链表&#xff1f;二、链表的分类①为什么要设置头节点&…

Oracle(15)Managing Users

目录 一、基础知识 1、Users and Security 用户和安全 2、Database Schema 3、Checklist for Creating Users创建用户步骤 二、基础操作 1、创建一个用户 2、OS Authentication 操作系统身份验证 3、Dropping a User 删除用户 4、Getting User Information 获取用户信…

Idea安装使用教程~

在本文中&#xff0c;我们将提供关于如何安装 IntelliJ IDEA 的详细步骤。如果您是初学者或只是想尝试一下 IDEA&#xff0c;我们建议您下载 Community 版。如果您需要更多高级功能&#xff0c;可以选择 Ultimate 版。 步骤一&#xff1a;下载 IntelliJ IDEA 首先&#xff0c;…

第三方商城对接项目(202311)

文章目录 1. 项目背景和目标2. 项目成果3. 项目经验总结4. 展望和建议 1. 项目背景和目标 竞标成功接口对接第三方商城&#xff0c;商品&#xff0c;订单&#xff0c;售后尽快完成对接 2. 项目成果 完成整个项目功能流程对接新业务功能移交项目等业务部门使用 3. 项目经验总…

app自动化测试——capability 配置参数解析

一、Capability 简介 功能&#xff1a;配置 Appium 会话&#xff0c;告诉 Appium 服务器需要自动化的平台的应用程序 形式&#xff1a;键值对的集合&#xff0c;键对应设置的名称&#xff0c;值对应设置的值 主要分为三部分 公共部分 ios 部分 android 部分 二、Session Appi…

【C++】特殊类实现——设计一个类、不能被拷贝、只能在堆上创建对象、只能在栈上创建对象、不能被继承、单例模式、饿汉模式、懒汉模式

文章目录 C特殊类实现1.设计一个类、不能被拷贝2.设计一个类、只能在堆上创建对象3.设计一个类、只能在栈上创建对象4.设计一个类、不能被继承5.设计一个类&#xff0c;只能创建一个对象(单例模式)5.1饿汉模式5.2懒汉模式 C 特殊类实现 1.设计一个类、不能被拷贝 在C中&#x…

11 # 手写 reduce 方法

reduce 使用 reduce() 方法对数组中的每个元素按序执行一个提供的 reducer 函数&#xff0c;每一次运行 reducer 会将先前元素的计算结果作为参数传入&#xff0c;最后将其结果汇总为单个返回值。 第一次执行回调函数时&#xff0c;不存在“上一次的计算结果”。如果需要回调…

短短45分钟,Open AI撼动了整个AI圈?

相信关注AI行业的人没有人不知道ChatGPT&#xff0c;作为人工智能新产品&#xff0c;ChatGPT一经发出就引爆全球&#xff0c;也让一众企业走上了探索AI大模型之路。而就在国内一众企业就AI大模型不断改进创新时&#xff0c;Open AI用一场仅45分钟的发布会&#xff0c;震惊了整个…

【JavaEESpring】Spring IoCDI

Spring IoC& DI 1. IoC2. IoC & DI 使⽤2.1 Bean的存储2.1 DI 注入 Autowired 3. 练习代码自取 1. IoC Spring 是包含了众多⼯具⽅法的 IoC 容器 IoC: Inversion of Control (控制反转), 也就是说 Spring 是⼀个"控制反转"的容器。 什么是控制反转呢? 也就…

uniapp使用vue

uniapp集成了Vuex&#xff0c;&#xff0c;并不需要安装vuex 定义自己的vuex vuex中独立命名空间&#xff1a; 可以在模块中使用 namespaced 属性&#xff0c;设置为 true&#xff0c;&#xff0c;这样做的好处是&#xff0c;&#xff0c;不同模块之间的state&#xff0c;mut…

电商库存随笔

好多年没有来写东西了&#xff0c;忙成狗&#xff0c;最近闲暇&#xff0c;有点时间&#xff0c;随手写一下之前的项目中的小点&#xff1b; 一方面是做个总结&#xff0c;一方面打发一下时间 出库 库存扣减时机 下单扣减 [生成订单]付款扣减预扣库存(实际使用) 预扣库存 并…

运营商大数据精准获客:我们提供精准客源渠道的最大资源体?

运营商大数据精准营销 谈起精准获客&#xff0c;竞争对手永远是为我们提供精准客源渠道的最大资源体&#xff01; 最新的获客方式&#xff0c;就是从竞争对手的手中把他们的精准客户资源变为自己的。 今年最火的运营商大数据精准营销是拒绝传统营销方式的烧钱推广&#xff0…

Nginx缓存基础

1 nginx缓存的流程 客户端需要访问服务器的数据时&#xff0c;如果都直接向服务器发送请求&#xff0c;服务器接收过多的请求&#xff0c;压力会比较大&#xff0c;也比较耗时&#xff1b;而如果在nginx缓存一定的数据&#xff0c;使客户端向基于nginx的代理服务器发送请求&…

ChatGPT - 在ChatGPT中设置通用提示模板

文章目录 Prompt设置验证 Prompt VERBOSITY: 我可能会使用 V[0-3] 来定义代码的详细程度&#xff1a;V0 简洁明了 V1 简练 V2 详细 V3 非常详细&#xff0c;附有例子助理回应 您是用户问题背景下的主题专家。我们一步一步来&#xff1a;除非您只是回答一个简短的问题&#xff…

Confluence 漏洞复现(CVE-2023-22515)

Confluence 漏洞复现&#xff08;CVE-2023-22515&#xff0c;CVE-2023-22518&#xff09; 1.CVE-2023-22515权限提升漏洞 1.1漏洞描述 Confluence近期推出的严重漏洞cve-2023-22515&#xff0c;由于未授权和xwork框架问题&#xff0c;导致攻击者可以未授权将系统设置为未安装…

分布式事务的华丽进化

说到分布式事务&#xff0c;大家并不陌生。之前我已做过相关的总结&#xff08;连接附本文后面&#xff09;&#xff0c;不过比较偏理论。在实际工作中&#xff0c;用得比较多的还是柔性分布式事务&#xff0c;今天主要把在工作中运用到的几种柔性分布式事务的场景及实现方式做…