future介绍:

Future代表的是异步执行的结果,意思是当异步执行结束之后,返回的结果将会保存在Future中。 那么我们什么时候会用到Future呢? 一般来说,当我们执行一个长时间运行的任务时,使用Future就可以让我们暂时去处理其他的任务,等长任务执行完毕再返回其结果。

场景:登录时获取用户ip地址,插入登录日志,需要获取用户ip对应的地理位置
接口:

import cn.hutool.core.thread.ThreadUtil;
@OpLog(title = "无密码登录", businessType = "用户登录")
@GetMapping(value = "/secret-key/{secretKey}", produces = "application/json;charset=UTF-8")
public Result<DiskUserSecretKeyLoginResponseDTO> secretKeyLogin(@PathVariable(name = "secretKey") String secretKey,
HttpServletRequest request, HttpServletResponse response) throws IOException {

if (SecurityUtils.getSubject().isAuthenticated()) {
log.info("重复调用登陆模块");
return getLoginInfo(request);
}

// 验证密钥是否为空
if (StrUtil.isBlank(secretKey)) {
return Result.refuse();
}

// 异步获取IP实际地理位置信息
Future<Region> future = ThreadUtil.execAsync(() -> IpUtils.getIpLocationByBtree(ServletUtil.getClientIP(request)));

...后文省略
}

ip工具类iputils:

import cn.hutool.core.lang.Singleton;
import org.lionsoul.ip2region.DataBlock;
import org.lionsoul.ip2region.DbConfig;
import org.lionsoul.ip2region.DbSearcher;
import org.apache.commons.io.IOUtils;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.StrUtil;
public static Region getIpLocationByBtree(String ip) {
return getIpLocation(ip, "btreeSearch");
}
private static synchronized Region getIpLocation(String ip, String algorithm) {
String intranetIp = "内网IP";
if (StrUtil.isBlank(ip)) {
log.info("The IP address detected is empty...");
return new Region(intranetIp, intranetIp, intranetIp, intranetIp);
} else if (isInnerIp(ip)) {
return new Region(intranetIp, intranetIp, intranetIp, intranetIp);
} else {
try {
DbConfig config = (DbConfig)Singleton.get(DbConfig.class, new Object[0]);
File tempFile = FileUtil.touch((File)Singleton.get(File.class, new Object[]{"ip2region.db"}));
InputStream inputStream = IpUtils.class.getClassLoader().getResourceAsStream("data/ip2region.db");
FileOutputStream out = new FileOutputStream(tempFile);
Throwable var7 = null;

try {
if (inputStream != null) {
IOUtils.copy(inputStream, out);
}
} catch (Throwable var17) {
var7 = var17;
throw var17;
} finally {
if (out != null) {
if (var7 != null) {
try {
out.close();
} catch (Throwable var16) {
var7.addSuppressed(var16);
}
} else {
out.close();
}
}

}

DbSearcher dbSearcher = (DbSearcher)Singleton.get(DbSearcher.class, new Object[]{config, tempFile.getPath()});
Method method = dbSearcher.getClass().getMethod(algorithm, String.class);
DataBlock dataBlock = (DataBlock)method.invoke(dbSearcher, ip);
if (dataBlock != null && StrUtil.isNotBlank(dataBlock.getRegion())) {
String[] ipData = dataBlock.getRegion().split("\\|");
return Region.builder().country(ipData[0]).province(ipData[2]).city(ipData[3]).isp(ipData[4]).build();
} else {
return new Region(intranetIp, intranetIp, intranetIp, intranetIp);
}
} catch (Exception var19) {
var19.printStackTrace();
return new Region(intranetIp, intranetIp, intranetIp, intranetIp);
}
}
}