2013-10-23 50 views
14

在多少,我与那里工作的代码是可怕的东西,如:有没有正确的方法来建立一个URL?

String url = "../Somewhere/SomeServlet?method=AMethod&id="+object.getSomething()+ "&aParam="+object.getSomethingElse()); 

或 - 甚至更糟:

String url = "Somewhere/Here/Something.jsp?path="+aFile.toString().replace("\\","/")+ "&aParam="+object.getSomethingElse()); 

是否有一个正确的方式:

  1. 创建新的URL(或者它是一个URI)。
  2. 向它添加正确的转义参数。
  3. 在这些参数中添加格式良好的文件路径。
  4. 将其解析为字符串。

本质上 - 建立字符串太容易了,而不是正确地做。有没有办法做到这一点正确就像建立字符串一样简单?

新增

为了清楚 - 我想我在寻找类似 - 和一点点思索后:

String s = new MyThing() 
    .setPlace("Somewhere/Something.jsp") 
    .addParameter(aName,aValue) 
    .addParameter(aName,aFile) 
    .toString(); 

,这样它会处理所有逃避和增加的不愉快“?”/“&”并将“\”更改为“/”而不是使用“\”作为文件等。

如果我必须自己写一个(即,如果Apache不是选项) techniqu es正确地逃脱各个部分。我的意思是像在参数中跳过“”。“同时在其他地方将“%20”转义为“”。

+1

我觉得这似乎是相似的。 http://stackoverflow.com/questions/1861620/is-there-a-java-package-to-handle-building-urls –

+0

另外,http://stackoverflow.com/questions/883136/is-有一个很好的url-builder-for-java – siledh

回答

5

我已经写了这个,你可以改变它,你想要额外的功能。它不使用任何外部资源,让我知道如果我看了一些东西!

它基本上是URI类的包装,它允许您更容易地将子目录和参数添加到URI。如果你对某些事情不感兴趣,你可以设置默认值。

编辑:我已添加一个选项来使用相对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(); 
    } 
} 

输出:

绝对

http://www.example.com/somesub/anothersub?param%20lol=unknown&paramY=known

相对

/servlet的/ JSP/somesub/anothersub PARAM%20lol =未知& paramY =知

+0

我最终使用了这种技术的变体[像这样](http://stackoverflow.com/a/19541585/823393)。 – OldCurmudgeon

-2

Recomendations

private final String BASE_URL = Properties.getProperty("base-url"); 

private Map propertiesMap; // = new HashMap<String,String>(); 

,并在代码来构建URL。

public String buildURL(){ 
    StringBuilder builder = new StringBuilder(); 
    builder.append(BASE_URL); 
    //for each property, append it 

    return builder.toString(); 

} 
+0

Downvoting,因为这只是一半的代码,重新发明轮子。它也没有解决OP的所有要求。 –

12

您可以使用Apache URIBuilder

示例代码:Full Apache Example

UriBuilder builder = new UriBuilder() 
    .setScheme("http") 
    .setHost("apache.org") 
    .setPath("/shindig") 
    .addParameter("hello world", "foo&bar") 
    .setFragment("foo"); 
builder.toString(); 

输出:http://apache.org/shindig?hello+world=foo%26bar#foo

+0

请更新setAuthority不再有效 – Olayinka

+0

它是'URIBuilder',而不是'UriBuilder'。最后一个网址无效,我会删除该示例的链接。 – ooi

1

我喜欢@ Jeroen的建议,但它并没有完全做到我想要的那样,用他的想法将零件收集在一起次然后用URI增长的最终结果我放在一起这一解决方案,这似乎做我想做的:

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); 
    } 
    } 

} 
+0

你能否澄清你添加了哪些功能?很高兴我可以帮助:) –

+0

@JeroenVannevel - 我将'File'的处理添加为查询并更全面地使用了'URI'类。我打算标记你的答案是正确的,因为它激发了我的建设者。我在等待任何迟到但鼓舞人心的建议。 – OldCurmudgeon

4

你也可以使用Spring UriComponentsBuilder

UriComponentsBuilder 
    .fromUriString(baseUrl) 
    .queryParam("name", name) 
    .queryParam("surname", surname) 
    .build().toUriString(); 
相关问题