执行器新增"注册方式"和"机器地址"属性,支持手动录入机器地址;
This commit is contained in:
parent
a057b2d00e
commit
338d3b62a5
12
README.md
12
README.md
|
@ -732,12 +732,12 @@ Tips: 历史版本(V1.3.x)目前已经Release至稳定版本, 进入维护阶段
|
||||||
- 8、GLUE依赖注入逻辑优化,支持别名注入;
|
- 8、GLUE依赖注入逻辑优化,支持别名注入;
|
||||||
|
|
||||||
#### 6.11 版本 V1.6.0 特性(CODING)
|
#### 6.11 版本 V1.6.0 特性(CODING)
|
||||||
- 1、通讯:hex 通讯调整为 http-rpc 模式;
|
- 1、通讯方案升级,原基于HEX的通讯模型调整为基于HTTP的二进制RPC的通讯模型;
|
||||||
- 2、线程模型统一;
|
- 2、规范线程模型统一,统一线程销毁方案;
|
||||||
- 3、执行器支持手动设置执行地址列表,提供开关切换使用注册地址还是手动设置的地址;
|
- 3、CleanCode,清理无效的历史参数;
|
||||||
- 4、执行器路由规则:第一个、循环、随机、顺序故障(默认)转移;
|
- 4、规范系统配置数据,通过配置文件统一管理;
|
||||||
- 5、CleanCode,清理无效的历史参数;
|
- 5、执行器支持手动设置执行地址列表,提供开关切换使用注册地址还是手动设置的地址;
|
||||||
- 6、规范系统配置数据,通过配置文件统一管理;
|
- 6、执行器路由规则:第一个、循环、随机、顺序故障(默认)转移;
|
||||||
|
|
||||||
#### TODO LIST
|
#### TODO LIST
|
||||||
- 1、支持脚本JOB(源码或指定路径), 即shell/python/php等, 日志实时输出并支持在线监控;定制JobHandler实现;
|
- 1、支持脚本JOB(源码或指定路径), 即shell/python/php等, 日志实时输出并支持在线监控;定制JobHandler实现;
|
||||||
|
|
|
@ -201,14 +201,17 @@ CREATE TABLE XXL_JOB_QRTZ_TRIGGER_REGISTRY (
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
CREATE TABLE XXL_JOB_QRTZ_TRIGGER_GROUP (
|
CREATE TABLE `XXL_JOB_QRTZ_TRIGGER_GROUP` (
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
`app_name` varchar(64) NOT NULL,
|
`app_name` varchar(64) NOT NULL COMMENT '执行器AppName',
|
||||||
`title` varchar(12) NOT NULL,
|
`title` varchar(12) NOT NULL COMMENT '执行器名称',
|
||||||
`order` tinyint(4) NOT NULL,
|
`order` tinyint(4) NOT NULL DEFAULT '0' COMMENT '排序',
|
||||||
|
`address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型:0=自动注册、1=手动录入',
|
||||||
|
`address_list` varchar(200) DEFAULT NULL COMMENT '执行器地址列表,多地址逗号分隔',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
INSERT INTO `XXL_JOB_QRTZ_TRIGGER_GROUP` VALUES ('1', 'xxl-job-executor-example', '示例执行器', '1');
|
|
||||||
|
INSERT INTO `XXL_JOB_QRTZ_TRIGGER_GROUP` ( `app_name`, `title`, `order`, `address_type`, `address_list`) values ( 'xxl-job-executor-example', '示例执行器', '1', '0', null);
|
||||||
|
|
||||||
commit;
|
commit;
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,7 +41,14 @@ public class JobGroupController {
|
||||||
|
|
||||||
if (CollectionUtils.isNotEmpty(list)) {
|
if (CollectionUtils.isNotEmpty(list)) {
|
||||||
for (XxlJobGroup group: list) {
|
for (XxlJobGroup group: list) {
|
||||||
List<String> registryList = JobRegistryHelper.discover(RegistHelper.RegistType.EXECUTOR.name(), group.getAppName());
|
List<String> registryList = null;
|
||||||
|
if (group.getAddressType() == 0) {
|
||||||
|
registryList = JobRegistryHelper.discover(RegistHelper.RegistType.EXECUTOR.name(), group.getAppName());
|
||||||
|
} else {
|
||||||
|
if (StringUtils.isNotBlank(group.getAddressList())) {
|
||||||
|
registryList = Arrays.asList(group.getAddressList().split(","));
|
||||||
|
}
|
||||||
|
}
|
||||||
group.setRegistryList(registryList);
|
group.setRegistryList(registryList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,6 +72,17 @@ public class JobGroupController {
|
||||||
if (xxlJobGroup.getTitle()==null || StringUtils.isBlank(xxlJobGroup.getTitle())) {
|
if (xxlJobGroup.getTitle()==null || StringUtils.isBlank(xxlJobGroup.getTitle())) {
|
||||||
return new ReturnT<String>(500, "请输入名称");
|
return new ReturnT<String>(500, "请输入名称");
|
||||||
}
|
}
|
||||||
|
if (xxlJobGroup.getAddressType()!=0) {
|
||||||
|
if (StringUtils.isBlank(xxlJobGroup.getAddressList())) {
|
||||||
|
return new ReturnT<String>(500, "手动录入注册方式,机器地址不可为空");
|
||||||
|
}
|
||||||
|
String[] addresss = xxlJobGroup.getAddressList().split(",");
|
||||||
|
for (String item: addresss) {
|
||||||
|
if (StringUtils.isBlank(item)) {
|
||||||
|
return new ReturnT<String>(500, "机器地址非法");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int ret = xxlJobGroupDao.save(xxlJobGroup);
|
int ret = xxlJobGroupDao.save(xxlJobGroup);
|
||||||
return (ret>0)?ReturnT.SUCCESS:ReturnT.FAIL;
|
return (ret>0)?ReturnT.SUCCESS:ReturnT.FAIL;
|
||||||
|
@ -82,6 +101,17 @@ public class JobGroupController {
|
||||||
if (xxlJobGroup.getTitle()==null || StringUtils.isBlank(xxlJobGroup.getTitle())) {
|
if (xxlJobGroup.getTitle()==null || StringUtils.isBlank(xxlJobGroup.getTitle())) {
|
||||||
return new ReturnT<String>(500, "请输入名称");
|
return new ReturnT<String>(500, "请输入名称");
|
||||||
}
|
}
|
||||||
|
if (xxlJobGroup.getAddressType()!=0) {
|
||||||
|
if (StringUtils.isBlank(xxlJobGroup.getAddressList())) {
|
||||||
|
return new ReturnT<String>(500, "手动录入注册方式,机器地址不可为空");
|
||||||
|
}
|
||||||
|
String[] addresss = xxlJobGroup.getAddressList().split(",");
|
||||||
|
for (String item: addresss) {
|
||||||
|
if (StringUtils.isBlank(item)) {
|
||||||
|
return new ReturnT<String>(500, "机器地址非法");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int ret = xxlJobGroupDao.update(xxlJobGroup);
|
int ret = xxlJobGroupDao.update(xxlJobGroup);
|
||||||
return (ret>0)?ReturnT.SUCCESS:ReturnT.FAIL;
|
return (ret>0)?ReturnT.SUCCESS:ReturnT.FAIL;
|
||||||
|
|
|
@ -11,9 +11,11 @@ public class XxlJobGroup {
|
||||||
private String appName;
|
private String appName;
|
||||||
private String title;
|
private String title;
|
||||||
private int order;
|
private int order;
|
||||||
|
private int addressType; // 执行器地址类型:0=自动注册、1=手动录入
|
||||||
|
private String addressList; // 执行器地址列表,多地址逗号分隔(手动录入)
|
||||||
|
|
||||||
// registry list
|
// registry list
|
||||||
private List<String> registryList;
|
private List<String> registryList; // 执行器地址列表(系统注册)
|
||||||
|
|
||||||
public int getId() {
|
public int getId() {
|
||||||
return id;
|
return id;
|
||||||
|
@ -54,4 +56,20 @@ public class XxlJobGroup {
|
||||||
public void setRegistryList(List<String> registryList) {
|
public void setRegistryList(List<String> registryList) {
|
||||||
this.registryList = registryList;
|
this.registryList = registryList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getAddressType() {
|
||||||
|
return addressType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAddressType(int addressType) {
|
||||||
|
this.addressType = addressType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAddressList() {
|
||||||
|
return addressList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAddressList(String addressList) {
|
||||||
|
this.addressList = addressList;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,9 +39,11 @@ public class JobRegistryHelper {
|
||||||
XxlJobDynamicScheduler.xxlJobRegistryDao.registrySave(RegistHelper.RegistType.ADMIN.name(), RegistHelper.RegistType.ADMIN.name(), XxlJobDynamicScheduler.getCallbackAddress());
|
XxlJobDynamicScheduler.xxlJobRegistryDao.registrySave(RegistHelper.RegistType.ADMIN.name(), RegistHelper.RegistType.ADMIN.name(), XxlJobDynamicScheduler.getCallbackAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove dead admin/executor
|
||||||
|
XxlJobDynamicScheduler.xxlJobRegistryDao.removeDead(RegistHelper.TIMEOUT*2);
|
||||||
|
|
||||||
// fresh registry map
|
// fresh registry map
|
||||||
ConcurrentHashMap<String, List<String>> temp = new ConcurrentHashMap<String, List<String>>();
|
ConcurrentHashMap<String, List<String>> temp = new ConcurrentHashMap<String, List<String>>();
|
||||||
XxlJobDynamicScheduler.xxlJobRegistryDao.removeDead(RegistHelper.TIMEOUT*2);
|
|
||||||
List<XxlJobRegistry> list = XxlJobDynamicScheduler.xxlJobRegistryDao.findAll(RegistHelper.TIMEOUT*2);
|
List<XxlJobRegistry> list = XxlJobDynamicScheduler.xxlJobRegistryDao.findAll(RegistHelper.TIMEOUT*2);
|
||||||
if (list != null) {
|
if (list != null) {
|
||||||
for (XxlJobRegistry item: list) {
|
for (XxlJobRegistry item: list) {
|
||||||
|
|
|
@ -8,13 +8,17 @@
|
||||||
<result column="app_name" property="appName" />
|
<result column="app_name" property="appName" />
|
||||||
<result column="title" property="title" />
|
<result column="title" property="title" />
|
||||||
<result column="order" property="order" />
|
<result column="order" property="order" />
|
||||||
|
<result column="address_type" property="addressType" />
|
||||||
|
<result column="address_list" property="addressList" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<sql id="Base_Column_List">
|
<sql id="Base_Column_List">
|
||||||
t.id,
|
t.id,
|
||||||
t.app_name,
|
t.app_name,
|
||||||
t.title,
|
t.title,
|
||||||
t.order
|
t.order,
|
||||||
|
t.address_type,
|
||||||
|
t.address_list
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
<select id="findAll" parameterType="java.lang.Integer" resultMap="XxlJobGroup">
|
<select id="findAll" parameterType="java.lang.Integer" resultMap="XxlJobGroup">
|
||||||
|
@ -24,15 +28,17 @@
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<insert id="save" parameterType="com.xxl.job.admin.core.model.XxlJobGroup" >
|
<insert id="save" parameterType="com.xxl.job.admin.core.model.XxlJobGroup" >
|
||||||
INSERT INTO XXL_JOB_QRTZ_TRIGGER_GROUP ( `app_name`, `title`, `order`)
|
INSERT INTO XXL_JOB_QRTZ_TRIGGER_GROUP ( `app_name`, `title`, `order`, `address_type`, `address_list`)
|
||||||
values ( #{appName}, #{title}, #{order});
|
values ( #{appName}, #{title}, #{order}, #{addressType}, #{addressList});
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
<update id="update" parameterType="com.xxl.job.admin.core.model.XxlJobGroup" >
|
<update id="update" parameterType="com.xxl.job.admin.core.model.XxlJobGroup" >
|
||||||
UPDATE XXL_JOB_QRTZ_TRIGGER_GROUP
|
UPDATE XXL_JOB_QRTZ_TRIGGER_GROUP
|
||||||
SET `app_name` = #{appName},
|
SET `app_name` = #{appName},
|
||||||
`title` = #{title},
|
`title` = #{title},
|
||||||
`order` = #{order}
|
`order` = #{order},
|
||||||
|
`address_type` = #{addressType},
|
||||||
|
`address_list` = #{addressList}
|
||||||
WHERE id = #{id}
|
WHERE id = #{id}
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
|
|
|
@ -33,16 +33,17 @@
|
||||||
<h3 class="box-title">执行器列表</h3>
|
<h3 class="box-title">执行器列表</h3>
|
||||||
<button class="btn btn-info btn-xs pull-left2 add" >+新增执行器</button>
|
<button class="btn btn-info btn-xs pull-left2 add" >+新增执行器</button>
|
||||||
|
|
||||||
调度中心OnLine:<#if adminAddressList?exists><#list adminAddressList as item><span class="badge bg-green">${item}</span></#list></#if>
|
调度中心OnLine机器:<#if adminAddressList?exists><#list adminAddressList as item><span class="badge bg-green">${item}</span></#list></#if>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body">
|
<div class="box-body">
|
||||||
<table id="joblog_list" class="table table-bordered table-striped display" width="100%" >
|
<table id="joblog_list" class="table table-bordered table-striped display" width="100%" >
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th name="id" >ID</th>
|
<#--<th name="id" >ID</th>-->
|
||||||
|
<th name="order" >排序</th>
|
||||||
<th name="appName" >AppName</th>
|
<th name="appName" >AppName</th>
|
||||||
<th name="title" >名称</th>
|
<th name="title" >名称</th>
|
||||||
<th name="order" >排序</th>
|
<th name="addressType" >注册方式</th>
|
||||||
<th name="registryList" >OnLine 机器</th>
|
<th name="registryList" >OnLine 机器</th>
|
||||||
<th name="operate" >操作</th>
|
<th name="operate" >操作</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -51,13 +52,20 @@
|
||||||
<#if list?exists && list?size gt 0>
|
<#if list?exists && list?size gt 0>
|
||||||
<#list list as group>
|
<#list list as group>
|
||||||
<tr>
|
<tr>
|
||||||
<td>${group.id}</td>
|
<#--<td>${group.id}</td>-->
|
||||||
|
<td>${group.order}</td>
|
||||||
<td>${group.appName}</td>
|
<td>${group.appName}</td>
|
||||||
<td>${group.title}</td>
|
<td>${group.title}</td>
|
||||||
<td>${group.order}</td>
|
<td><#if group.addressType==0>自动注册<#else>手动录入</#if></td>
|
||||||
<td><#if group.registryList?exists><#list group.registryList as item><span class="badge bg-green">${item}</span><br></#list></#if></td>
|
<td><#if group.registryList?exists><#list group.registryList as item><span class="badge bg-green">${item}</span><br></#list></#if></td>
|
||||||
<td>
|
<td>
|
||||||
<button class="btn btn-warning btn-xs update" id="${group.id}" appName="${group.appName}" title="${group.title}" order="${group.order}" >编辑</button>
|
<button class="btn btn-warning btn-xs update"
|
||||||
|
id="${group.id}"
|
||||||
|
appName="${group.appName}"
|
||||||
|
title="${group.title}"
|
||||||
|
order="${group.order}"
|
||||||
|
addressType="${group.addressType}"
|
||||||
|
addressList="${group.addressList}" >编辑</button>
|
||||||
<button class="btn btn-danger btn-xs remove" id="${group.id}" >删除</button>
|
<button class="btn btn-danger btn-xs remove" id="${group.id}" >删除</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -93,6 +101,18 @@
|
||||||
<label for="lastname" class="col-sm-2 control-label">排序<font color="red">*</font></label>
|
<label for="lastname" class="col-sm-2 control-label">排序<font color="red">*</font></label>
|
||||||
<div class="col-sm-10"><input type="text" class="form-control" name="order" placeholder="请输入“排序”" maxlength="50" ></div>
|
<div class="col-sm-10"><input type="text" class="form-control" name="order" placeholder="请输入“排序”" maxlength="50" ></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="lastname" class="col-sm-2 control-label">注册方式<font color="red">*</font></label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input type="radio" name="addressType" value="0" checked />自动注册
|
||||||
|
|
||||||
|
<input type="radio" name="addressType" value="1" />手动录入
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="lastname" class="col-sm-2 control-label">机器地址<font color="red">*</font></label>
|
||||||
|
<div class="col-sm-10"><input type="text" class="form-control" name="addressList" placeholder="请输入执行器地址列表,多地址逗号分隔" maxlength="200" readonly="readonly" ></div>
|
||||||
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-sm-offset-3 col-sm-6">
|
<div class="col-sm-offset-3 col-sm-6">
|
||||||
|
@ -127,6 +147,18 @@
|
||||||
<label for="lastname" class="col-sm-2 control-label">排序<font color="red">*</font></label>
|
<label for="lastname" class="col-sm-2 control-label">排序<font color="red">*</font></label>
|
||||||
<div class="col-sm-10"><input type="text" class="form-control" name="order" placeholder="请输入“排序”" maxlength="50" ></div>
|
<div class="col-sm-10"><input type="text" class="form-control" name="order" placeholder="请输入“排序”" maxlength="50" ></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="lastname" class="col-sm-2 control-label">注册方式<font color="red">*</font></label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input type="radio" name="addressType" value="0" />自动注册
|
||||||
|
|
||||||
|
<input type="radio" name="addressType" value="1" />手动录入
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="lastname" class="col-sm-2 control-label">机器地址<font color="red">*</font></label>
|
||||||
|
<div class="col-sm-10"><input type="text" class="form-control" name="addressList" placeholder="请输入执行器地址列表,多地址逗号分隔" maxlength="200" readonly="readonly" ></div>
|
||||||
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-sm-offset-3 col-sm-6">
|
<div class="col-sm-offset-3 col-sm-6">
|
||||||
|
|
|
@ -107,12 +107,33 @@ $(function() {
|
||||||
$("#addModal .form .form-group").removeClass("has-error");
|
$("#addModal .form .form-group").removeClass("has-error");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 注册方式,切换
|
||||||
|
$("#addModal input[name=addressType], #updateModal input[name=addressType]").click(function(){
|
||||||
|
var addressType = $(this).val();
|
||||||
|
var $addressList = $(this).parents("form").find("input[name=addressList]");
|
||||||
|
if (addressType == 0) {
|
||||||
|
$addressList.val("");
|
||||||
|
$addressList.attr("readonly","readonly");
|
||||||
|
} else {
|
||||||
|
$addressList.removeAttr("readonly");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// update
|
||||||
$('.update').on('click', function(){
|
$('.update').on('click', function(){
|
||||||
$("#updateModal .form input[name='id']").val($(this).attr("id"));
|
$("#updateModal .form input[name='id']").val($(this).attr("id"));
|
||||||
$("#updateModal .form input[name='appName']").val($(this).attr("appName"));
|
$("#updateModal .form input[name='appName']").val($(this).attr("appName"));
|
||||||
$("#updateModal .form input[name='title']").val($(this).attr("title"));
|
$("#updateModal .form input[name='title']").val($(this).attr("title"));
|
||||||
$("#updateModal .form input[name='order']").val($(this).attr("order"));
|
$("#updateModal .form input[name='order']").val($(this).attr("order"));
|
||||||
|
|
||||||
|
// 注册方式
|
||||||
|
var addressType = $(this).attr("addressType");
|
||||||
|
$("#updateModal .form input[name='addressType']").removeAttr('checked');
|
||||||
|
//$("#updateModal .form input[name='addressType'][value='"+ addressType +"']").attr('checked', 'true');
|
||||||
|
$("#updateModal .form input[name='addressType'][value='"+ addressType +"']").click();
|
||||||
|
// 机器地址
|
||||||
|
$("#updateModal .form input[name='addressList']").val($(this).attr("addressList"));
|
||||||
|
|
||||||
$('#updateModal').modal({backdrop: false, keyboard: false}).modal('show');
|
$('#updateModal').modal({backdrop: false, keyboard: false}).modal('show');
|
||||||
});
|
});
|
||||||
var updateModalValidate = $("#updateModal .form").validate({
|
var updateModalValidate = $("#updateModal .form").validate({
|
||||||
|
|
|
@ -16,9 +16,9 @@ import java.util.regex.Pattern;
|
||||||
public class IpUtil {
|
public class IpUtil {
|
||||||
private static final Logger logger = LoggerFactory.getLogger(IpUtil.class);
|
private static final Logger logger = LoggerFactory.getLogger(IpUtil.class);
|
||||||
|
|
||||||
public static final String ANYHOST = "0.0.0.0";
|
private static final String ANYHOST = "0.0.0.0";
|
||||||
public static final String LOCALHOST = "127.0.0.1";
|
private static final String LOCALHOST = "127.0.0.1";
|
||||||
private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$");
|
public static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$");
|
||||||
|
|
||||||
private static volatile InetAddress LOCAL_ADDRESS = null;
|
private static volatile InetAddress LOCAL_ADDRESS = null;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue