Правильный способ создания URL-адреса?
В большей части кода, с которым я работаю, есть такие ужасные вещи, как:
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());
Есть ли правильный способ:
- Создайте новый URL (или это URI).
- Добавьте к нему правильно экранированные параметры.
- Добавьте корректные пути к файлам в этих параметрах.
- Разрешить его в строку.
По существу - слишком просто просто построить строку, чем это сделать правильно. Есть ли способ сделать это правильно, что так же просто, как просто построить строку?
Добавлен
Для ясности - и после небольшой мысли - я полагаю, что я ищу что-то вроде:
String s = new MyThing()
.setPlace("Somewhere/Something.jsp")
.addParameter(aName,aValue)
.addParameter(aName,aFile)
.toString();
чтобы он имел дело со всей неприятностью побега и добавлением "?" / "&". и сменив "\" на "/" вместо "\" для файлов и т.д.
Если я должен написать один сам (то есть, если Apache не является вариантом) существуют ли реальные методы Java для правильного выхода из разных частей. Я имею в виду такие вещи, как экранирование "в параметрах как". "а в других местах -" %20".
Ответы
Ответ 1
Я написал это, вы можете изменить его там, где вам нужна дополнительная функциональность. Он не использует никаких внешних ресурсов, дайте мне знать, если я что-то посмотрел!
В основном это оболочка для класса 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
Относительный
/сервлет/JSP/somesub/anothersub парам %20lol = неизвестно &? = ParamY известно
Ответ 2
Вы можете использовать Apache URIBuilder
Пример кода: Полный пример Apache
UriBuilder builder = new UriBuilder()
.setScheme("http")
.setHost("apache.org")
.setPath("/shindig")
.addParameter("hello world", "foo&bar")
.setFragment("foo");
builder.toString();
Выход: http://apache.org/shindig?hello+world=foo%26bar#foo
Ответ 3
Вы также можете использовать spring UriComponentsBuilder
UriComponentsBuilder
.fromUriString(baseUrl)
.queryParam("name", name)
.queryParam("surname", surname)
.build().toUriString();
Ответ 4
Мне нравится предложение @Jeroen, но он не совсем сделал все, что я хотел, используя его идею собрать части вместе, а затем используя URI
, чтобы вырастить конечный результат, я собрал это решение, которое, похоже, делает то, что Я хочу:
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);
}
}
}
Ответ 5
Рекомендации
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();
}