一. 系统启动时执行定时任务
一.一 服务启动后执行定时任务
在系统启动时,我们常常需要初始化一些数据,如构造出必要的数据,将数据库中的某些数据提前写入到缓存里面,获取当前服务器的相关信息等。
@SpringBootApplication public class InitApplication { public static void main(String[] args) { SpringApplication.run(InitApplication.class,args); System.out.println(">>>>>>>项目启动成功"); //执行初始化数据. initData(); } public static void initData(){ System.out.println("静态方法初始化数据"); } }
这样的操作, initData() 并不是系统启动时执行的定时任务,而是系统启动后执行的.
这样写,当不牵扯到组件 @Component 相关的注解方法时,也就是说只有简单的方法处理时,虽然可以进行初始化数据,但不规范,一般不采用这种方式处理.
本章节代码层次结构如下:
定义一个接口和一个实现
UserService 接口
public interface UserService { public void set(); public void get(); }
UserServiceImpl 实现
@Service public class UserServiceImpl implements UserService { @Override public void set() { System.out.println("UserService--->set值"); } @Override public void get() { System.out.println("UserService--->取出值"); } }
一.二 Listener 监听器执行定时任务
在 JSP /Servlet 时,我们常常使用 Listener 监听器来初始化数据.
SpringBoot 也支持这种形式.
一.二.一 事件监听器 InitListener
在 listener 包下创建事件监听器
package top.yueshushu.init.listener; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; /** * @ClassName:InitListener * @Description 监听器 * @Author zk_yjl * @Date 2021/11/30 9:00 * @Version 1.0 * @Since 1.0 **/ public class InitListener implements ServletContextListener { /** 容器启动时 */ @Override public void contextInitialized(ServletContextEvent sce) { //初始化必要的数据. 常于构建缓存,初始化数据. System.out.println(">>>>Listener,容器启动,初始化必要的数据"); } /** 容器突然销毁时 */ @Override public void contextDestroyed(ServletContextEvent sce) { //容器关闭了,进行数据备份的处理. System.out.println(">>>>Listener,容器销毁,将重要数据备份"); } }
一.二.二 启动添加 Listener
@SpringBootApplication public class InitApplication { public static void main(String[] args) { SpringApplication.run(InitApplication.class,args); System.out.println(">>>>>>>项目启动成功"); //执行初始化数据. // initData(); } /* public static void initData(){ System.out.println("静态方法初始化数据"); } */ /** * 添加Listener * @date 2021/11/30 9:03 * @author zk_yjl * @return */ @Bean public ServletListenerRegistrationBean<InitListener> initListenerServletListenerRegistrationBean(){ ServletListenerRegistrationBean<InitListener> registrationBean=new ServletListenerRegistrationBean<>( new InitListener() ); return registrationBean; } }
在项目启动之前执行了,初始化 ExecutorService 之前.
二. SpringBoot 系统启动任务
通常使用 CommandLineRunner , ApplicationRunner , 和 @PostConstruct三种方式进行处理
关于参数的使用,可以参考江南一点雨大神的这篇文章.
二.一 CommandLineRunner 方式
如启动时,获取机器码
二.一.一 获取机器码的工具类 HardwareUtil
package top.yueshushu.init.util; import lombok.extern.log4j.Log4j2; import org.springframework.util.StringUtils; import java.io.IOException; import java.io.InputStream; import java.net.NetworkInterface; import java.net.SocketException; import java.util.Arrays; import java.util.Enumeration; import java.util.List; import java.util.Scanner; @Log4j2 public class HardwareUtil { private static final String[] getCpuIdWindows = {"wmic", "cpu", "get", "ProcessorId"}; private static String cpuId; public static String getCpuId() { try{ String osName = getOsName(); String cpuId = null; if (osName.toLowerCase().contains("linux")) { cpuId = getSerialNumber("dmidecode -t processor | grep 'ID'", "ID", ":"); } else if (osName.toLowerCase().contains("windows")) { cpuId = getWindowsCpuId(); } return !StringUtils.hasText(cpuId)?"1020304050607080":cpuId; }catch (Exception e){ log.error("生成CpuId错误",e); return "1020304050607080"; } } private static String getWindowsCpuId() { try { Process process = Runtime.getRuntime().exec(getCpuIdWindows); process.getOutputStream().close(); Scanner sc = new Scanner(process.getInputStream()); String property = sc.next(); String serial = sc.next(); log.info(property + ": " + serial); return serial; } catch (IOException e) { // TODO Auto-generated catch block log.error("发生异常", e); } return null; } public static String getMac() { NetworkInterface networkInterface = getRealNetworkInterface(); try { if (networkInterface == null) { return null; } byte[] mac = networkInterface.getHardwareAddress(); return buildMac(mac); } catch (SocketException e) { log.error("发生异常{}", e); } return null; } public static String getServerId() { return buildServerId(getIpAddress()); } private static String getIpAddress() { NetworkInterface networkInterface = HardwareUtil.getRealNetworkInterface(); return networkInterface.getInterfaceAddresses().get(0).getAddress().getHostAddress(); } private static NetworkInterface getRealNetworkInterface() { try { //枚举本机所有的网络接口 Enumeration<NetworkInterface> allNetInterfaces = NetworkInterface.getNetworkInterfaces(); while (allNetInterfaces.hasMoreElements()) { NetworkInterface netInterface = allNetInterfaces.nextElement(); // 去除回环接口,子接口,未运行和接口 if (netInterface.isLoopback() || netInterface.isVirtual() || !netInterface.isUp()) { continue; } return netInterface; } } catch (SocketException e) { System.err.println("Error when getting host ip address" + e.getMessage()); } return null; } private static String buildServerId(String address) { List<String> ips = Arrays.asList(address.split("\\.")); return ips.stream().mapToInt(Integer::parseInt).boxed().map(Object::toString).reduce("", String::concat); } private static String buildMac(byte[] mac) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < mac.length; i++) { if (i != 0) { sb.append("-"); } String s = Integer.toHexString(mac[i] & 0xFF); sb.append(s.length() == 1 ? 0 + s : s); } return sb.toString().toUpperCase(); } private static String getOsName() { return System.getProperty("os.name"); } private static String getSerialNumber(String cmd, String record, String symbol) { String execResult = executeLinuxCmd(cmd); String[] infos = execResult.split("\n"); for (String info : infos) { info = info.trim(); if (info.contains(record)) { info.replace(" ", ""); String[] sn = info.split(symbol); return sn[1]; } } return null; } private static String executeLinuxCmd(String cmd) { try { log.debug("got cmd job : " + cmd); Runtime run = Runtime.getRuntime(); Process process; process = run.exec(cmd); InputStream in = process.getInputStream(); // BufferedReader bs = new BufferedReader(new InputStreamReader(in)); StringBuffer out = new StringBuffer(); byte[] b = new byte[8192]; for (int n; (n = in.read(b)) != -1; ) { out.append(new String(b, 0, n)); } in.close(); process.destroy(); return out.toString(); } catch (Exception e) { log.error("发生异常", e); } return null; } }