49

在我使用的大部分代码中,都有一些可怕的东西,例如:

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 不是一个选项),是否有真正的 Java 技术可以正确地转义各个部分。我的意思是将参数中的“”转义为“。”。而在其他地方转义“”“%20”。

4

5 回答 5

59

您可以使用Apache URIBuilder

示例代码:完整的 Apache 示例

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

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

于 2013-10-23T11:10:38.713 回答
26

您还可以使用弹簧UriComponentsBuilder

UriComponentsBuilder
    .fromUriString(baseUrl)
    .queryParam("name", name)
    .queryParam("surname", surname)
    .build().toUriString();
于 2017-06-17T16:04:26.553 回答
15

我已经写了这个,你可以在你想要额外功能的地方改变它。它不使用任何外部资源,如果我查看了某些内容,请告诉我!

它基本上是类的包装器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¶mY=known

相对的

/servlet/jsp/somesub/anothersub?param%20lol=unknown¶mY=known

于 2013-10-23T10:28:23.797 回答
1

我喜欢@Jeroen 的建议,但它并没有完全满足我的要求,使用他将零件收集在一起然后使用 aURI来增加最终结果的想法我将这个解决方案放在一起,这似乎可以满足我的需求:

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

}
于 2013-10-23T12:23:41.627 回答
-6

推荐

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

}
于 2013-10-23T09:57:18.083 回答