package com.virjar.dungproxy.client.samples.poolstrategy; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.lang3.math.NumberUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Function; import com.google.common.base.Splitter; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.common.io.Files; import com.google.common.io.LineProcessor; import com.virjar.dungproxy.client.ippool.strategy.ResourceFacade; import com.virjar.dungproxy.client.model.AvProxyVO; import com.virjar.dungproxy.client.util.CommonUtil; /** * Created by virjar on 17/1/17.<br/> * 自定义数据源,传统的基于文件的加载方式,注意替换 filePath为真实文件路径,文件格式如下 * * <pre> * ip:port * ip2:port * 123.34.65.23:80 * 34.45.65.34:8123 * </pre> */ public class CustomIPSource implements ResourceFacade { private static final Logger logger = LoggerFactory.getLogger(CustomIPSource.class); private Map<String, List<String>> cache = Maps.newConcurrentMap(); private Set<String> allProxies = Sets.newConcurrentHashSet(); private static final String filePath = "";// 通过文件加载IP,这里替换为文件路径 private static final Splitter ipAndPortSpitter = Splitter.on(":"); @Override public List<AvProxyVO> importProxy(String domain, String testUrl, Integer number) { if (number == null || number == 0) { number = 40;// 拍脑门儿随意写的 } // 获取缓存数据 List<String> ipList = cache.get(domain); if (ipList == null) { synchronized (this) { ipList = cache.get(domain); if (ipList == null) { ipList = createNewDomainCache(); cache.put(domain, ipList); } } } // IP不足量,增量加载IP if (ipList.size() < number) { importAllData(); } // 从缓存总拿出对应数目的IP,并删除缓存 Iterator<String> iterator = ipList.iterator(); List<AvProxyVO> ret = Lists.newArrayList(); while (iterator.hasNext()) { String next = iterator.next(); List<String> strings = ipAndPortSpitter.splitToList(next); AvProxyVO avProxyVO = new AvProxyVO(); avProxyVO.setIp(strings.get(0)); avProxyVO.setPort(NumberUtils.toInt(strings.get(1))); ret.add(avProxyVO); iterator.remove(); if (ret.size() >= number) { return ret; } } return ret; } private List<String> createNewDomainCache() { if (allProxies.size() == 0) { importAllData(); } return Lists.newArrayList(allProxies); } @Override public void feedBack(String domain, List<AvProxyVO> avProxies, List<AvProxyVO> disableProxies) { // 看自己的需求是否需要反馈IP使用情况到自己的IP数据源了 } private void extendCache(List<String> newData) { for (List<String> domainItem : cache.values()) { domainItem.addAll(newData); } } @Override public List<AvProxyVO> allAvailable() { if (allProxies.size() == 0) { importAllData(); } return Lists.transform(Lists.newArrayList(allProxies), new Function<String, AvProxyVO>() { @Override public AvProxyVO apply(String input) { List<String> strings = ipAndPortSpitter.splitToList(input); AvProxyVO avProxyVO = new AvProxyVO(); avProxyVO.setIp(strings.get(0)); avProxyVO.setPort(NumberUtils.toInt(strings.get(1))); return avProxyVO; } }); } private synchronized void importAllData() { try { List<String> avProxyVOs = Files.readLines(new File(filePath), Charset.defaultCharset(), new LineProcessor<List<String>>() { private List<String> ret = Lists.newArrayList(); @Override public boolean processLine(String line) throws IOException { if (CommonUtil.isPlainProxyItem(line)) { return true; } logger.warn("{}不是合法的IP条目", line); return false; } @Override public List<String> getResult() { return ret; } }); allProxies.addAll(avProxyVOs); extendCache(avProxyVOs); logger.info("本次共加载:{}条IP数据", avProxyVOs.size()); } catch (IOException e) { e.printStackTrace(); } } }