之前申请了公网IP,这样调试接口的时候可以直接远程调试,但因为申请的公网IP会随时变化,所以使用阿里云DDNS服务,随时绑定公网IP,直接域名访问服务。
1.创建阿里云账号和访问密钥(AccessKey)
AccessKey是您访问阿里云API的密钥,使用阿里SDK进行操作必须先获取AccessKey!
创建地址:https://usercenter.console.aliyun.com/
因为主账号权限过于强大,所以尽量使用子账号AccessKey并赋予需要使用的权限,这里我们点击“开始使用子账号AccessKey”。
这里我们进行简单操作,直接点击创建用户即可
名称随意,控制台权限随意,但要注意选择OpenAPI访问!
创建成功后,需要添加AccessKey,点击创建。
注意:创建成功后一定要记住AccessKey等相关信息,如果忘记,只能创建新的key代替!
之后点击权限管理,添加权限!
找到“管理云解析(DNS)的权限”添加即可。
2.使用SDK绑定动态IP绑定
创建Maven项目并加入阿里云SDK依赖
<dependencies>
<!-- https://mvnrepository.com/artifact/com.aliyun/aliyun-java-sdk-core -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.4.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.aliyun/aliyun-java-sdk-alidns -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-alidns</artifactId>
<version>2.0.10</version>
</dependency>
</dependencies>
示例代码:
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.alidns.model.v20150109.DescribeDomainRecordsRequest;
import com.aliyuncs.alidns.model.v20150109.DescribeDomainRecordsResponse;
import com.aliyuncs.alidns.model.v20150109.UpdateDomainRecordRequest;
import com.aliyuncs.alidns.model.v20150109.UpdateDomainRecordResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.google.gson.Gson;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 动态域名解析
*/
public class DDNS {
/**
* 获取主域名的所有解析记录列表
*/
private DescribeDomainRecordsResponse describeDomainRecords(DescribeDomainRecordsRequest request, IAcsClient client){
try {
// 调用SDK发送请求
return client.getAcsResponse(request);
} catch (ClientException e) {
e.printStackTrace();
// 发生调用错误,抛出运行时异常
throw new RuntimeException();
}
}
/**
* 获取当前主机公网IP
*/
private String getCurrentHostIP(){
// 这里使用jsonip.com第三方接口获取本地IP
String jsonip = "https://jsonip.com/";
// 接口返回结果
String result = "";
BufferedReader in = null;
try {
// 使用HttpURLConnection网络请求第三方接口
URL url = new URL(jsonip);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
in = new BufferedReader(new InputStreamReader(
urlConnection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
e.printStackTrace();
}
// 使用finally块来关闭输入流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
// 正则表达式,提取xxx.xxx.xxx.xxx,将IP地址从接口返回结果中提取出来
String rexp = "(\\d{1,3}\\.){3}\\d{1,3}";
Pattern pat = Pattern.compile(rexp);
Matcher mat = pat.matcher(result);
String res="";
while (mat.find()) {
res=mat.group();
break;
}
return res;
}
/**
* 修改解析记录
*/
private UpdateDomainRecordResponse updateDomainRecord(UpdateDomainRecordRequest request, IAcsClient client){
try {
// 调用SDK发送请求
return client.getAcsResponse(request);
} catch (ClientException e) {
e.printStackTrace();
// 发生调用错误,抛出运行时异常
throw new RuntimeException();
}
}
private static void log_print(String functionName, Object result) {
Gson gson = new Gson();
System.out.println("-------------------------------" + functionName + "-------------------------------");
System.out.println(gson.toJson(result));
}
public static void main(String[] args) {
// 设置鉴权参数,初始化客户端
DefaultProfile profile = DefaultProfile.getProfile(
"cn-qingdao",// 地域ID
"your-access-key-id",// 您的AccessKey ID
"your-access-key-secret");// 您的AccessKey Secret
IAcsClient client = new DefaultAcsClient(profile);
DDNS ddns = new DDNS();
// 查询指定二级域名的最新解析记录
DescribeDomainRecordsRequest describeDomainRecordsRequest = new DescribeDomainRecordsRequest();
// 主域名
describeDomainRecordsRequest.setDomainName("example.com");
// 主机记录
describeDomainRecordsRequest.setRRKeyWord("ddnstest");
// 解析记录类型
describeDomainRecordsRequest.setType("A");
DescribeDomainRecordsResponse describeDomainRecordsResponse = ddns.describeDomainRecords(describeDomainRecordsRequest, client);
log_print("describeDomainRecords",describeDomainRecordsResponse);
List<DescribeDomainRecordsResponse.Record> domainRecords = describeDomainRecordsResponse.getDomainRecords();
// 最新的一条解析记录
if(domainRecords.size() != 0 ){
DescribeDomainRecordsResponse.Record record = domainRecords.get(0);
// 记录ID
String recordId = record.getRecordId();
// 记录值
String recordsValue = record.getValue();
// 当前主机公网IP
String currentHostIP = ddns.getCurrentHostIP();
System.out.println("-------------------------------当前主机公网IP为:"+currentHostIP+"-------------------------------");
if(!currentHostIP.equals(recordsValue)){
// 修改解析记录
UpdateDomainRecordRequest updateDomainRecordRequest = new UpdateDomainRecordRequest();
// 主机记录
updateDomainRecordRequest.setRR("ddnstest");
// 记录ID
updateDomainRecordRequest.setRecordId(recordId);
// 将主机记录值改为当前主机IP
updateDomainRecordRequest.setValue(currentHostIP);
// 解析记录类型
updateDomainRecordRequest.setType("A");
UpdateDomainRecordResponse updateDomainRecordResponse = ddns.updateDomainRecord(updateDomainRecordRequest, client);
log_print("updateDomainRecord",updateDomainRecordResponse);
}
}
}
}
此处注意,有四个地方需要改动:
your-access-key-id
,your-access-key-secret
,这两处对应了之前申请的AccessKey,填写即可。
example.com
:这里需要修改为申请的域名,直接修改即可。
ddnstest
:主机记录,按照域名解析设置中填写即可
直接执行即可,免去手动修改域名。
如果有服务器不停机的需求,还可以直接使用定时任务循环之形态吗,检测到域名更改则重新绑定:
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.alidns.model.v20150109.DescribeDomainRecordsRequest;
import com.aliyuncs.alidns.model.v20150109.DescribeDomainRecordsResponse;
import com.aliyuncs.alidns.model.v20150109.UpdateDomainRecordRequest;
import com.aliyuncs.alidns.model.v20150109.UpdateDomainRecordResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.google.gson.Gson;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 动态域名解析
*/
public class DDNS {
/**
* 获取主域名的所有解析记录列表
*/
private DescribeDomainRecordsResponse describeDomainRecords(DescribeDomainRecordsRequest request, IAcsClient client){
try {
// 调用SDK发送请求
return client.getAcsResponse(request);
} catch (ClientException e) {
e.printStackTrace();
// 发生调用错误,抛出运行时异常
throw new RuntimeException();
}
}
/**
* 获取当前主机公网IP
*/
private String getCurrentHostIP(){
// 这里使用jsonip.com第三方接口获取本地IP
String jsonip = "https://jsonip.com/";
// 接口返回结果
String result = "";
BufferedReader in = null;
try {
// 使用HttpURLConnection网络请求第三方接口
URL url = new URL(jsonip);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
in = new BufferedReader(new InputStreamReader(
urlConnection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
e.printStackTrace();
}
// 使用finally块来关闭输入流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
// 正则表达式,提取xxx.xxx.xxx.xxx,将IP地址从接口返回结果中提取出来
String rexp = "(\\d{1,3}\\.){3}\\d{1,3}";
Pattern pat = Pattern.compile(rexp);
Matcher mat = pat.matcher(result);
String res="";
while (mat.find()) {
res=mat.group();
break;
}
return res;
}
/**
* 修改解析记录
*/
private UpdateDomainRecordResponse updateDomainRecord(UpdateDomainRecordRequest request, IAcsClient client){
try {
// 调用SDK发送请求
return client.getAcsResponse(request);
} catch (ClientException e) {
e.printStackTrace();
// 发生调用错误,抛出运行时异常
throw new RuntimeException();
}
}
public static void checkIP()
{
System.err.println("————————————————————————————————————————————————————————————————————————————————————————————————————");
System.err.println("任务开始,当前时间为:"+ LocalDateTime.now());
// 设置鉴权参数,初始化客户端
DefaultProfile profile = DefaultProfile.getProfile(
"cn-qingdao",// 地域ID
"",// 您的AccessKey ID
"");// 您的AccessKey Secret
IAcsClient client = new DefaultAcsClient(profile);
DDNS ddns = new DDNS();
// 查询指定二级域名的最新解析记录
DescribeDomainRecordsRequest describeDomainRecordsRequest = new DescribeDomainRecordsRequest();
// 主域名
describeDomainRecordsRequest.setDomainName("");
// 主机记录
describeDomainRecordsRequest.setRRKeyWord("@");
// 解析记录类型
describeDomainRecordsRequest.setType("A");
DescribeDomainRecordsResponse describeDomainRecordsResponse = ddns.describeDomainRecords(describeDomainRecordsRequest, client);
List<DescribeDomainRecordsResponse.Record> domainRecords = describeDomainRecordsResponse.getDomainRecords();
// 最新的一条解析记录
if(domainRecords.size() != 0 ){
DescribeDomainRecordsResponse.Record record = domainRecords.get(0);
// 记录ID
String recordId = record.getRecordId();
// 记录值
String recordsValue = record.getValue();
// 当前主机公网IP
String currentHostIP = ddns.getCurrentHostIP();
System.err.println("云解析IP为:"+recordsValue);
System.err.println("当前主机公网IP为:"+currentHostIP);
if(!currentHostIP.equals(recordsValue)){
// 修改解析记录
UpdateDomainRecordRequest updateDomainRecordRequest = new UpdateDomainRecordRequest();
// 主机记录
updateDomainRecordRequest.setRR("@");
// 记录ID
updateDomainRecordRequest.setRecordId(recordId);
// 将主机记录值改为当前主机IP
updateDomainRecordRequest.setValue(currentHostIP);
// 解析记录类型
updateDomainRecordRequest.setType("A");
UpdateDomainRecordResponse updateDomainRecordResponse = ddns.updateDomainRecord(updateDomainRecordRequest, client);
System.err.println("云解析IP更新成功");
}else{
System.err.println("IP相同无需更新");
}
}
}
public static void main(String[] args) {
// 创建一个ScheduledThreadPoolExecutor线程池,核心线程数为5
ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(1);
// 创建Runnable打印当前线程和当前时间
Runnable r = () -> checkIP();
// 在指定1秒延迟后执行r,之后每30秒执行一次
scheduledExecutorService.scheduleAtFixedRate(r, 1, 30, TimeUnit.SECONDS);
}
}
后台执行即可!