Возможно ли, чтобы пустые значения RequestParam использовали defaultValue?


120

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

@RequestMapping(value = "/test", method = RequestMethod.POST)
@ResponseBody
public void test(@RequestParam(value = "i", defaultValue = "10") int i) {
}

А затем вызовите этот запрос с помощью:

http://example.com/test?i=

Я получаю сообщение об ошибке

Не удалось преобразовать значение типа java.lang.String в тип int; вложенное исключение - java.lang.NumberFormatException: для входной строки: "" '

Я могу решить эту проблему, либо запретив клиенту javascript отправлять пустые параметры, либо приняв строковые значения и выполняя синтаксический анализ только в том случае, если они не обнаружены как пустые.

ОБНОВЛЕНИЕ : более поздние версии Spring теперь реализуют изначально желаемое поведение.

Я только что протестировал это в Spring 4.3.5 и обнаружил, что теперь поведение фактически превратит нулевое значение в значение по умолчанию без повышения a NumberFormatException, таким образом; мое исходное отображение теперь работает нормально.

Я не уверен, в какой версии весны было сделано это изменение поведения.


конечно, параметр будет целочисленным типом, чтобы вызвать это исключение?
laher

3
Я не эксперт по Spring, но используется ли значение по умолчанию, если вы его не устанавливаете? т.е. если ваш запрос будет example.com/test ? поскольку вы используете example.com/test?i=, тогда i присутствует и установлен в "", поэтому значение по умолчанию не используется
user902383

Спасибо amir75, случайно поставил Stringтипа. user902383, это правильно, хотя для целочисленного значения я бы предпочел, чтобы вместо значения null / empty использовалось defaultValue.
Бретт Райан,

Ответы:


176

Вы можете изменить тип @RequestParam на Integer и сделать его необязательным. Это позволит вашему запросу быть успешным, но тогда он будет нулевым. Вы можете явно установить для него значение по умолчанию в методе контроллера:

@RequestMapping(value = "/test", method = RequestMethod.POST)
@ResponseBody
public void test(@RequestParam(value = "i", required=false) Integer i) {
    if(i == null) {
        i = 10;
    }
    // ...
}

Я удалил defaultValue из приведенного выше примера, но вы можете включить его, если ожидаете получать запросы, где оно вообще не установлено:

http://example.com/test

6
Просто обновление по этому поводу, последние версии spring на самом деле больше не требуют нулевой проверки, поскольку желаемое поведение было включено в spring, что пустые значения приведут к использованию значения по умолчанию.
Бретт Райан

3
Устаревшие ответы, лучшее решение от @AppLend
Jose Pose S

101

Вы можете сохранить примитивный тип, установив значение по умолчанию, в вашем случае просто добавьте свойство "required = false" :

@RequestParam(value = "i", required = false, defaultValue = "10") int i

PS Эта страница из документации Spring может быть полезна: Тип аннотации RequestParam


1
Спасибо, но вы упустили суть моего вопроса в названии. Я попросил предоставить возможность указывать пустые параметры, /test?i=и, поскольку iон пуст, имеет значение по умолчанию.
Бретт Райан

5
Во всяком случае, когда defaultValueбыло предоставлено, required == falseнеявно
Тимур Милованов

4
Если параметр указан, но пуст defaultValue, не вступает в силу.
Бретт Райан

12

Вы можете установить RequestParam, используя общий класс Integer вместо int, это решит вашу проблему.

   @RequestParam(value= "i", defaultValue = "20") Integer i

1

Вы также можете сделать что-то вроде этого -

 @RequestParam(value= "i", defaultValue = "20") Optional<Integer> i

3
Если у вас есть defaultValue, нет необходимости делать это необязательным.
Kevin M

1

В 2013 году это считалось ошибкой: https://jira.spring.io/browse/SPR-10180.

и был исправлен в версии 3.2.2. После этого проблема не должна возникать ни в одной из версий, и ваш код должен работать нормально.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.