web-dev-qa-db-fra.com

Existe-t-il une bonne façon de créer une URL?

Dans une grande partie du code avec lequel je travaille, il y a des choses horribles comme:

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

ou - pire encore:

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

Existe-t-il une bonne façon de:

  1. Créez une nouvelle URL (ou s'agit-il d'un URI).
  2. Ajoutez-y des paramètres correctement échappés.
  3. Ajoutez des chemins de fichiers bien formés dans ces paramètres.
  4. Résolvez-le en une chaîne.

Essentiellement - il est trop facile de simplement construire la chaîne que de le faire correctement. Existe-t-il un moyen de le faire correctement aussi simple que de simplement construire la chaîne?

ajouté

Pour plus de clarté - et après un peu de réflexion - je suppose que je cherche quelque chose comme:

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

de sorte qu'il gérera tous les désagréments de s'échapper et d'ajouter "?"/"&" et de changer "\" en "/" au lieu d'utiliser "\" pour les fichiers, etc.

Si je dois en écrire un moi-même (c'est-à-dire si Apache n'est pas une option), y a-t-il de réelles techniques Java pour échapper correctement les différentes parties. Je veux dire des choses comme échapper "" dans les paramètres en tant que "." en échappant "" dans d'autres endroits un "% 20".

28
OldCurmudgeon

J'ai écrit ceci, vous pouvez le changer où vous voulez des fonctionnalités supplémentaires. Il n'utilise aucune ressource externe, faites-moi savoir si j'ai regardé quelque chose!

Il s'agit essentiellement d'un wrapper pour la classe URI qui vous permet d'ajouter plus facilement des sous-répertoires et des paramètres à l'URI. Vous pouvez définir des valeurs par défaut si vous n'êtes pas intéressé par certaines choses.

Modifier: j'ai ajouté une option pour utiliser un URI relatif (selon votre question).

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

Sortie:

Absolue

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

Relatif

/ servlet/jsp/somesub/anothersub? param% 20lol = inconnu & paramY = connu

8
Jeroen Vannevel

Vous pouvez utiliser Apache URIBuilder

Exemple de code: exemple complet d'Apache

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

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

21
Barun

Vous pouvez également utiliser spring riComponentsBuilder

UriComponentsBuilder
    .fromUriString(baseUrl)
    .queryParam("name", name)
    .queryParam("surname", surname)
    .build().toUriString();
9
Marcin Szymczak

J'aime la suggestion de @ Jeroen mais elle n'a pas tout à fait fait ce que je voulais donc, en utilisant son idée de rassembler les pièces ensemble puis en utilisant un URI pour augmenter le résultat final j'ai mis au point cette solution qui semble faire ce que Je voudrais:

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

}
1
OldCurmudgeon