如何在Java中准确比较URI对象的端口(处理默认端口场景)
解决URI端口校验时默认端口不匹配的问题
这个问题我之前也碰到过,根源在于Java的URI类对未指定端口的处理逻辑——当URI里没显式写端口时,getPort()会返回-1,而不会自动填充对应协议的默认端口,这就导致你例子里http://example.com的端口被判定为-1,和显式写了80的http://example.com:80比较时自然不相等。
要解决这个问题,核心思路是获取每个URI的「有效端口」:如果getPort()返回-1,就根据URI的协议(scheme)获取对应的默认端口,否则直接用getPort()返回的数值。下面给你两种可行的实现方式:
方式一:手动维护默认端口映射
这种方式更灵活,你可以根据自己的业务需求添加需要支持的协议:
// 工具方法:获取URI的有效端口 private static int getEffectivePort(URI uri) { int port = uri.getPort(); if (port == -1) { // 根据协议返回对应默认端口 switch (uri.getScheme().toLowerCase()) { case "http": return 80; case "https": return 443; case "ftp": return 21; case "ssh": return 22; // 可以继续添加其他需要支持的协议 default: throw new IllegalArgumentException("Unsupported scheme: " + uri.getScheme()); } } return port; } // 修改后的校验逻辑 public static void main(String[] args) throws URISyntaxException { URI firstURI = new URI("http://example.com:80"); URI secondURI = new URI("http://example.com/testing"); int firstEffectivePort = getEffectivePort(firstURI); int secondEffectivePort = getEffectivePort(secondURI); if (!firstURI.getHost().equals(secondURI.getHost()) || !firstURI.getScheme().equalsIgnoreCase(secondURI.getScheme()) || firstEffectivePort != secondEffectivePort) { // 错误处理逻辑 System.out.println("校验失败"); } else { // 校验通过 System.out.println("校验通过"); } }
方式二:利用URL类的默认端口处理
Java的URL类内置了常见协议的默认端口映射,你可以把URI转成URL来获取默认端口,省去手动维护的麻烦:
// 工具方法:借助URL获取有效端口 private static int getEffectivePort(URI uri) throws MalformedURLException { URL url = uri.toURL(); // 如果URL的默认端口存在(不是-1)就用默认端口,否则用显式指定的端口 return url.getDefaultPort() != -1 ? url.getDefaultPort() : url.getPort(); } // 校验逻辑和方式一类似,注意处理MalformedURLException异常 public static void main(String[] args) throws URISyntaxException, MalformedURLException { URI firstURI = new URI("http://example.com:80"); URI secondURI = new URI("http://example.com/testing"); int firstEffectivePort = getEffectivePort(firstURI); int secondEffectivePort = getEffectivePort(secondURI); if (!firstURI.getHost().equals(secondURI.getHost()) || !firstURI.getScheme().equalsIgnoreCase(secondURI.getScheme()) || firstEffectivePort != secondEffectivePort) { // 错误处理 System.out.println("校验失败"); } else { System.out.println("校验通过"); } }
两种方式都能解决你的问题,第一种适合需要自定义协议端口的场景,第二种适合只用到常见协议、不想手动维护映射的场景。
内容的提问来源于stack exchange,提问作者user6800688
相关产品推荐
相关产品推荐

