SpringBoot部署Azure Linux应用服务,H2-Console 1.4.200+版本报UnknownHostException
问题分析与解决方案
问题现象
部署在Azure Linux应用服务的SpringBoot应用中,访问H2-console时触发如下错误,浏览器返回500状态码:
java.net.UnknownHostException: 189.216.xxx.xxx:58157: invalid IPv6 address at java.base/java.net.InetAddress.getAllByName(InetAddress.java:1344) at java.base/java.net.InetAddress.getAllByName(InetAddress.java:1301) at java.base/java.net.InetAddress.getByName(InetAddress.java:1251) at org.h2.util.NetworkConnectionInfo.<init>(NetworkConnectionInfo.java:37) at org.h2.server.web.WebServlet.doGet(WebServlet.java:129) at javax.servlet.http.HttpServlet.service(HttpServlet.java:655) at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
该问题仅在H2数据库1.4.200及更高版本出现,使用1.4.199及以下版本时无异常;本地部署(如http://localhost/api/v1/h2-console/)无论哪个H2版本都能正常访问。
根因
H2 1.4.200版本开始,NetworkConnectionInfo类在解析客户端地址时,错误地将IP:端口格式的字符串当作纯IP地址传入InetAddress.getByName()方法。Azure Linux应用服务传递的客户端地址包含端口号,而该方法无法解析带端口的IP字符串,最终抛出UnknownHostException。本地环境中客户端地址通常不带端口,因此不会触发该问题。
解决方案
方案1:降级H2版本(临时快速解决)
将H2依赖版本回退到1.4.199或更低,直接规避该解析逻辑问题:
- Maven(pom.xml):
<dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>1.4.199</version> <scope>runtime</scope> </dependency>
- Gradle(build.gradle):
runtimeOnly 'com.h2database:h2:1.4.199'
方案2:自定义H2 WebServlet(适配高版本H2)
通过自定义Servlet替换H2默认的WebServlet,剥离客户端地址中的端口号后再解析:
- 创建自定义Servlet类:
import org.h2.server.web.WebServlet; import javax.servlet.http.HttpServletRequest; import java.net.InetAddress; import java.net.UnknownHostException; public class CustomH2WebServlet extends WebServlet { @Override protected void doGet(HttpServletRequest req) { String remoteAddr = req.getRemoteAddr(); // 处理IPv4带端口的情况,剥离端口号 if (remoteAddr.contains(":") && remoteAddr.chars().filter(ch -> ch == ':').count() == 1) { remoteAddr = remoteAddr.split(":")[0]; } try { InetAddress.getByName(remoteAddr); super.doGet(req); } catch (UnknownHostException e) { // 解析失败时强制使用localhost绕过错误 req.setAttribute("javax.servlet.remote_addr", "localhost"); super.doGet(req); } } }
- 注册自定义Servlet替换默认H2控制台Servlet:
import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class H2ConsoleConfig { @Bean public ServletRegistrationBean<CustomH2WebServlet> h2ConsoleServletRegistration() { ServletRegistrationBean<CustomH2WebServlet> registrationBean = new ServletRegistrationBean<>(new CustomH2WebServlet(), "/h2-console/*"); registrationBean.setName("H2Console"); return registrationBean; } }
方案3:配置Azure反向代理头(推荐)
Azure Linux应用服务的反向代理会传递X-Forwarded-For头,配置SpringBoot优先使用该头获取真实客户端IP,避免直接获取带端口的地址:
在application.properties中添加:
server.forward-headers-strategy=NATIVE server.use-forward-headers=true
内容的提问来源于stack exchange,提问作者Ernesto Pedraza
相关产品推荐
相关产品推荐

