版权声明:可以随意转载反正又写不出什么核心技术 但转载请注明出处 https://blog.csdn.net/My_dearest_/article/details/82558680
利用阿里云提供的云解析服务API完成动态域名解析。
所用到的阿里云API版本参照https://help.aliyun.com/document_detail/29821.html :
<repositories>
<repository>
<id>sonatype-nexus-staging</id>
<name>Sonatype Nexus Staging</name>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
添加jar包依赖
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-alidns</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>2.3.8</version>
</dependency>
整个服务分为以下四个模块:
1、获取外部IP。可以是通过某个URL请求或者模拟在百度搜索“IP”,再通过正则抓取返回信息中的IP信息。
2、解析域名。
3、定时任务。阿里云提供的免费云解析TTL = 600s,服务商可能每天或者几天进行一次动态IP的分配,由于一次生效后有效时间较长,中间只需要对比目前的外网IP与上一次解析到的IP是否一致即可。这里可以利用while(true)+Thread.sleep完成,也可以利用Timer等完成。
4、log4j2日志处理。
这里只贴一下1、2部分的代码:
获取外部IP:
package com.shinoha.ddns;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class IPService{
//百度应该是最稳定的获取IP的方法之一了
//必要参数,否则百度不会返回正常数据
private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; WOW64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36";
public static String getOutSideIP(){
try{
String reqUrl = "https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=0&rsv_idx=1&tn=baidu&wd=ip";
URL url = new URL(reqUrl);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setConnectTimeout(5000);
setReqProperty(connection);
int responseCode = connection.getResponseCode();
if(responseCode != 200){
throw new Exception("connection error : "+responseCode+"");
}
InputStream is = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is , StandardCharsets.UTF_8));
StringBuilder responseContent = new StringBuilder();
String line;
//这里或许逐行执行正则匹配,成功立即返回,可能效率更高一点
while((line = reader.readLine()) != null){
line += "\r\n";
responseContent.append(line);
}
String regex = "本机IP: ([\\S]+?)</span>";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(responseContent);
if(matcher.find()){
return matcher.group(1);
}
}catch (Exception e){
e.printStackTrace();
}
return "error";
}
private static void setReqProperty(HttpURLConnection connection){
connection.setRequestProperty("Accept-Charset", "utf-8");
connection.setRequestProperty("Accept" ,"text/html,application/xhtml+xml,
application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
connection.setRequestProperty("User-Agent" ,USER_AGENT);
connection.setRequestProperty("Connection" ,"keep-alive");
}
}
执行动态解析:
package com.shinoha.ddns;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.alidns.model.v20150109.*;
import com.aliyuncs.alidns.model.v20150109.DescribeDomainRecordsResponse.Record;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import java.util.List;
public class DynamicDNS {
//待解析的域名
private static final String TARGET_DOMAIN = "Your Domain";
//用来发送各种请求
private static IAcsClient client;
static {
//根据阿里云SDK文档,云解析时这个参数只能为"cn-hangzhou"
String regionId = "cn-hangzhou";
String accessKeyId = "Your accessKeyId";
String accessKeySecret = "Your accessKeySecret";
IClientProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
client = new DefaultAcsClient(profile);
}
/**
* @return 是否解析成功 1 = ok ,-1 = 获取外网ip错误,-2 = 通过阿里云API解析时错误
*/
public static int parsingDNS(String outSideIP){
//将拿到的外部IP传入这里
if(outSideIP.equals("error")){
return -1;
}
DescribeDomainRecordsRequest request = new DescribeDomainRecordsRequest();
//必要参数,指定目标域名
request.setDomainName(TARGET_DOMAIN);
DescribeDomainRecordsResponse response;
try{
response = client.getAcsResponse(request);
//实际上前边的request.setDomainName(TARGET_DOMAIN)完整无误的话这里的list的长度就是1
List<Record> list = response.getDomainRecords();
String recordID = null;
for(Record record : list){
if(record.getDomainName().equals(TARGET_DOMAIN)){
recordID = record.getRecordId();//拿到待解析域名的RecordID,后边是必须参数
}
}
UpdateDomainRecordRequest updateReq = new UpdateDomainRecordRequest();
updateReq.setActionName("UpdateDomainRecord");//更新解析只能为UpdateDomainRecord,必填
updateReq.setValue(outSideIP);//解析记录值
updateReq.setRecordId(recordID);//在前边通过response.getDomainRecords()拿到
updateReq.setType("A");//解析类型
updateReq.setTTL(600L);//TTL,免费版最小值为600
updateReq.setRR("@");//主机记录
client.getAcsResponse(updateReq);//发送请求.在返回中好像拿不到ErrorCode一类的东西了,出错是直接抛出异常
return 1;
}catch (ClientException e){
e.printStackTrace();
Loggers.info(e.getCause()+" "+e.getMessage());
return -2;
}
}
//获取当前解析记录,程序初始化时可能有用
public static String getCurrentDNSVal() {
DescribeDomainRecordsRequest request = new DescribeDomainRecordsRequest();
request.setDomainName(TARGET_DOMAIN);
DescribeDomainRecordsResponse response;
try {
response = client.getAcsResponse(request);
List<Record> list = response.getDomainRecords();
for (Record record : list) {
if (record.getDomainName().equals(TARGET_DOMAIN)) {
return record.getValue();
}
}
} catch (ClientException e) {
e.printStackTrace();
Loggers.info(e.getCause() + " " + e.getMessage());
}
return "0.0.0.0";
}
}