不能分析解码后的URLURL的语法只在它被解码前是有意义的,一旦解码就可能出现保留字。 例如"http://example.com/blue%2Fred%3Fand+green" 在解码前由如下部分组成:
这样看来, 我们是在请求一个名为"blue/red?and+green"的文件,而不是一个位于"blue"文件夹下的名为"red?and+green"的文件。 如果我们把它解码为"http://example.com/blue/red?and+green",我们将得到如下部分:
这明显是错误的,所以,对保留字和URL各部分的分析必须在URL解码之前完成。这意味着URL重写过滤器不应当 在尝试匹配之前解码URL,当且仅当保留字允许进行URL编码时才可以(有时符合这种情形,有时不符合,这取决 于你的应用)。 解码后的URL不能被再编码为同样的形式如果你解码"http://example.com/blue%2Fred%3Fand+green" 为"http://example.com/blue/red?and +green",然后对它进行编码(哪怕使用一个对URL每一部分都很了解的编码器),你将会得到"http://example.com/blue/red?and+green",这是因为它已经是一个有效的URL。它跟我们解码之前的 URL非常的不同。 用Java正确处理URL当你觉得自己已经拿到了URL的黑腰带(柔道中的最高级别--译者注),你将会发现仍有一些Java里特有的、URL 相关的陷阱。如果没有一个强大的心脏,你很难正确的处理URL。 不要用java.net.URLEncoder或者java.net.URLDecoder来处理整个URL不开玩笑。这些类不是用来编码或解码URL的,API文档中清楚的写着:
这不是给URL用的。充其量它类似于查询 部分的编码方式。使用它来编码或解码整个URL是错误的。你肯定以 为标准的JDK一定会有一个标准的类来正确的处理URL编码(是这样,只不过是各部分分开处理的),但是要么是 压根没有,要么是我们还没有发现。不过,这种臆测导致许多人错用了URLEncoder。 在对每一部分编码之前不要拼装URL正如我们已经讲过的:完整构建后的URL不能再被编码。 以下面的代码为例:
如果"a/b?c" 是一个路径片段,那么不可能把"http://example.com/a/b?c" 转换回之前它的原样,因为它碰 巧是一个有效的URL。之前我们已经解释过这一点。 下面是正确的代码:
这里我们使用了一个工具类URLUtils,它是我们自己开发的,因为网络上找不到一个详尽的足够快的工具类。 上面的代码会带给你正确编码的URL "http://example.com/a%2Fb%3Fc"。 注意,同样的方式也适用于查询子串:
这会给你"http://example.com/?query=a&b==c",这是个有效的URL,而不是我们想得到的 "http://example.com/?query=a%26b==c"。 不要期望 URI.getPath() 给你结构化的数据因为一旦一个URL被解码,句法信息就会丢失,下面这样的代码就是错误的:
它会先将路径 "a%2Fb%3Fc"解码为 "a/b?c",然后在不应该分割的地方将地址分割为地址片段。 正确的代码使用的是 未解码的路径 :
注意路径参数仍然存在:如果需要的话再处理它们。 不要期望 Apache Commons HTTPClient的URI类能够正确的做对Apache Commons HTTPClient 3的 URI 类使用了Apache Commons Codec的URLCodec来做 URL 编码, 正如 API文档提到的 它是有问题的,因为它犯了和使用java.net.URLEncoder同样的错误。它不但 使用了错误的编码器,还错误的 按照每一部分都具有同样的预定设置进行解码。 在web应用的每一层修复URL编码问题近来我们已经被动修复了许多应用中的URL编码问题。从在Java中支持它,到低层次的URL重写。这里我们 会列出一些必要的修改。 总是在创建的时候进行URL编码在我们的 HTML文件中,我们将所有出现:
的地方替换为:
查询参数也是类似的。 |