怎么自己做視頻網(wǎng)站免費(fèi)找客戶軟件
某些業(yè)務(wù)需要獲取請(qǐng)求IP以及將IP解析成省份之類的,于是我寫了一個(gè)工具類,可以直接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地址的數(shù)據(jù)文件,這個(gè)文件去ip2region GitHub官方倉(cāng)庫(kù)獲取*/private static String IP_ADDRESS_FILE_PATH ;/*** 前從 xdb 文件中加載出來 VectorIndex 數(shù)據(jù),然后全局緩存,* 每次創(chuàng)建 Searcher 對(duì)象的時(shí)候使用全局的 VectorIndex 緩存可以減少一次固定的 IO 操作,* 從而加速查詢,減少 IO 壓力。*/private static byte[] vIndex= null;private static Searcher searcher = null;static {try {//這個(gè)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 中預(yù)先加載 VectorIndex 緩存,并且把這個(gè)得到的數(shù)據(jù)作為全局變量,后續(xù)反復(fù)使用。vIndex = Searcher.loadVectorIndexFromFile(IP_ADDRESS_FILE_PATH);// 使用全局的 vIndex 創(chuàng)建帶 VectorIndex 緩存的查詢對(duì)象。searcher = Searcher.newWithVectorIndex(IP_ADDRESS_FILE_PATH, vIndex);} catch (Exception e) {throw new RuntimeException("IPUtils class load error", e);}}/*** 每個(gè)線程需要單獨(dú)創(chuàng)建一個(gè)獨(dú)立的 Searcher 對(duì)象,但是都共享全局的制度 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 請(qǐng)求* @return 字符串*/public static String getIp(HttpServletRequest request) {String ip = null;try {//解析IPip = new ChainUtils<>(request.getHeader("X-Forwarded-For"))//多次反向代理后會(huì)有多個(gè)ip值,第一個(gè)ip才是真實(shí)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;}
}
使用以上工具類需要以下依賴和一個(gè)自定義工具類
<!-- 解析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:為什么寫這個(gè)工具類在解析請(qǐng)求中的IP參考了https://blog.csdn.net/chwshuang/article/details/71940858
此博客中部分代碼如下圖可以發(fā)現(xiàn)有很多if判斷,很難看不好維護(hù)。于是就寫了以下的工具類
/*** @author: xxl* @since: 2023/11/9* @description: 解決if,else地獄*/
@AllArgsConstructor
public class ChainUtil<T> {/*** 存儲(chǔ)的值*/private T value;public <E> ChainUtil<E> chain(Function<T,E> function) {return new ChainUtil<>(function.apply(value));}/*** 獲取存儲(chǔ)的值** @param isNullForException 如果存儲(chǔ)的值為null是否拋出異常* @return T*/public T getValue(boolean isNullForException) {if (isNullForException) {Assert.notNull(value, () -> new RuntimeException("chain value is null"));}return value;}
}
if地獄