Параметры матрицы URL и параметры запроса
Мне интересно, использовать ли матрицу или параметры запроса в моих URL. Я нашел старое обсуждение этой темы не удовлетворяющим.
Примеры
- URL с параметрами запроса: http://some.where/thing?paramA=1¶mB=6542
- URL с матричными параметрами: http://some.where/thing;paramA=1;paramB=6542
На первый взгляд, матричные параметры имеют только преимущества:
- более читабельный
- не требуется кодирование и декодирование "&" в документах XML
- URL с "?" не кэшируются во многих случаях; URL-адреса с матричными параметрами кэшируются
- Параметры матрицы могут появляться повсюду в пути и не ограничены его концом.
- Параметры матрицы могут иметь более одного значения:
paramA=val1,val2
Но есть и недостатки:
- только несколько сред, таких как JAX-RS, поддерживают параметры матрицы
- Когда браузер отправляет форму через GET, параметры становятся параметрами запроса. Таким образом, это заканчивается двумя типами параметров для одной и той же задачи. Чтобы не запутывать пользователей служб REST и ограничивать усилия разработчиков служб, было бы проще всегда использовать параметры запроса - в этой области.
Поскольку разработчик сервиса может выбрать платформу с поддержкой матричных параметров, единственным оставшимся недостатком будет то, что браузеры создают по умолчанию параметры запроса.
Есть ли другие недостатки? Чтобы ты делал?
3 ответа
Важным отличием является то, что параметры матрицы применяются к конкретному элементу пути, а параметры запроса применяются к запросу в целом. Это вступает в игру при создании сложного запроса в стиле REST для нескольких уровней ресурсов и подресурсов:
http://example.com/res/categories;name=foo/objects;name=green/?page=1
Это действительно сводится к пространству имен. Если бы использовались только параметры запроса, вы бы получили такие параметры, как "имя_категории" и "имя_объекта", и потеряли бы ясность, добавленную локальностью параметров в запросе. Кроме того, при использовании инфраструктуры, такой как JAX-RS, все параметры запроса будут отображаться в каждом обработчике ресурсов, что приведет к потенциальным конфликтам и путанице.
Если ваш запрос имеет только один "уровень", то разница не так уж важна, и два типа параметров эффективно взаимозаменяемы, однако параметры запроса обычно лучше поддерживаются и более широко распознаются. В общем, я бы рекомендовал придерживаться параметров запроса для таких вещей, как формы HTML и простые одноуровневые HTTP API.
В дополнение к ответу Тима Сильвестра я хотел бы привести пример того, как параметры матрицы могут обрабатываться с помощью JAX-RS.
Параметры матрицы у последнего элемента ресурса
http://localhost:8080/res/categories/objects;name=green
Вы можете получить к ним доступ, используя
@MatrixParam
аннотирование@GET @Path("categories/objects") public String objects(@MatrixParam("name") String objectName) { return objectName; }
отклик
green
Но, как говорится в Javadoc
Обратите внимание, что
@MatrixParam
значение аннотации относится к имени параметра матрицы, который находится в последнем совпадающем сегменте пути структуры Java с аннотацией пути, которая вводит значение параметра матрицы.... что подводит нас к пункту 2
Параметры матрицы в середине URL
http://localhost:8080/res/categories;name=foo/objects;name=green
Вы можете получить доступ к параметрам матрицы в любом месте, используя переменные пути и
@PathParam
PathSegment
,@GET @Path("{categoryVar:categories}/objects") public String objectsByCategory(@PathParam("categoryVar") PathSegment categorySegment, @MatrixParam("name") String objectName) { MultivaluedMap<String, String> matrixParameters = categorySegment.getMatrixParameters(); String categorySegmentPath = categorySegment.getPath(); String string = String.format("object %s, path:%s, matrixParams:%s%n", objectName, categorySegmentPath, matrixParameters); return string; }
отклик
object green, path:categories, matrixParams:[name=foo]
Поскольку параметры матрицы предоставляются в виде
MultivaluedMap
Вы можете получить доступ к каждому поList<String> names = matrixParameters.get("name");
или если вам нужен только первый
String name = matrixParameters.getFirst("name");
Получить все параметры матрицы как один параметр метода
http://localhost:8080/res/categories;name=foo/objects;name=green//attributes;name=size
Использовать
List<PathSegment>
чтобы получить их всех@GET @Path("all/{var:.+}") public String allSegments(@PathParam("var") List<PathSegment> pathSegments) { StringBuilder sb = new StringBuilder(); for (PathSegment pathSegment : pathSegments) { sb.append("path: "); sb.append(pathSegment.getPath()); sb.append(", matrix parameters "); sb.append(pathSegment.getMatrixParameters()); sb.append("<br/>"); } return sb.toString(); }
отклик
path: categories, matrix parameters [name=foo] path: objects, matrix parameters [name=green] path: attributes, matrix parameters [name=size]
- Слишком важно быть отправленным в раздел комментариев.--
Я не уверен, в чём дело с матричными URL. Согласно статье о дизайне w3c, написанной TBL, это была просто идея дизайна, в которой прямо говорится, что она не является особенностью сети. Такие вещи, как относительные URL-адреса, не используются при его использовании. Если вы хотите использовать это, это нормально; просто нет стандартного способа его использовать, потому что это не стандарт. - Стив Померой
Итак, короткий ответ: если вам нужен RS для бизнес-целей, вам лучше использовать параметр запроса.