Перейти к основному содержимому

Необязательные переменные пути Spring

· 4 мин. чтения

1. Обзор

В этом уроке мы узнаем, как сделать переменную пути необязательной в Spring. Во- первых, мы опишем , как Spring связывает параметры @PathVariable в методе обработчика. Затем мы покажем различные способы сделать переменную пути необязательной в разных версиях Spring.

Краткий обзор переменных пути можно найти в нашей статье Spring MVC .

2. Как Spring связывает параметры @PathVariable

По умолчанию Spring попытается связать все параметры, аннотированные с помощью @PathVariable , в методе обработчика с соответствующими переменными в шаблоне URI. Если Spring выйдет из строя, он не доставит наш запрос этому методу обработчика.

Например, рассмотрим следующий метод getArticle , который пытается (безуспешно) сделать переменную пути id необязательной:

@RequestMapping(value = {"/article", "/article/{id}"})
public Article getArticle(@PathVariable(name = "id") Integer articleId) {
if (articleId != null) {
//...
} else {
//...
}
}

Здесь метод getArticle должен обслуживать запросы как к /article , так и к /article/{id} . Spring попытается привязать параметр articleId к переменной пути id , если она присутствует.

Например, отправка запроса на /article/123 устанавливает значение articleId равным 123.

С другой стороны, если мы отправим запрос в /article , Spring вернет код состояния 500 из-за следующего исключения:

org.springframework.web.bind.MissingPathVariableException:
Missing URI template variable 'id' for method parameter of type Integer

Это произошло потому, что Spring не мог установить значение для параметра articleId , так как идентификатор отсутствовал.

Итак, нам нужен какой-то способ сказать Spring игнорировать привязку определенного параметра @PathVariable , если у него нет соответствующей переменной пути, как мы увидим в следующих разделах.

3. Делаем переменные пути необязательными

3.1. Использование обязательного атрибута @PathVariable

Начиная с Spring 4.3.3, аннотация @PathVariable определяет логический атрибут , необходимый для того, чтобы мы могли указать, является ли переменная пути обязательной для метода обработчика.

Например, следующая версия getArticle использует обязательный атрибут:

@RequestMapping(value = {"/article", "/article/{id}"})
public Article getArticle(@PathVariable(required = false) Integer articleId) {
if (articleId != null) {
//...
} else {
//...
}
}

Поскольку атрибут required равен false , Spring не будет жаловаться, если в запросе не будет отправлена переменная пути id . То есть Spring установит для articleId значение id , если оно отправлено, или null в противном случае.

С другой стороны, если бы required было true , Spring выдавал бы исключение в случае отсутствия id .

3.2. Использование дополнительного типа параметра

Следующая реализация показывает, как Spring 4.1 вместе с классом Optional из JDK 8 `` предлагает еще один способ сделать articleId необязательным:

@RequestMapping(value = {"/article", "/article/{id}"}")
public Article getArticle(@PathVariable Optional<Integer> optionalArticleId) {
if (optionalArticleId.isPresent()) {
Integer articleId = optionalArticleId.get();
//...
} else {
//...
}
}

Здесь Spring создает экземпляр Optional<Integer> , optionalArticleId , для хранения значения id . Если id присутствует, optionArticleId будет обертывать его значение, в противном случае optionArticleId будет обертывать нулевое значение. Затем мы можем использовать методы isPresent (), get() или orElse() класса Optional для работы со значением.

3.3. Использование типа параметра карты

Другой способ определить необязательную переменную пути, которая доступна начиная с Spring 3.2, — использовать M ap для параметров @PathVariable :

@RequestMapping(value = {"/article", "/article/{id}"})
public Article getArticle(@PathVariable Map<String, String> pathVarsMap) {
String articleId = pathVarsMap.get("id");
if (articleId != null) {
Integer articleIdAsInt = Integer.valueOf(articleId);
//...
} else {
//...
}
}

В этом примере параметр Map<String, String> pathVarsMap собирает все переменные пути, которые находятся в URI, в виде пар ключ/значение. Затем мы можем получить определенную переменную пути, используя метод get() .

Обратите внимание: поскольку Spring извлекает значение переменной пути как String , мы использовали метод Integer.valueOf() для преобразования его в Integer .

3.4. Использование двух методов обработчика

Если мы использовали устаревшую версию Spring, мы можем разделить метод обработчика getArticle на два метода.

Первый метод будет обрабатывать запросы к /article/{id} :

@RequestMapping(value = "/article/{id}")
public Article getArticle(@PathVariable(name = "id") Integer articleId) {
//...
}

В то время как второй метод будет обрабатывать запросы к /article :

@RequestMapping(value = "/article")
public Article getDefaultArticle() {
//...
}

4. Вывод

Подводя итог, мы обсудили, как сделать переменную пути необязательной в разных версиях Spring.

Как обычно, полный код для этой статьи доступен на GitHub .