四、获取IP地址工具包

由于getHostAddress()方法在Linux下读取hosts文件获取的是127.0.0.1

InetAddress.getLocalHost().getHostAddress()

所以这里采用NetworkInterfaces + getInetAddresses来获取IP地址

import org.apache.commons.lang3.StringUtils;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;

/**
 * @Description 网络工具包
 * @Author lay 
 * @Date 2019/01/23 14:13
 */
public class NetUtil {
    private static volatile String ip = "";

    /**
     * 通过NetworkInterfaces + getInetAddresses 获取IP地址
     * 注意:
     * 1)本方法将获取第一个ipv4地址,如果系统存在如虚拟机等将会有多个ipv4地址可选,可能导致获取到虚拟机地址
     * 2)由于该方法要遍历逻辑网络接口,是一个重量级方法,这里采用static来确保全局只获取一次
     * 3)为防止当前JVM中多次调用并发耗费资源,这里采用类锁控制
     * @return IP地址
     * @throws BusinessException 获取系统IP失败,getNetworkInterfaces()如果发生IO异常
     */
    public static String getHostAddress() {
        // 如果已经获取到了直接返回
        if (StringUtils.isNotEmpty(ip)) {
            return ip;
        }
        synchronized (NetUtil.class) {
            if (StringUtils.isNotEmpty(ip)) {
                return ip;
            }
            // 枚举所有逻辑网络接口
            Enumeration<NetworkInterface> en;
            try {
                en = NetworkInterface.getNetworkInterfaces();
            } catch (SocketException e) {
                throw new BusinessException(ReturnStatus.SC_INTERNAL_SERVER_ERROR, "获取网络逻辑接口发生IO异常", e);
            }
            // 遍历所有接口
            a: while (en.hasMoreElements()) {
                NetworkInterface networkInterface = en.nextElement();
                // 遍历该接口的所有地址
                for (Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses(); inetAddresses.hasMoreElements(); ) {
                    InetAddress inetAddress = inetAddresses.nextElement();
                    String      address     = inetAddress.getHostAddress();
                    // 排除ip6等其它选项
                    if (!address.contains("::") && !address.contains("0:0:") && !address.contains("fe80")) {
                        // 排除127
                        if (!inetAddress.isLoopbackAddress() && inetAddress.isSiteLocalAddress()) {
                            // 赋值到静态变量
                            ip = address;
                            // 取第一个即结束
                            break a;
                        }
                    }
                }
            }
        }
        if (StringUtils.isEmpty(ip)) {
            throw new BusinessException(ReturnStatus.SC_INTERNAL_SERVER_ERROR, "未能获取本机IP,IP=" + ip);
        }
        return ip;
    }
}

这种获取方式实际上也可能存在问题,如使用了VM或者docker之类的东西,那么获取的时候会获取到多个并且无法区分是不是本机的IP,所以这里只取了第一个IP即break到a的位置。使用的时候需要注意服务器环境是否会造成这样的影响

原文地址:https://www.cnblogs.com/lay2017/p/10368983.html