网上的手机号码归属地查询,要么限制查询条数,要么收费,于是找到一个 360 提供的查询 api
使用多线程异步查询,Future 确保查询结果顺序与输入顺序一致
核心 Controller
package com.example.phonenumber.controller;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@RestController
@RequestMapping("/api")
public class PhoneController {
@Autowired
private RestTemplate restTemplate;
private static final int THREAD_POOL_SIZE = 8;
@GetMapping("/search")
public String search() {
String url = "http://cx.shouji.360.cn/phonearea.php?number=";
String[] phoneNumberList = getPhoneNumberList();
ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
List<Future<Map<String, String>>> futures = new ArrayList<>();
for (String number : phoneNumberList) {
Future<Map<String, String>> future = executorService.submit(() -> processPhoneNumber(url, number));
futures.add(future);
}
// 等待所有任务完成
for (Future<Map<String, String>> future : futures) {
try {
Map<String, String> result = future.get();
// 在这里,你可以将结果保存起来,比如放到一个 List 中
System.out.println(result.get("number") + "\t" + result.get("province") + "\t" + result.get("city") + "\t" + result.get("sp"));
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace(); // 在实际应用中需要适当处理异常
}
}
executorService.shutdown();
return "success";
}
// 调用接口查询
private Map<String, String> processPhoneNumber(String url, String number) {
String response = restTemplate.getForObject(url + number, String.class);
JSONObject responseJson = JSONUtil.parseObj(response);
Map<String, String> result = new HashMap<>();
result.put("number", number);
// 解析响应数据
if (responseJson.getInt("code") == 0) {
JSONObject dataJson = responseJson.getJSONObject("data");
// 省份
result.put("province", dataJson.getStr("province"));
// 城市
result.put("city", dataJson.getStr("city"));
// 运营商
result.put("sp", dataJson.getStr("sp"));
} else {
result.put("error", "电话号码有误");
}
return result;
}
// 电话号码列表,以逗号分隔
private String[] getPhoneNumberList() {
String phoneNumberStr =
"15649408889," +
"13333857377," +
"18898135919," +
"15037601625," +
"15890350177," +
"15890350177," +
"13673379352," +
"13673379352," +
"13849159230," +
"18937807559," +
"15649408889," +
"13333857377"; // 你的电话号码列表
return phoneNumberStr.split(",");
}
}
浏览器访问 http://localhost:8080/api/search
结果截图:
完整源码可下载