更新定时任务
This commit is contained in:
@@ -15,8 +15,8 @@ import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/bizApi")
|
||||
public class bizController {
|
||||
@RequestMapping("/erpApi")
|
||||
public class erpController {
|
||||
|
||||
|
||||
@Resource
|
||||
@@ -1,4 +1,13 @@
|
||||
package com.mini.capi.api;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
@Controller
|
||||
public class startApp {
|
||||
|
||||
@GetMapping("/")
|
||||
public String redirectToSwagger() {
|
||||
return "redirect:/swagger-ui/index.html";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.mini.capi.biz.controller;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 主机信息表 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/biz/bizMonitorHost")
|
||||
public class BizMonitorHostController {
|
||||
|
||||
}
|
||||
128
src/main/java/com/mini/capi/biz/domain/BizMonitorHost.java
Normal file
128
src/main/java/com/mini/capi/biz/domain/BizMonitorHost.java
Normal file
@@ -0,0 +1,128 @@
|
||||
package com.mini.capi.biz.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 主机信息表
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@TableName("biz_monitor_host")
|
||||
public class BizMonitorHost implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 记录创建时间
|
||||
*/
|
||||
@TableField("create_time")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 主机唯一标识(自增主键)
|
||||
*/
|
||||
@TableId(value = "host_id", type = IdType.AUTO)
|
||||
private String hostId;
|
||||
|
||||
/**
|
||||
* 主机名称
|
||||
*/
|
||||
@TableField("hostname")
|
||||
private String hostname;
|
||||
|
||||
/**
|
||||
* IP地址
|
||||
*/
|
||||
@TableField("ip_address")
|
||||
private String ipAddress;
|
||||
|
||||
/**
|
||||
* 主机类型
|
||||
*/
|
||||
@TableField("host_type")
|
||||
private String hostType;
|
||||
|
||||
/**
|
||||
* 操作系统
|
||||
*/
|
||||
@TableField("host_os")
|
||||
private String hostOs;
|
||||
|
||||
/**
|
||||
* 主机状态(1-在线、0-离线、9-维护中)
|
||||
*/
|
||||
@TableField("ustatus")
|
||||
private String ustatus;
|
||||
|
||||
/**
|
||||
* 最后一次检测到在线的时间
|
||||
*/
|
||||
@TableField("last_online_time")
|
||||
private LocalDateTime lastOnlineTime;
|
||||
|
||||
/**
|
||||
* 物理位置
|
||||
*/
|
||||
@TableField("location_name")
|
||||
private String locationName;
|
||||
|
||||
/**
|
||||
* 管理人员
|
||||
*/
|
||||
@TableField("admin_user")
|
||||
private String adminUser;
|
||||
|
||||
/**
|
||||
* 联系方式
|
||||
*/
|
||||
@TableField("other_contact")
|
||||
private String otherContact;
|
||||
|
||||
/**
|
||||
* 备注信息
|
||||
*/
|
||||
@TableField("remark")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 记录最后更新时间
|
||||
*/
|
||||
@TableField("update_time")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 租户id
|
||||
*/
|
||||
@TableField("f_tenant_id")
|
||||
private String fTenantId;
|
||||
|
||||
/**
|
||||
* 流程id
|
||||
*/
|
||||
@TableField("f_flow_id")
|
||||
private String fFlowId;
|
||||
|
||||
/**
|
||||
* 流程任务主键
|
||||
*/
|
||||
@TableField("f_flow_task_id")
|
||||
private String fFlowTaskId;
|
||||
|
||||
/**
|
||||
* 流程任务状态
|
||||
*/
|
||||
@TableField("f_flow_state")
|
||||
private Integer fFlowState;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.mini.capi.biz.mapper;
|
||||
|
||||
import com.mini.capi.biz.domain.BizMonitorHost;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 主机信息表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
public interface BizMonitorHostMapper extends BaseMapper<BizMonitorHost> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.mini.capi.biz.service;
|
||||
|
||||
import com.mini.capi.biz.domain.BizMonitorHost;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 主机信息表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
public interface BizMonitorHostService extends IService<BizMonitorHost> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.mini.capi.biz.service.impl;
|
||||
|
||||
import com.mini.capi.biz.domain.BizMonitorHost;
|
||||
import com.mini.capi.biz.mapper.BizMonitorHostMapper;
|
||||
import com.mini.capi.biz.service.BizMonitorHostService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 主机信息表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author gaoxq
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
@Service
|
||||
public class BizMonitorHostServiceImpl extends ServiceImpl<BizMonitorHostMapper, BizMonitorHost> implements BizMonitorHostService {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.mini.capi.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
@Configuration
|
||||
@EnableAsync // 启用异步任务支持
|
||||
public class MonitorExecutorConfig {
|
||||
|
||||
/**
|
||||
* 配置主机监控专用线程池
|
||||
*/
|
||||
@Bean(name = "hostMonitorExecutor")
|
||||
public ThreadPoolTaskExecutor hostMonitorExecutor() {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
int corePoolSize = Runtime.getRuntime().availableProcessors();
|
||||
executor.setCorePoolSize(corePoolSize);
|
||||
executor.setMaxPoolSize(corePoolSize * 2);
|
||||
executor.setQueueCapacity(200);
|
||||
executor.setKeepAliveSeconds(60);
|
||||
executor.setThreadNamePrefix("Host-Monitor-");
|
||||
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
}
|
||||
14
src/main/java/com/mini/capi/config/WebMvcConfig.java
Normal file
14
src/main/java/com/mini/capi/config/WebMvcConfig.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package com.mini.capi.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
@Configuration
|
||||
public class WebMvcConfig implements WebMvcConfigurer{
|
||||
|
||||
@Override
|
||||
public void addViewControllers(ViewControllerRegistry registry) {
|
||||
// 访问根路径 "/" 时,自动重定向到 Swagger UI
|
||||
registry.addRedirectViewController("/", "/swagger-ui/index.html");
|
||||
}
|
||||
}
|
||||
60
src/main/java/com/mini/capi/job/jobController.java
Normal file
60
src/main/java/com/mini/capi/job/jobController.java
Normal file
@@ -0,0 +1,60 @@
|
||||
package com.mini.capi.job;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.mini.capi.biz.domain.BizMonitorHost;
|
||||
import com.mini.capi.biz.service.BizMonitorHostService;
|
||||
import com.mini.capi.utils.NetworkUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Controller
|
||||
public class jobController {
|
||||
|
||||
|
||||
@Resource
|
||||
private BizMonitorHostService bizMonitorHostService;
|
||||
|
||||
// 注入配置好的线程池
|
||||
@Resource(name = "hostMonitorExecutor")
|
||||
private ThreadPoolTaskExecutor hostMonitorExecutor;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Scheduled(cron = "0 0/10 * * * ?")
|
||||
public void getJobMonitHostStatus() {
|
||||
List<BizMonitorHost> monitorHosts = bizMonitorHostService.list();
|
||||
List<CompletableFuture<Void>> futures = new ArrayList<>(monitorHosts.size());
|
||||
for (BizMonitorHost monitorHost : monitorHosts) {
|
||||
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
UpdateWrapper<BizMonitorHost> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("host_id", monitorHost.getHostId());
|
||||
boolean isReachable = NetworkUtils.isNetworkReachable(monitorHost.getIpAddress());
|
||||
monitorHost.setUstatus(isReachable ? "1" : "0");
|
||||
if (isReachable) {
|
||||
monitorHost.setLastOnlineTime(LocalDateTime.now());
|
||||
}
|
||||
bizMonitorHostService.update(monitorHost, updateWrapper);
|
||||
} catch (Exception e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
}, hostMonitorExecutor); // 指定使用配置的线程池
|
||||
futures.add(future);
|
||||
}
|
||||
try {
|
||||
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
|
||||
.get(60, TimeUnit.SECONDS); // 超时时间可根据业务调整
|
||||
} catch (Exception e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ public class demo {
|
||||
.pathInfo(Collections.singletonMap(OutputFile.xml, System.getProperty("user.dir") + "/src/main/resources/mapper"));
|
||||
})
|
||||
.strategyConfig(builder -> {
|
||||
builder.addInclude("biz_cities,biz_company,biz_mail_account,biz_project_info,biz_project_requirements,biz_province,biz_resume_employee,erp_transfer,biz_website_storage,erp_period_summary,biz_municipalities,erp_account,erp_transaction_flow,erp_expense,erp_category,erp_income,biz_project_report,biz_mail_sent")
|
||||
builder.addInclude("biz_monitor_host")
|
||||
.addTablePrefix("biz_,erp_")
|
||||
.entityBuilder()
|
||||
.enableLombok()
|
||||
|
||||
125
src/main/java/com/mini/capi/utils/NetworkUtils.java
Normal file
125
src/main/java/com/mini/capi/utils/NetworkUtils.java
Normal file
@@ -0,0 +1,125 @@
|
||||
package com.mini.capi.utils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 网络连通性检测工具类(支持IPv4和域名)
|
||||
*/
|
||||
public class NetworkUtils {
|
||||
|
||||
// IPv4地址校验正则(支持带前后空白)
|
||||
private static final Pattern IPV4_PATTERN = Pattern.compile(
|
||||
"^\\s*((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\s*$"
|
||||
);
|
||||
|
||||
// Ping命令配置常量
|
||||
private static final int PING_COUNT = 2;
|
||||
private static final int WINDOWS_TIMEOUT_MS = 3000;
|
||||
private static final int LINUX_TIMEOUT_SEC = 3;
|
||||
private static final int PROCESS_WAIT_TIMEOUT_SEC = 6;
|
||||
|
||||
// 私有构造器:禁止实例化
|
||||
private NetworkUtils() {
|
||||
throw new AssertionError("工具类不允许实例化");
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测本地网络到目标IP或域名的连通性
|
||||
*/
|
||||
public static boolean isNetworkReachable(String target) {
|
||||
if (target == null || target.trim().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
target = target.trim();
|
||||
|
||||
List<String> ipList = new ArrayList<>();
|
||||
// 区分IP和域名,解析目标为IP列表
|
||||
if (isValidIpv4(target)) {
|
||||
ipList.add(target); // 是IP,直接加入
|
||||
} else {
|
||||
// 是域名,尝试解析为IP
|
||||
try {
|
||||
InetAddress[] addresses = InetAddress.getAllByName(target);
|
||||
for (InetAddress addr : addresses) {
|
||||
ipList.add(addr.getHostAddress());
|
||||
}
|
||||
if (ipList.isEmpty()) {
|
||||
return false; // 域名解析无结果
|
||||
}
|
||||
} catch (UnknownHostException e) {
|
||||
return false; // 域名无法解析(如不存在、网络故障)
|
||||
}
|
||||
}
|
||||
|
||||
// 对每个IP执行ping检测,有一个成功则返回true
|
||||
for (String ip : ipList) {
|
||||
if (executePingCommand(buildPingCommand(ip))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验是否为合法的IPv4地址(支持带前后空白)
|
||||
*/
|
||||
private static boolean isValidIpv4(String ip) {
|
||||
return IPV4_PATTERN.matcher(ip).matches();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建跨系统的ping命令
|
||||
*/
|
||||
private static List<String> buildPingCommand(String ip) {
|
||||
List<String> command = new ArrayList<>(5);
|
||||
command.add("ping");
|
||||
|
||||
String osName = System.getProperty("os.name", "").toLowerCase();
|
||||
if (osName.contains("windows")) {
|
||||
command.add("-n");
|
||||
command.add(String.valueOf(PING_COUNT));
|
||||
command.add("-w");
|
||||
command.add(String.valueOf(WINDOWS_TIMEOUT_MS));
|
||||
} else {
|
||||
command.add("-c");
|
||||
command.add(String.valueOf(PING_COUNT));
|
||||
command.add("-W");
|
||||
command.add(String.valueOf(LINUX_TIMEOUT_SEC));
|
||||
}
|
||||
|
||||
command.add(ip);
|
||||
return command;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行ping命令并返回执行结果
|
||||
*/
|
||||
private static boolean executePingCommand(List<String> command) {
|
||||
Process process = null;
|
||||
try {
|
||||
ProcessBuilder processBuilder = new ProcessBuilder(command);
|
||||
processBuilder.redirectErrorStream(true);
|
||||
process = processBuilder.start();
|
||||
|
||||
boolean isFinished = process.waitFor(PROCESS_WAIT_TIMEOUT_SEC, TimeUnit.SECONDS);
|
||||
if (!isFinished) {
|
||||
process.destroyForcibly();
|
||||
return false;
|
||||
}
|
||||
return process.exitValue() == 0;
|
||||
|
||||
} catch (IOException | InterruptedException e) {
|
||||
return false;
|
||||
} finally {
|
||||
if (process != null) {
|
||||
process.destroyForcibly();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
31
src/main/resources/mapper/BizMonitorHostMapper.xml
Normal file
31
src/main/resources/mapper/BizMonitorHostMapper.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.mini.capi.biz.mapper.BizMonitorHostMapper">
|
||||
|
||||
<!-- 通用查询映射结果 -->
|
||||
<resultMap id="BaseResultMap" type="com.mini.capi.biz.domain.BizMonitorHost">
|
||||
<id column="host_id" property="hostId" />
|
||||
<result column="create_time" property="createTime" />
|
||||
<result column="hostname" property="hostname" />
|
||||
<result column="ip_address" property="ipAddress" />
|
||||
<result column="host_type" property="hostType" />
|
||||
<result column="host_os" property="hostOs" />
|
||||
<result column="ustatus" property="ustatus" />
|
||||
<result column="last_online_time" property="lastOnlineTime" />
|
||||
<result column="location_name" property="locationName" />
|
||||
<result column="admin_user" property="adminUser" />
|
||||
<result column="other_contact" property="otherContact" />
|
||||
<result column="remark" property="remark" />
|
||||
<result column="update_time" property="updateTime" />
|
||||
<result column="f_tenant_id" property="fTenantId" />
|
||||
<result column="f_flow_id" property="fFlowId" />
|
||||
<result column="f_flow_task_id" property="fFlowTaskId" />
|
||||
<result column="f_flow_state" property="fFlowState" />
|
||||
</resultMap>
|
||||
|
||||
<!-- 通用查询结果列 -->
|
||||
<sql id="Base_Column_List">
|
||||
create_time, host_id, hostname, ip_address, host_type, host_os, ustatus, last_online_time, location_name, admin_user, other_contact, remark, update_time, f_tenant_id, f_flow_id, f_flow_task_id, f_flow_state
|
||||
</sql>
|
||||
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user