What Is the Idiomatic Way to Compose a Url or Uri in Java

What is the idiomatic way to compose a URL or URI in Java?

Using HTTPClient worked well.

protected static String createUrl(List<NameValuePair> pairs) throws URIException{

HttpMethod method = new GetMethod("http://example.org");
method.setQueryString(pairs.toArray(new NameValuePair[]{}));

return method.getURI().getEscapedURI();

}

Is there a right way to build a URL?

I have written this up, you can change it where you want extra functionality. It doesn't use any external resources, let me know if I have looked over something!

It's basically a wrapper for the URI class that allows you to more easily add subdirectories and parameters to the URI. You can set default values if you're not interested in some things.

Edit: I have added an option to use a relative URI (per your 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();
}
}

Output:

Absolute

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

Relative

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

Is there a Java package to handle building URLs?

I found apache httpcomponents to be a solid and versatile library for dealing with HTTP in Java. However, here's a sample class, which might suffice for building URL query strings:

import java.net.URLEncoder;

public class QueryString {

private String query = "";

public QueryString(HashMap<String, String> map) {
Iterator it = mp.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry)it.next();
query += URLEncoder.encode(pairs.getKey(), "utf-8") + "=" +
URLEncoder.encode(pairs.getValue(), "utf-8");
if (it.hasNext()) { query += "&"; }
}
}

public QueryString(Object name, Object value) {
query = URLEncoder.encode(name.toString(), "utf-8") + "=" +
URLEncoder.encode(value.toString(), "utf-8");
}

public QueryString() { query = ""; }

public synchronized void add(Object name, Object value) {
if (!query.trim().equals("")) query += "&";
query += URLEncoder.encode(name.toString(), "utf-8") + "=" +
URLEncoder.encode(value.toString(), "utf-8");
}

public String toString() { return query; }
}

Usage:

HashMap<String, String> map = new HashMap<String, String>();
map.put("hello", "world");
map.put("lang", "en");

QueryString q = new QueryString(map);
System.out.println(q);
// => "hello=world&lang=en"

How to build url in java?

Try apache's URIBuilder : [Documentation]

import org.apache.http.client.utils.URIBuilder;

// ...

URIBuilder b = new URIBuilder("http://example.com");
b.addParameter("t", "search");
b.addParameter("q", "apples");

Url url = b.build().toUrl();

Maven dependency:

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.1</version>
</dependency>

Does there exist a mutable URL/URI object in Java?

There is no such JDK class that I know of.

Spring Web (Maven link) provides the UriComponentsBuilder class for building UriComponents which

Represents an immutable collection of URI components, mapping
component type to string values. Contains convenience getters for all
components. Effectively similar to java.net.URI, but with more
powerful encoding options and support for URI template variables.

How to append URL in java

A rather straightforward example (and very similar to Noel M's example who posted his while I was writing this) would be:

StringBuilder sb = new StringBuilder(url);
url.indexOf("?") > -1 ? sb.append("&") : sb.append("?");

// loop over your paramaters and append them like in Noel M's example

url = sb.toString();

Java: String representation of just the host, scheme, possibly port from servlet request

try this:

URL serverURL = new URL(request.getScheme(),      // http
request.getServerName(), // host
request.getServerPort(), // port
""); // file

EDIT

hiding default port on http and https:

int port = request.getServerPort();

if (request.getScheme().equals("http") && port == 80) {
port = -1;
} else if (request.getScheme().equals("https") && port == 443) {
port = -1;
}

URL serverURL = new URL(request.getScheme(), request.getServerName(), port, "");

Is there a Java method that encodes a collection of parameters as a URL query component?

I ended up writing my own. It can be called like

URIUtils.withQuery(uri, "param1", "value1", "param2", "value2");

which isn't so bad.

/**
* Concatenates <code>uri</code> with a query string generated from
* <code>params</code>.
*
* @param uri the base URI
* @param params a <code>Map</code> of key/value pairs
* @return a new <code>URI</code>
*/

public static URI withQuery(URI uri, Map<String, String> params) {
StringBuilder query = new StringBuilder();
char separator = '?';
for (Entry<String, String> param : params.entrySet()) {
query.append(separator);
separator = '&';
try {
query.append(URLEncoder.encode(param.getKey(), "UTF-8"));
if (!StringUtils.isEmpty(param.getValue())) {
query.append('=');
query.append(URLEncoder.encode(param.getValue(), "UTF-8"));
}
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
return URI.create(uri.toString() + query.toString());
}

/**
* Concatenates <code>uri</code> with a query string generated from
* <code>params</code>. The members of <code>params</code> will be
* interpreted as {key1, val1, key2, val2}. Empty values can be given
* as <code>""</code> or <code>null</code>.
*
* @param uri the base URI
* @param params the key/value pairs in sequence
* @return a new <code>URI</code>
*/
public static URI withQuery(URI uri, String... params) {
Map<String, String> map = new LinkedHashMap<String, String>();
for (int i = 0; i < params.length; i += 2) {
String key = params[i];
String val = i + 1 < params.length ? params[i + 1] : "";
map.put(key, val);
}
return withQuery(uri, map);
}

How can I append a query parameter to an existing URL?

This can be done by using the java.net.URI class to construct a new instance using the parts from an existing one, this should ensure it conforms to URI syntax.

The query part will either be null or an existing string, so you can decide to append another parameter with & or start a new query.

public class StackOverflow26177749 {

public static URI appendUri(String uri, String appendQuery) throws URISyntaxException {
URI oldUri = new URI(uri);

String newQuery = oldUri.getQuery();
if (newQuery == null) {
newQuery = appendQuery;
} else {
newQuery += "&" + appendQuery;
}

return new URI(oldUri.getScheme(), oldUri.getAuthority(),
oldUri.getPath(), newQuery, oldUri.getFragment());
}

public static void main(String[] args) throws Exception {
System.out.println(appendUri("http://example.com", "name=John"));
System.out.println(appendUri("http://example.com#fragment", "name=John"));
System.out.println(appendUri("http://example.com?email=john.doe@email.com", "name=John"));
System.out.println(appendUri("http://example.com?email=john.doe@email.com#fragment", "name=John"));
}
}

Shorter alternative

public static URI appendUri(String uri, String appendQuery) throws URISyntaxException {
URI oldUri = new URI(uri);
return new URI(oldUri.getScheme(), oldUri.getAuthority(), oldUri.getPath(),
oldUri.getQuery() == null ? appendQuery : oldUri.getQuery() + "&" + appendQuery, oldUri.getFragment());
}

Output

http://example.com?name=John
http://example.com?name=John#fragment
http://example.com?email=john.doe@email.com&name=John
http://example.com?email=john.doe@email.com&name=John#fragment

How to create a relative path to append to a URL that is not using the java.nio.file in JAVA?

Why not to use an UriBuilder? it was already discussed here:

What is the idiomatic way to compose a URL or URI in Java?
and here:

Is there a right way to build a URL?



Related Topics



Leave a reply



Submit