Java启动服务器时获取带端口主机名(解决HttpServletRequest空指针问题)
Got it, let's work through this problem together—since HttpServletRequest is tied to incoming client requests, it doesn't exist during server startup (that's exactly why you ran into the NullPointerException). Here are several reliable ways to get your server's address in the format you need (localhost:8080 or IP:port) without relying on request objects:
1. Spring Boot: Use Built-in Environment or Server Properties
If you're using Spring Boot, this is the simplest approach. You can access the configured port via the Environment or ServerProperties bean, and pair it with the local hostname/IP:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.stereotype.Component; import java.net.InetAddress; import java.net.UnknownHostException; @Component public class ServerAddressProvider { private final Environment environment; @Autowired public ServerAddressProvider(Environment environment) { this.environment = environment; } public String getServerAddress() throws UnknownHostException { // Get hostname (or use getHostAddress() for IP) String hostname = InetAddress.getLocalHost().getHostName(); // Fallback to 8080 if server.port isn't configured String port = environment.getProperty("server.port", "8080"); return hostname + ":" + port; } }
You can call this method in a @PostConstruct annotated method or any early startup logic—Spring makes Environment available as soon as the context initializes.
2. Non-Framework Apps: InetAddress + System Properties
For vanilla Java apps or servers that don't use Spring, you can fetch the local hostname/IP via InetAddress and read the port from system properties (most servers let you pass the port as a system property on startup):
import java.net.InetAddress; import java.net.UnknownHostException; public class StartupServerInfo { public static void main(String[] args) throws UnknownHostException { // Choose between hostname or IP address InetAddress localHost = InetAddress.getLocalHost(); String hostIdentifier = localHost.getHostName(); // e.g., localhost // Or use localHost.getHostAddress() for the IP (e.g., 127.0.0.1) // Read port from system property (set via -Dserver.port=8080 on startup) String port = System.getProperty("server.port", "8080"); String serverAddress = hostIdentifier + ":" + port; System.out.println("Server address at startup: " + serverAddress); } }
Pro tip: If you're using Tomcat, you can add -Dserver.port=8080 to your catalina.sh or catalina.bat startup script to make the port available as a system property.
3. Server-Specific APIs (Tomcat Example)
If you're working directly with a server like Tomcat, you can use its internal APIs to fetch connector details programmatically:
Programmatic Tomcat Startup
If you're starting Tomcat via code:
import org.apache.catalina.connector.Connector; import org.apache.catalina.startup.Tomcat; public class TomcatStartupInfo { public static void main(String[] args) throws Exception { Tomcat tomcat = new Tomcat(); // Configure your Tomcat instance (context, webapp, etc.) tomcat.start(); // Get the main HTTP connector Connector connector = tomcat.getConnector(); String host = connector.getHost().getName(); int port = connector.getLocalPort(); String serverAddress = host + ":" + port; System.out.println("Tomcat server address: " + serverAddress); } }
Deployed Tomcat Apps (Using MBeans)
For apps deployed to an existing Tomcat server, use JMX MBeans to access connector attributes:
import javax.management.MBeanServer; import javax.management.ObjectName; import java.lang.management.ManagementFactory; import java.net.InetAddress; public class TomcatMBeanServerInfo { public static void main(String[] args) throws Exception { MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer(); // Replace port=8080 with your actual connector port ObjectName connectorName = new ObjectName("Catalina:type=Connector,port=8080"); String host = (String) mBeanServer.getAttribute(connectorName, "address"); int port = (Integer) mBeanServer.getAttribute(connectorName, "port"); // If host is 0.0.0.0 (listening on all interfaces), replace with localhost/actual IP if ("0.0.0.0".equals(host)) { host = InetAddress.getLocalHost().getHostName(); } String serverAddress = host + ":" + port; System.out.println("Tomcat server address: " + serverAddress); } }
Bonus: Handle Edge Cases (e.g., Docker/Network Interfaces)
Sometimes InetAddress.getLocalHost() returns an internal IP (like in Docker containers). To get a public/accessible IP, iterate over network interfaces:
import java.net.NetworkInterface; import java.util.Enumeration; import java.net.InetAddress; public class NetworkInterfaceHelper { public static String getAccessibleHostAddress() throws Exception { Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); while (interfaces.hasMoreElements()) { NetworkInterface iface = interfaces.nextElement(); // Skip loopback, virtual, or inactive interfaces if (iface.isLoopback() || iface.isVirtual() || !iface.isUp()) { continue; } Enumeration<InetAddress> addresses = iface.getInetAddresses(); while (addresses.hasMoreElements()) { InetAddress addr = addresses.nextElement(); // Skip loopback and IPv6 if not needed if (!addr.isLoopbackAddress() && addr.isSiteLocalAddress()) { return addr.getHostAddress(); } } } // Fallback to localhost if no accessible IP found return InetAddress.getLocalHost().getHostAddress(); } }
内容的提问来源于stack exchange,提问作者Hariharan

