2013-10-23 13 views
14

In gran parte del codice con cui lavoro c'è roba orribile come:Esiste un modo giusto per creare un URL?

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

o - ancora peggio:

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

C'è un modo giusto per:

  1. Crea una nuovo URL (o è un URI).
  2. Aggiungete correttamente i parametri di escape.
  3. Aggiungi percorsi di file ben strutturati in questi parametri.
  4. Risolvilo in una stringa.

In sostanza - è troppo facile costruire solo la stringa che è di farlo correttamente. C'è un modo per farlo correttamente che è facile come costruire semplicemente la stringa?

Aggiunto

Per chiarezza - e dopo un po 'di pensiero - suppongo che sto cercando qualcosa di simile:

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

in modo che si occuperà di tutta la sgradevolezza di fuga e l'aggiunta di "?"/"&" e cambia '\' a '/' invece di usare '\' per i file etc.

Se devo scrivere uno io (cioè se Apache non è un'opzione) ci sono reali Java techniqu es per uscire correttamente dalle varie parti. Intendo cose come l'escaping "" nei parametri come "." durante l'escape di "" in altri posti a "% 20".

+1

Penso che questo sembra simile. http://stackoverflow.com/questions/1861620/is-there-a-java-package-to-handle-building-urls –

+0

Inoltre, http://stackoverflow.com/questions/883136/is- there-a-good-url-builder-for-java – siledh

risposta

5

Ho scritto questo, puoi cambiarlo dove vuoi funzionalità extra. Non usa risorse esterne, fammi sapere se ho guardato qualcosa!

È fondamentalmente un wrapper per la classe URI che consente di aggiungere più facilmente sottodirectory e parametri all'URI. È possibile impostare valori predefiniti se non si è interessati ad alcune cose.

Modifica: Ho aggiunto un'opzione per utilizzare un URI relativo (in base alla tua domanda).

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

uscita:

assoluta

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

relativa

/servlet/jsp/somesub/anothersub param% 20lol = sconosciuto & paramY = noto

+0

Alla fine ho usato una variante di questa tecnica [come questa] (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>(); 

e nel codice per costruire l'URL.

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

    return builder.toString(); 

} 
+0

Downvoting, perché questo è solo il codice mezzo cotto che reinventa la rotella. Inoltre non affronta tutti i requisiti dell'OP. –

12

È possibile utilizzare Apache URIBuilder

codice di esempio:? Full Apache Example

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

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

+0

Si prega di aggiornare setAuthority non è più valido – Olayinka

+0

È 'URIBuilder', non' UriBuilder'. L'ultimo URL non è valido e rimuoverei il collegamento a quell'esempio. – ooi

1

Mi piace il suggerimento di @ Jeroen ma non ha fatto tutto quello che volevo, usando la sua idea di riunire le parti insieme ND quindi utilizzando un URI per far crescere il risultato finale ho messo insieme questa soluzione che sembra fare quello che voglio:

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

Potrebbe chiarire quale funzionalità è stata aggiunta? Felice di poter aiutare :) –

+0

@JeroenVannevel - Ho aggiunto la gestione di 'File' come query e un uso più completo della classe' URI'. Ho intenzione di contrassegnare la tua risposta come corretta in quanto ha ispirato il mio costruttore. Sto aspettando qualche suggerimento tardivo ma stimolante. – OldCurmudgeon

4

È inoltre possibile utilizzare la primavera UriComponentsBuilder

UriComponentsBuilder 
    .fromUriString(baseUrl) 
    .queryParam("name", name) 
    .queryParam("surname", surname) 
    .build().toUriString(); 
Problemi correlati