场景
项目每天5点需要执行一次定时任务,因为不频繁,根本不需要用redis锁。
解决方案
这里用spring的Condition,指定某个ip下的机器执行即可。
Condition的原理,实现这个接口,重写matches方法,返回true则匹配成功,返回false则匹配失败。
先写个工具类:
public class TaskCondition implements Condition {
private static Logger logger = LoggerFactory.getLogger(TaskCondition.class);
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
List<String> ipList = getLocalHostAndPortIps();
logger.info("ipList={}",String.join(",",ipList));
String ip = context.getEnvironment().getProperty("task.ip");
logger.info("ip={}",ip);
if(ipList.contains(ip)){
return true;
}
return false;
}
/*
* 获取本机ip+端口,可能有多个
*/
public static List<String> getLocalHostAndPortIps() {
String result = "";
List<String> rtnList = new ArrayList<String>();
Enumeration netInterfaces;
try {
netInterfaces = NetworkInterface.getNetworkInterfaces();
while (netInterfaces.hasMoreElements()) {
NetworkInterface ni = (NetworkInterface) netInterfaces.nextElement();
Enumeration niips = ni.getInetAddresses();
while (niips.hasMoreElements()) {
InetAddress ip = (InetAddress) niips.nextElement();
if (ip.isSiteLocalAddress() || ip.isLoopbackAddress()) {
rtnList.add(ip.getHostAddress());
}
}
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
return rtnList;
}
}
然后在定时任务类里加上这个注解:
@Component
@Configuration
@Conditional({TaskCondition.class})
public class AutoSyncTask {
}
当然,配置文件中要指定下ip:
task.ip=10.192.168.10
注: 以上task.ip只适用于单ip,如果有多个ip会解析不到。很明显代码中的ipList是本机的ipList。 如果传入多个ip,那么contains的时候很明显匹配不上,就失去效果了。