Java URL 类 getPath()、getQuery() 和 getFile() 与 RFC3986 URI 语法不一致

Posted

技术标签:

【中文标题】Java URL 类 getPath()、getQuery() 和 getFile() 与 RFC3986 URI 语法不一致【英文标题】:Java URL Class getPath(), getQuery() and getFile() inconsistent with RFC3986 URI Syntax 【发布时间】:2015-07-12 06:27:42 【问题描述】:

我正在编写一个半包装 Java 的 URL class 的实用程序类,并且我编写了一堆测试用例来验证我使用自定义实现包装的方法。对于某些URL 字符串,我不理解某些Java 的getter 的输出。

根据 RFC 3986 规范,路径组件定义如下:

The path is terminated by the first question mark ("?") or number sign   
("#") character, or by the end of the URI.

查询组件定义如下:

The query component is indicated by the first question
mark ("?") character and terminated by a number sign ("#") character
or by the end of the URI.

我有几个测试用例被 Java 视为有效 URL,但路径、文件和查询的 getter 没有返回我预期的值:

URL url = new URL("https://www.somesite.com/?param1=val1");

System.out.print(url.getPath());
System.out.println(url.getFile());
System.out.println(url.getQuery());

以上结果如下:

//?param1=val1
param1=val1
<empty string>

我的另一个测试用例:

URL url = new URL("https://www.somesite.com?param1=val1");

System.out.print(url.getPath());
System.out.println(url.getFile());
System.out.println(url.getQuery());

以上结果如下:

?param1=val1
param1=val1
<empty string>

根据Java URL的文档:

public String getFile()

Gets the file name of this URL. The returned file portion will be the  
same as getPath(), plus the concatenation of the value of getQuery(), if 
any. If there is no query portion, this method and getPath() will return 
identical results.

Returns:
    the file name of this URL, or an empty string if one does not exist

所以,当调用 getQuery() 时,我的测试用例会导致空字符串。在这种情况下,我希望getFile() 返回与getPath() 相同的值。事实并非如此。

我预计两个测试用例的输出如下:

<empty string>
?param1=val1
param1=val1

也许我对 RFC 3986 的解释不正确。但是我看到的输出也不符合 URL 类的文档?谁能解释我所看到的?

【问题讨论】:

【参考方案1】:

这里有一些基于你的片段的可执行代码:

import java.net.MalformedURLException;
import java.net.URL;

public class URLExample 
  public static void main(String[] args) throws MalformedURLException 
    printURLInformation(new URL("https://www.somesite.com/?param1=val1"));
    printURLInformation(new URL("https://www.somesite.com?param1=val1"));
  

  private static void printURLInformation(URL url) 
    System.out.println(url);
    System.out.println("Path:\t" + url.getPath());
    System.out.println("File:\t" + url.getFile());
    System.out.println("Query:\t" + url.getQuery() + "\n");
  


工作正常,这是您可能预期的结果。唯一的区别是,您使用了一个System.out.print,然后是System.out.println,将路径和文件的结果打印在同一行中。

https://www.somesite.com/?param1=val1
Path:   /
File:   /?param1=val1
Query:  param1=val1

https://www.somesite.com?param1=val1
Path:   
File:   ?param1=val1
Query:  param1=val1

【讨论】:

以上是关于Java URL 类 getPath()、getQuery() 和 getFile() 与 RFC3986 URI 语法不一致的主要内容,如果未能解决你的问题,请参考以下文章

JAVA关于java中 类.class.getResource("/").getPath()获取路径有空格的问题

URL的getFile()和getPath()方法的区别(转)

Java 中的 getPath()、getAbsolutePath() 和 getCanonicalPath() 有啥区别?

java 项目如何获取项目所在的物理根路径

java中File类的getPath(),getAbsolutePath(),getCanonicalPath()区别

Java秒杀系统--4.实现秒杀接口