2013-10-23 46 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(); 
相關問題