Java 有没有正确的方法来构建 URL?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19538431/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a right way to build a URL?
提问by OldCurmudgeon
In much of the code I work with there is horrible stuff like:
在我使用的大部分代码中,都有一些可怕的东西,例如:
String url = "../Somewhere/SomeServlet?method=AMethod&id="+object.getSomething()+ "&aParam="+object.getSomethingElse());
or - even worse:
或者 - 更糟糕的是:
String url = "Somewhere/Here/Something.jsp?path="+aFile.toString().replace("\","/")+ "&aParam="+object.getSomethingElse());
Is there a right way to:
有没有正确的方法:
- Create a new URL (or is it a URI).
- Add correctly escaped parameters to it.
- Add well-formed file paths in those params.
- Resolve it to a String.
- 创建一个新的 URL(或者它是一个 URI)。
- 向其添加正确转义的参数。
- 在这些参数中添加格式正确的文件路径。
- 将其解析为字符串。
Essentially - it is too easy to just build the string than it is to do it properly. Is there a way to do it properlythat is as easy as just building the string?
本质上 - 构建字符串比正确地构建字符串太容易了。有没有一种方法可以像构建字符串一样简单地正确执行此操作?
Added
添加
For clarity - and after a little thought - I suppose I am looking for something like:
为了清楚起见 - 经过一番思考 - 我想我正在寻找类似的东西:
String s = new MyThing()
.setPlace("Somewhere/Something.jsp")
.addParameter(aName,aValue)
.addParameter(aName,aFile)
.toString();
so that it will deal with all of the unpleasantness of escaping and adding "?"/"&" and changing "\" to "/" instead of using "\" for files etc.
这样它将处理转义和添加“?”/“&”并将“\”更改为“/”而不是对文件等使用“\”的所有不愉快。
If I have to write one myself (i.e. if Apache is not an option) are there real Java techniques for correctly escaping the various parts. I mean things like escaping " " in parameters as "." while escaping " " in other places a "%20".
如果我必须自己编写一个(即如果 Apache 不是一个选项),是否有真正的 Java 技术可以正确转义各个部分。我的意思是将参数中的“”转义为“。” 在其他地方转义“ ”时为“%20”。
采纳答案by Jeroen Vannevel
I have written this up, you can change it where you want extra functionality. It doesn't use any external resources, let me know if I have looked over something!
我已经写好了,您可以在需要额外功能的地方更改它。它不使用任何外部资源,如果我查看过某些内容,请告诉我!
It's basically a wrapper for the URI
class that allows you to more easily add subdirectories and parameters to the URI. You can set default values if you're not interested in some things.
它基本上是URI
类的包装器,允许您更轻松地将子目录和参数添加到 URI。如果您对某些事情不感兴趣,可以设置默认值。
Edit: I have added an option to use a relative URI (per your question).
编辑:我添加了一个使用相对 URI 的选项(根据您的问题)。
public class Test {
public static void main(String[] args) throws URISyntaxException,
MalformedURLException {
URLBuilder urlb = new URLBuilder("www.example.com");
urlb.setConnectionType("http");
urlb.addSubfolder("somesub");
urlb.addSubfolder("anothersub");
urlb.addParameter("param lol", "unknown");
urlb.addParameter("paramY", "known");
String url = urlb.getURL();
System.out.println(url);
urlb = new URLBuilder();
urlb.addSubfolder("servlet");
urlb.addSubfolder("jsp");
urlb.addSubfolder("somesub");
urlb.addSubfolder("anothersub");
urlb.addParameter("param lol", "unknown");
urlb.addParameter("paramY", "known");
String relUrl = urlb.getRelativeURL();
System.out.println(relUrl);
}
}
class URLBuilder {
private StringBuilder folders, params;
private String connType, host;
void setConnectionType(String conn) {
connType = conn;
}
URLBuilder(){
folders = new StringBuilder();
params = new StringBuilder();
}
URLBuilder(String host) {
this();
this.host = host;
}
void addSubfolder(String folder) {
folders.append("/");
folders.append(folder);
}
void addParameter(String parameter, String value) {
if(params.toString().length() > 0){params.append("&");}
params.append(parameter);
params.append("=");
params.append(value);
}
String getURL() throws URISyntaxException, MalformedURLException {
URI uri = new URI(connType, host, folders.toString(),
params.toString(), null);
return uri.toURL().toString();
}
String getRelativeURL() throws URISyntaxException, MalformedURLException{
URI uri = new URI(null, null, folders.toString(), params.toString(), null);
return uri.toString();
}
}
Output:
输出:
Absolute
绝对
http://www.example.com/somesub/anothersub?param%20lol=unknown¶mY=known
http://www.example.com/somesub/anothersub?param%20lol=unknown¶mY=known
Relative
相对的
/servlet/jsp/somesub/anothersub?param%20lol=unknown¶mY=known
/servlet/jsp/somesub/anothersub?param%20lol=unknown¶mY=known
回答by RamonBoza
Recomendations
建议
private final String BASE_URL = Properties.getProperty("base-url");
private Map propertiesMap; // = new HashMap<String,String>();
and in the code to build the URL.
并在代码中构建 URL。
public String buildURL(){
StringBuilder builder = new StringBuilder();
builder.append(BASE_URL);
//for each property, append it
return builder.toString();
}
回答by Barun
You can use Apache URIBuilder
您可以使用Apache URIBuilder
Sample code: Full Apache Example
示例代码:完整的 Apache 示例
URIBuilder builder = new URIBuilder()
.setScheme("http")
.setHost("apache.org")
.setPath("/shindig")
.addParameter("hello world", "foo&bar")
.setFragment("foo");
builder.toString();
回答by OldCurmudgeon
I like @Jeroen's suggestion but it didn't quite do all I wanted so, using his idea of gathering the parts together and then using a URI
to grow the final result I put together this solution which seems to do what I want:
我喜欢@Jeroen 的建议,但它并没有完全满足我的要求,因此,利用他将各个部分聚集在一起然后使用 aURI
来增加最终结果的想法,我将这个解决方案放在一起,这似乎满足了我的要求:
public class URLBuilder {
// The scheme - http
private String scheme = null;
// The user - user
private String user = null;
// The host - example.com
private String host = null;
// The port - 8080
private int port = -1;
// The paths - /Path/To/Somewhere/index.jsp
private final ArrayList<String> paths = new ArrayList<String>();
// The parameters - ?a=b&c=d
private final ArrayList<Pair<String, String>> queries = new ArrayList<Pair<String, String>>();
// The fragment - #n
private String fragment = null;
public URLBuilder addQuery(String name, String value) {
queries.add(new Pair(name, value));
return this;
}
public URLBuilder addQuery(String name, long value) {
addQuery(name, String.valueOf(value));
return this;
}
public URLBuilder addQuery(String name, File file) {
addQuery(name, file.toURI().getPath());
return this;
}
public URLBuilder addPath(String path) {
paths.add(path);
return this;
}
@Override
public String toString() {
// Build the path.
StringBuilder path = new StringBuilder();
for (String p : paths) {
path.append("/").append(p);
}
// Build the query.
StringBuilder query = new StringBuilder();
String sep = "";
for (Pair<String, String> p : queries) {
query.append(sep).append(p.p).append("=").append(p.q);
sep = "&";
}
String url = null;
try {
URI uri = new URI(
scheme,
user,
host,
port,
path.length() > 0 ? path.toString() : null,
query.length() > 0 ? query.toString() : null,
fragment);
url = uri.toString();
} catch (URISyntaxException ex) {
Logger.getLogger(URLBuilder.class.getName()).log(Level.SEVERE, null, ex);
}
return url;
}
/**
* @param host the host to set
* @return this
*/
public URLBuilder setHost(String host) {
this.host = host;
return this;
}
/**
* @param scheme the scheme to set
* @return this
*/
public URLBuilder setScheme(String scheme) {
this.scheme = scheme;
return this;
}
/**
* @param user the user to set
* @return this
*/
public URLBuilder setUser(String user) {
this.user = user;
return this;
}
/**
* @param port the port to set
* @return this
*/
public URLBuilder setPort(int port) {
this.port = port;
return this;
}
/**
* @param fragment the fragment to set
* @return this
*/
public URLBuilder setFragment(String fragment) {
this.fragment = fragment;
return this;
}
public static void main(String args[]) {
try {
URLBuilder url = new URLBuilder();
System.out.println(url.toString());
url.setFragment("fragment");
System.out.println(url.toString());
url.setHost("host.com");
System.out.println(url.toString());
url.addPath("APath");
System.out.println(url.toString());
url.addPath("AnotherPath");
System.out.println(url.toString());
url.addQuery("query1", "param1");
System.out.println(url.toString());
url.addQuery("query 2", "param 2");
System.out.println(url.toString());
url.addQuery("file", new File("Hello World.txt"));
System.out.println(url.toString());
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
}
回答by Marcin Szymczak
You can also use spring UriComponentsBuilder
您还可以使用 spring UriComponentsBuilder
UriComponentsBuilder
.fromUriString(baseUrl)
.queryParam("name", name)
.queryParam("surname", surname)
.build().toUriString();