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:
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".
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¶mY=known
Relatif
/ servlet/jsp/somesub/anothersub? param% 20lol = inconnu & paramY = connu
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();
Vous pouvez également utiliser spring riComponentsBuilder
UriComponentsBuilder
.fromUriString(baseUrl)
.queryParam("name", name)
.queryParam("surname", surname)
.build().toUriString();
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);
}
}
}