CompletableFuture并发获取IP的country_code

package com.xxx.app.service.impl;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.pisen.yunma2.server.service.IpInfoService;
import com.pisen.yunma2.server.vo.IPInfo;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.Nullable;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author: fanxian
 * @Date: 2024/10/22 15:13
 **/
@Slf4j
@Service
public class IpInfoServiceImpl implements IpInfoService {
    @Override
    public IPInfo ipInfo(String ip) {
        IPInfo ipInfo = new IPInfo(ip);
        CompletableFuture.anyOf(
                CompletableFuture.supplyAsync(()->fetchCountryCode(StrUtil.format("https://ipapi.com/ip_api.php?ip={}", ip), e->extractField(e, "country_code")))
                        .thenAccept(cCode -> ipInfo.setCountryCode(cCode)),
                CompletableFuture.supplyAsync(()->fetchCountryCode(StrUtil.format("https://webapi-pc.meitu.com/common/ip_location?ip={}", ip), e->extractField(e, "nation_code")))
                        .thenAccept(cCode -> ipInfo.setCountryCode(cCode)),
                CompletableFuture.supplyAsync(()->fetchCountryCode(StrUtil.format("https://ip-api.io/json/{}", ip), e->extractField(e, "country_code")))
                        .thenAccept(cCode -> ipInfo.setCountryCode(cCode)),
                CompletableFuture.supplyAsync(()->fetchCountryCode(StrUtil.format("https://api.ipapi.is/?ip={}", ip), e->extractField(e, "country_code")))
                        .thenAccept(cCode -> ipInfo.setCountryCode(cCode))
        ).join();
        return ipInfo;
    }


    private static Integer TIMEOUT = 1000;
    public String fetchCountryCode(String url, Function<String,String> extractField) {
        try {
            log.info("fetching {}", url);
            String resStr = HttpUtil.get(url, TIMEOUT);
            String countryCode = extractField.apply(resStr);
            Assert.notBlank(countryCode);
            log.info("resp {} country code: {}", url, countryCode);
            return countryCode.toUpperCase();
        }catch (Exception e){
            log.error("failed url: {}, error: {}", url, e.getMessage());
            ThreadUtil.sleep(TIMEOUT+300, TimeUnit.MILLISECONDS); // 停一下,让其他请求成功返回
            return null;
        }
    }
    private static @Nullable String extractField(String resStr, String fieldName) {
        String regex = "\""+fieldName+"\":\\s*\"([^\"]*)\"";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(resStr);

        if (matcher.find()) {
            String nationCode = matcher.group(1);
            System.out.println("extract field... " + fieldName +": " + nationCode);
            return nationCode;
        } else {
            System.out.println(fieldName +" not found.");
            return null;
        }
    }


    public static void main(String[] args) throws IOException {

//        String ip = "172.66.43.8"; // not china
        String ip = "121.8.215.106"; // china
        IpInfoServiceImpl ipInfoService = new IpInfoServiceImpl();
        IPInfo ipInfo = ipInfoService.ipInfo(ip);
        System.out.println("--->ipInfo: " + JSONUtil.toJsonStr(ipInfo));
    }

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 津渡欧鹭阅读 57评论 0 3
  • 昨天都十点了,牛牛一直磨蹭要买的大巴车,消防车拿到床上,小汽车,那一堆,非要拿到床上,之前干净的拿到床上无所谓。我...
    现在的小辣椒阅读 48评论 0 0
  • 我忽然间明白一件事情,既然我能感受到某个音乐的感受,或者某个电影的非常不明显的隐喻,那其实也不用怀疑自己感受到的善...
    和北极熊一起读书阅读 46评论 0 0
  • 前几天阴雨绵绵,气温也下降的历害,让人有恍惚一夜入冬的感觉。据说今年的冬天很冷,也不知是不是真的。从时间上来说,现...
    74e80bcc1a31阅读 64评论 0 2
  • 以往的清晨,我都会在七点之前离开床,起来运动或是坐下来看书,运动是流了汗水的,但看书不见得能看的进去,看书还是适合...
    请叫我谢有恒阅读 57评论 0 0