更新定时任务

This commit is contained in:
2025-11-10 15:03:59 +08:00
parent 2dd0dfdc40
commit 64baa08aa7
13 changed files with 471 additions and 3 deletions

View File

@@ -15,8 +15,8 @@ import java.math.BigDecimal;
import java.time.LocalDateTime;
@RestController
@RequestMapping("/bizApi")
public class bizController {
@RequestMapping("/erpApi")
public class erpController {
@Resource

View File

@@ -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";
}
}

View File

@@ -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 {
}

View 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;
}

View File

@@ -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> {
}

View File

@@ -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> {
}

View File

@@ -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 {
}

View File

@@ -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;
}
}

View 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");
}
}

View 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());
}
}
}

View File

@@ -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()

View 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();
}
}
}
}

View 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>