Сохранить значения @PathParam из REST-вызова в списке или массиве
Моя функция выглядит так:
@PUT
@Path("property/{uuid}/{key}/{value}")
@Produces("application/xml")
public Map<String,ValueEntity> updateProperty(@Context HttpServletRequest request,
@PathParam("key") String key,
@PathParam("value") String value,
@PathParam("uuid") String uuid) throws Exception {
...
}
Я должен изменить его, чтобы он принимал неопределенный (или многие) список пар ключ-значение из вызова REST, что-то вроде
@Path("property/{uuid}/{key1}/{value1}/{key2}/{value2}/{key3}/{value3}/...")
Можно ли хранить их в массиве или списке, поэтому я не перечисляю десятки @PathParams и параметров, чтобы избежать этого:
@PathParam("key1") String key1,
@PathParam("key2") String key2,
@PathParam("key3") String key3,
2 ответа
Может быть, это хорошая возможность переосмыслить этот дизайн. Используя /
с, мы в некотором смысле означаем, с каждым /
что мы пытаемся найти другой ресурс. Пары ключ / значение (в контексте URL) в основном предназначены для параметров запроса или параметров матрицы.
Если /property/{uuid}
это путь к главному ресурсу, и мы просто хотим предложить клиенту некоторые параметры для доступа к этому ресурсу, тогда мы могли бы разрешить параметры матрицы или параметры запроса
Параметры матрицы (в URL запроса) будут выглядеть примерно так
/12345;key1=value1;key2=value2;key3=value3
Ресурсный метод для получения значений может выглядеть примерно так
@GET
@Path("/property/{uuid}")
public Response getMatrix(@PathParam("uuid") PathSegment pathSegment) {
StringBuilder builder = new StringBuilder();
// Get the {uuid} value
System.out.println("Path: " + pathSegment.getPath());
MultivaluedMap matrix = pathSegment.getMatrixParameters();
for (Object key : matrix.keySet()) {
builder.append(key).append(":")
.append(matrix.getFirst(key)).append("\n");
}
return Response.ok(builder.toString()).build();
}
- Увидеть
PathSegment
Параметры запроса (в URL запроса) могут выглядеть примерно так
/12345?key1=value1&key2=value2&key3=value3
Ресурсный метод для получения значений может выглядеть примерно так
@GET
@Path("/property/{uuid}")
public Response getQuery(@PathParam("uuid") String uuid,
@Context UriInfo uriInfo) {
MultivaluedMap params = uriInfo.getQueryParameters();
StringBuilder builder = new StringBuilder();
for (Object key : params.keySet()) {
builder.append(key).append(":")
.append(params.getFirst(key)).append("\n");
}
return Response.ok(builder.toString()).build();
}
- Увидеть
UriInfo
Разница в том, что параметры Matrix могут быть встроены в сегменты пути, а параметры запроса должны быть помещены в конце URL-адреса. Вы также можете заметить небольшую разницу в синтаксисе.
Некоторые ресурсы
- Строка запроса (Википедия)
- Когда использовать параметры запроса в сравнении с параметрами матрицы?
- Параметры матрицы URL и параметры запроса
ОБНОВИТЬ
Также глядя на PUT
в сигнатуре вашего метода кажется, что вы пытаетесь обновить ресурс, используя путь в качестве значений, для которых вы пытаетесь обновить, поскольку я не вижу никаких параметров в вашем методе для тела объекта. При PUTting вы должны отправлять представление в теле сущности, а не как сегменты пути или параметры.
Обходной путь:
@Path("/foo/bar/{other: .*}
public Response foo(@PathParam("other") VariableStrings vstrings) {
String[] splitPath = vstrings.getSplitPath();
}
Класс VariableStrings:
public class VariableStrings {
private String[] splitPath;
public VariableStrings(String unparsedPath) {
splitPath = unparsedPath.split("/");
}
}
Последовательность сегмента пути к массиву vararg в JAX-RS / Джерси?
Другой пример, где вы отображаете необязательный параметр на карту:
@GET
@ Produces({"application/xml", "application/json", "plain/text"})
@ Path("/location/{locationId}{path:.*}")
public Response getLocation(@PathParam("locationId") int locationId, @PathParam("path") String path) {
Map < String, String > params = parsePath(path);
String format = params.get("format");
if ("xml".equals(format)) {
String xml = "<location<</location<<id<</id<" + locationId + "";
return Response.status(200).type("application/xml").entity(xml).build();
} else if ("json".equals(format)) {
String json = "{ 'location' : { 'id' : '" + locationId + "' } }";
return Response.status(200).type("application/json").entity(json).build();
} else {
String text = "Location: id=" + locationId;
return Response.status(200).type("text/plain").entity(text).build();
}
}
private Map < String, String > parsePath(String path) {
if (path.startsWith("/")) {
path = path.substring(1);
}
String[] pathParts = path.split("/");
Map < String, String > pathMap = new HashMap < String, String > ();
for (int i = 0; i < pathParts.length / 2; i++) {
String key = pathParts[2 * i];
String value = pathParts[2 * i + 1];
pathMap.put(key, value);
}
return pathMap;
}