起初只是想做到使用 Java 在运行过程中切换 host,刚开始使用 HttpClient,用着还挺顺手,后来公司 HTTPS 迁移,发现很多接口在设置代理 ip 后无法访问了,输出了响应才明白,原来公司是为域名分发的证书,如果直接用 HTTPS 访问 ip 是不可行的。这样可能说不清楚,举个例子:
https://app.api.com.cn/api/test?a=2ip,修改 Windows 的 host 文件当然是可行的(switchhost 软件),但是直接在浏览器中把域名更换为 ip 就不通了,会提示证书不可信,例如 https://192.168.100.1/api/test?a=2,你不能总是要求开发或者运维给你配置。。。直接访问自然是没有问题,有时候我们测试时会有多套环境,这就需要指向对应的
其实 HttpClient 在这里不好使的原因也是如此,它的封装相当于在一个浏览器中把域名更换为 ip 然后点击访问按钮(结果上来看)。
今天偶尔发现一个第三方扩展,可以实现虚拟 DNS,我一看就乐了,熟悉网络的肯定明白,域名的解析就是靠 DNS 这个东东啦。
不啰嗦了,直接上用法,顺便感谢原作者。贴下他们的网站吧,http://leopard.io/。
<dependency>
<groupId>io.leopard</groupId>
<artifactId>javahost</artifactId>
<version>0.3-SNAPSHOT</version>
</dependency>
就是指定虚拟 DNS 的映射关系咯。
idea 建立的项目可以指定一个 resource 目录,eclipse 的话放在 classpath 下即可。
vdns.properties
app.api.com.cn=192.168.100.1
#多IP设置,域名解析时随机返回其中一个
user.api.com.cn=192.168.100.2,192.168.100.3
API 调用永远是很简单啦,不过有兴趣可以看看内部实现。
方法:
import io.leopard.javahost.JavaHost;
import java.io.IOException;
import java.net.InetAddress;
import java.util.Properties;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
public class VirtualDns {
public static void loadDns() throws IOException {
Resource resource = new ClassPathResource("/vdns.properties");
Properties props = PropertiesLoaderUtils.loadProperties(resource);
JavaHost.updateVirtualDns(props);
}
}
调用
public class Test {
public static void main(String[] args)
throws Exception {
VirtualDns.loadDns();
JavaHost.printAllVirtualDns();// 打印所有虚拟DNS记录
System.out.println("IP:" + InetAddress.getByName("app.api.com.cn").getHostAddress());// 验证一下解析是否正确
}
}
当然只是这样是看不出虚拟 DNS 的好处的,比较靠切换 host 方案也可以实现。我这里提出一种场景:现在我在测试环境有个接口,需要测试其返还的数据是否和线上环境完全一致,且 URL 也完全相同,写到脚本里的话就需要在一次执行过程中启用两套环境。
一种办法是写个自定义线程,在需要访问测试环境的数据时,手工切换 host 为测试环境的 host,获取到响应后让线程休眠一段时间,然后手工切换 host 到线上环境,此时线程差不多激活了。。。听着好像有些蛋疼。
另一种办法就是使用虚拟 DNS 了,写两套配置文件,使用哪个环境就用哪个配置文件,demo 如下:
package util;
import io.leopard.javahost.JavaHost;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import java.io.IOException;
import java.util.Properties;
/**
* Created by Administrator on 2017/1/4.
* 这里是封装的共用方法
*/
public class VirtualDns {
private Resource resource;
public VirtualDns(String path){
//resource = new ClassPathResource("/dns-test.properties");
resource = new ClassPathResource(path);
}
public void loadDns() throws IOException {
Properties props = PropertiesLoaderUtils.loadProperties(resource);
JavaHost.updateVirtualDns(props);
}
}
package util;
import org.junit.Assert;
import java.io.IOException;
import static io.restassured.RestAssured.*;
import static io.restassured.matcher.RestAssuredMatchers.*;
import static io.restassured.path.json.JsonPath.from;
import static org.hamcrest.Matchers.*;
/**
* Created by Administrator on 2017/1/10.
* 这里相当于我们的一个测试用例代码
*/
public class Test {
public static void main(String[] args) throws IOException {
//获取测试环境的某个数据
VirtualDns virtualDnsTest = new VirtualDns("/dns-test.properties");
virtualDnsTest.loadDns();
int id_test = get("http://app.api.com.cn/test?a=1").then().extract().path("result.list[0].id");
//获取线上环境的某个数据
VirtualDns virtualDnsOnline = new VirtualDns("/dns-online.properties");
virtualDnsOnline.loadDns();
int id_online = get("http://app.api.com.cn/test?a=1").then().extract().path("result.list[0].id");
//对比断言
Assert.assertEquals(id_online,id_test);
}
}
其实都挺蛋疼的,要怪就怪世界吧(无奈摊手)。