将相对URL追加到java.net.URL
假设我有一个java.net.URL对象,指向将相对URL追加到java.net.URL,java,url,Java,Url,假设我有一个java.net.URL对象,指向 http://example.com/myItems或http://example.com/myItems/ 是否有某个帮助程序可以将某个相对URL附加到此文件? 例如,追加/myItemId或myItemId以获取: http://example.com/myItems/myItemIdURL有一个以URL和String规范为基础的 或者,java.net.URI更符合标准,并且有一种方法来做同样的事情。用你的URL创建一个URI。我已经到处搜索
http://example.com/myItems
或http://example.com/myItems/
是否有某个帮助程序可以将某个相对URL附加到此文件?
例如,追加/myItemId
或myItemId
以获取:
http://example.com/myItems/myItemId
URL
有一个以URL
和String
规范为基础的
或者,
java.net.URI
更符合标准,并且有一种方法来做同样的事情。用你的URL
创建一个URI
。我已经到处搜索了这个问题的答案。我能找到的唯一实现是Android SDK:。我提取它是为了我自己的目的
private String appendSegmentToPath(String path, String segment) {
if (path == null || path.isEmpty()) {
return "/" + segment;
}
if (path.charAt(path.length() - 1) == '/') {
return path + segment;
}
return path + "/" + segment;
}
就是我找到源头的地方
结合,我使用它的方式如下:
builder.setPath(appendSegmentToPath(builder.getPath(),segment))代码>使用Apache URIBuilder的一些示例:
例1:
结果1->
例2:
结果2->基于twhitbeck答案的我的解决方案:
import java.net.URI;
import java.net.URISyntaxException;
public class URIBuilder extends org.apache.http.client.utils.URIBuilder {
public URIBuilder() {
}
public URIBuilder(String string) throws URISyntaxException {
super(string);
}
public URIBuilder(URI uri) {
super(uri);
}
public org.apache.http.client.utils.URIBuilder addPath(String subPath) {
if (subPath == null || subPath.isEmpty() || "/".equals(subPath)) {
return this;
}
return setPath(appendSegmentToPath(getPath(), subPath));
}
private String appendSegmentToPath(String path, String segment) {
if (path == null || path.isEmpty()) {
path = "/";
}
if (path.charAt(path.length() - 1) == '/' || segment.startsWith("/")) {
return path + segment;
}
return path + "/" + segment;
}
}
测试:
要点:此操作不需要任何额外的lib或代码,并提供所需的结果:
//import java.net.URL;
URL url1 = new URL("http://petstore.swagger.wordnik.com/api/api-docs?foo=1&bar=baz");
URL url2 = new URL(url1.getProtocol(), url1.getHost(), url1.getPort(), url1.getPath() + "/pet" + "?" + url1.getQuery(), null);
System.out.println(url1);
System.out.println(url2);
这张照片是:
http://petstore.swagger.wordnik.com/api/api-docs?foo=1&bar=baz
http://petstore.swagger.wordnik.com/api/api-docs/pet?foo=1&bar=baz
只有在主机后面没有路径时,接受的答案才有效(我知道接受的答案是错误的)我编写了一个帮助函数来添加到url路径:
public static URL concatenate(URL baseUrl, String extraPath) throws URISyntaxException,
MalformedURLException {
URI uri = baseUrl.toURI();
String newPath = uri.getPath() + '/' + extraPath;
URI newUri = uri.resolve(newPath);
return newUri.toURL();
}
已更新
我相信这是最短的解决方案:
URL url1 = new URL("http://domain.com/contextpath");
String relativePath = "/additional/relative/path";
URL concatenatedUrl = new URL(url1.toExternalForm() + relativePath);
您可以使用和方法URI#normalize
,以避免URI中重复的/
:
URIBuilder uriBuilder = new URIBuilder("http://example.com/test");
URI uri = uriBuilder.setPath(uriBuilder.getPath() + "/path/to/add")
.build()
.normalize();
// expected : http://example.com/test/path/to/add
对于android,请确保使用来自android.net.Uri的.appendPath()
将相对路径连接到Uri:
java.net.URI uri = URI.create("https://stackoverflow.com/questions")
java.net.URI res = uri.resolve(uri.getPath + "/some/path")
res
将包含https://stackoverflow.com/questions/some/path
您只需使用URI
类即可:
import java.net.URI;
import org.apache.http.client.utils.URIBuilder;
URI uri = URI.create("http://example.com/basepath/");
URI uri2 = uri.resolve("./relative");
// => http://example.com/basepath/relative
请注意基本路径上的尾随斜杠和所附加段的基本相对格式。您还可以使用Apache HTTP客户端的URIBuilder
类:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
我对URI的编码有一些困难。追加对我来说不起作用,因为它是content://类型,并且不喜欢“/”。此解决方案假设没有查询,也没有片段(毕竟我们正在处理路径): 科特林代码:
val newUri = Uri.parse(myUri.toString() + Uri.encode("/$relPath"))
在Android上你可以使用。下面允许从现有URL创建Uri.Builder
,作为String
,然后追加:
Uri.parse(baseUrl) // Create Uri from String
.buildUpon() // Creates a "Builder"
.appendEncodedPath("path/to/add")
.appendQueryParameter("at_ref", "123") // To add ?at_ref=123
.fragment("anker") // To add #anker
.build()
请注意,appendEncodedPath
不需要前导的/
,只包含检查“baseUrl”是否以一结尾,否则在路径之前添加一个
根据文档,这支持
- 遵循模式的绝对层次URI引用
://?#
- 带模式的相对URI
?#
/?#
- 带模式的不透明URI
:#
可能的重复似乎没有简单的解决方案。URL或URI类都不支持此操作。Apache HttpClient也不支持此功能。
newURL(“/additional/relative/path”)代码>抛出MalformedURLException“URL具有接受基本URL和字符串规范的构造函数”-没有帮助。URL url1=newurl(“);URL url2=newurl(url1,“/pet”);System.out.println(url2.toString())为您提供了:,这不是为了其他人的利益:第一个URL构造函数方法的工作方式与我预期的不完全一样(rtfm,呃?)。仅使用baseURL的非路径部分。@user2585038:第二个参数不能以斜杠开头。斜杠表示“绝对”“链接,因此url1的路径被丢弃。URI解析实际上只在这里错误地起作用。请参阅belowAs@user2585038中@Christoph Henkelmann的回答。该回答没有考虑第5.2(6a)节,该节规定:“除了基本URI路径组件的最后一段之外,所有其他段都复制到缓冲区。换句话说,最后(最右边)斜杠字符(如果有)之后的任何字符都被排除在外。”这个IMO使得URI解析在大多数情况下都不可用,包括OP的情况。MalformedUrlException
为什么他们不抛出未经检查的异常:'(是的,这很糟糕……而且不一致:解析数字会引发未经检查的异常^^^此解决方案不处理尾部斜杠。问题提供了两个示例。url1.getFile().endsWith(“/”)?url1.getFile()+“pet”:url1.getFile()+“/pet”
?@Martinsene发现得很好,我对示例进行了调整。使用jersey客户端的UriBuilder/IfbaseUrl
以/
结尾或外部路径
以/
开头,您将在最终URL中重复/
。您应该添加.normalize()
在最后一次toul()之前
。这不适用于以开头的本地文件URLfile://If 运行此代码后,我想您会发现结果是:更正了使用uri.getPath
的代码,谢谢!第一位代码的结果不是http://example.com/basepath/relative
,但http://example.com/relative
,未经修订单独地使这个答案的第一部分不正确。事实上,答案的第一部分是正确的;如果在第一个URI中有多个/,那么如果没有提供./也会起作用~~~
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
import java.net.URI;
import org.apache.http.client.utils.URIBuilder;
URI uri = URI.create("http://example.com/basepath");
URI uri2 = appendPath(uri, "relative");
// => http://example.com/basepath/relative
public URI appendPath(URI uri, String path) {
URIBuilder builder = new URIBuilder(uri);
builder.setPath(URI.create(builder.getPath() + "/").resolve("./" + path).getPath());
return builder.build();
}
val newUri = Uri.parse(myUri.toString() + Uri.encode("/$relPath"))
Uri.parse(baseUrl) // Create Uri from String
.buildUpon() // Creates a "Builder"
.appendEncodedPath("path/to/add")
.appendQueryParameter("at_ref", "123") // To add ?at_ref=123
.fragment("anker") // To add #anker
.build()
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
class URLHelper {
public static URL appendRelativePathToURL(URL base, String relPath) {
/*
foo://example.com:8042/over/there?name=ferret#nose
\_/ \______________/\_________/ \_________/ \__/
| | | | |
scheme authority path query fragment
| _____________________|__
/ \ / \
urn:example:animal:ferret:nose
see https://en.wikipedia.org/wiki/Uniform_Resource_Identifier
*/
try {
URI baseUri = base.toURI();
// cut initial slash of relative path
String relPathToAdd = relPath.startsWith("/") ? relPath.substring(1) : relPath;
// cut trailing slash of present path
String path = baseUri.getPath();
String pathWithoutTrailingSlash = path.endsWith("/") ? path.substring(0, path.length() - 1) : path;
return new URI(baseUri.getScheme(),
baseUri.getAuthority(),
pathWithoutTrailingSlash + "/" + relPathToAdd,
baseUri.getQuery(),
baseUri.getFragment()).toURL();
} catch (URISyntaxException e) {
throw new MalformedURLRuntimeException("Error parsing URI.", e);
} catch (MalformedURLException e) {
throw new MalformedURLRuntimeException("Malformed URL.", e);
}
}
public static class MalformedURLRuntimeException extends RuntimeException {
public MalformedURLRuntimeException(String msg, Throwable cause) {
super("Malformed URL: " + msg, cause);
}
}
}
private void demo() {
try {
URL coolURL = new URL("http://fun.de/path/a/b/c?query&another=3#asdf");
URL notSoCoolURL = new URL("http://fun.de/path/a/b/c/?query&another=3#asdf");
System.out.println(URLHelper.appendRelativePathToURL(coolURL, "d"));
System.out.println(URLHelper.appendRelativePathToURL(coolURL, "/d"));
System.out.println(URLHelper.appendRelativePathToURL(notSoCoolURL, "d"));
System.out.println(URLHelper.appendRelativePathToURL(notSoCoolURL, "/d"));
} catch (MalformedURLException e) {
e.printStackTrace();
}
}