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 un bon moyen de:

  1. Créer une nouvelle URL (ou est-ce 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. Est-il un moyen de le faire correctement, ce qui est-ce aussi facile que de simplement construire la chaîne?

Ajouté

Pour plus de clarté-et après une petite 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 traitera de tous les désagréments de s'échapper et d'ajouter "?"/"&" et "\" pour "/" 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) existe-t-il de vraies techniques Java pour échapper correctement les différentes parties. Je veux dire des choses comme s'échapper du "" dans les paramètres "."tout en échappant "" dans d'autres endroits "%20".

Author: OldCurmudgeon, 2013-10-23

5 answers

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!

C'est essentiellement 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 certaines choses ne vous intéressent pas.

Edit: 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:

Absolu

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

Par rapport

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

 7
Author: Jeroen Vannevel, 2013-10-23 10:57:47

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+monde=foo%26bar#foo

 14
Author: Barun, 2018-09-28 14:07:16

Vous pouvez aussi utiliser le printemps UriComponentsBuilder

UriComponentsBuilder
    .fromUriString(baseUrl)
    .queryParam("name", name)
    .queryParam("surname", surname)
    .build().toUriString();
 7
Author: Marcin Szymczak, 2017-06-17 16:04:26

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

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
Author: OldCurmudgeon, 2014-05-17 22:03:20

Recommandations

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

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

Et dans le code pour construire l'URL.

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

    return builder.toString();

}
 -2
Author: RamonBoza, 2013-10-23 09:57:18