É possível ter valores de RequestParam vazios usando defaultValue?

120

se eu tiver um mapeamento de solicitação semelhante ao seguinte:

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

E então chame esta solicitação com:

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

Recebo a mensagem de erro

Falha ao converter o valor do tipo 'java.lang.String' para o tipo 'int'; a exceção aninhada é java.lang.NumberFormatException: Para string de entrada: "" '

Posso resolver isso impedindo o cliente javascript de enviar parâmetros vazios ou aceitando valores de string e analisando apenas se eles não estiverem em branco.

ATUALIZAÇÃO : as versões posteriores do Spring agora implementam o comportamento originalmente desejado.

Acabei de testar isso no spring 4.3.5 e descobri que o comportamento agora vai de fato transformar o valor nulo no valor padrão sem aumentar a NumberFormatException, portanto; meu mapeamento original agora funciona bem.

Não tenho certeza de qual versão da primavera essa mudança de comportamento foi feita.

Brett Ryan
fonte
certamente o parâmetro seria um tipo inteiro para levantar essa exceção?
laher
3
Não sou especialista em molas, mas o valor padrão é usado quando você não o define? ou seja, se sua solicitação for example.com/test ? conforme você usa example.com/test?i= então i está presente e definido como "", então o valor padrão não é usado
user902383
Obrigado amir75, Stringtipo fornecido acidentalmente . user902383, isso é correto, embora para um valor inteiro eu preferisse que um valor nulo / vazio usasse o defaultValue.
Brett Ryan

Respostas:

175

Você pode alterar o tipo @RequestParam para um Integer e torná-lo desnecessário. Isso permitiria que sua solicitação fosse bem-sucedida, mas seria nula. Você pode defini-lo explicitamente com seu valor padrão no método do controlador:

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

Removi o defaultValue do exemplo acima, mas você pode querer incluí-lo se espera receber solicitações em que não está definido de forma alguma:

http://example.com/test
Matt
fonte
6
Apenas uma atualização sobre isso, as versões recentes do spring na verdade não exigem mais a verificação de nulo, pois o comportamento desejado foi incluído com o spring, que valores vazios resultarão no valor padrão sendo usado.
Brett Ryan
3
Respostas obsoletas, a melhor solução é de @AppLend
Jose Pose S
101

Você pode manter o tipo primitivo definindo o valor padrão, no seu caso, basta adicionar a propriedade "required = false" :

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

PS Esta página da documentação do Spring pode ser útil: Tipo de anotação RequestParam

AppLend
fonte
1
Obrigado, mas você perdeu o ponto da minha pergunta que está no título. Solicitei a capacidade de fornecer parâmetros vazios /test?i=e, como iestá vazio, tem o valor padrão.
Brett Ryan de
5
De qualquer forma, quando defaultValuefoi fornecido, required == falseimplicitamente
Timur Milovanov
4
Se o parâmetro for fornecido, mas estiver vazio defaultValue, não terá efeito.
Brett Ryan
12

Você pode definir RequestParam, usando a classe genérica Integer em vez de int, isso resolverá seu problema.

   @RequestParam(value= "i", defaultValue = "20") Integer i
Anand Tagore
fonte
1

Você também pode fazer algo assim -

 @RequestParam(value= "i", defaultValue = "20") Optional<Integer> i
Tisha
fonte
3
Se você tiver um defaultValue, não há necessidade de torná-lo opcional.
Kevin M
1

Isso foi considerado um bug em 2013: https://jira.spring.io/browse/SPR-10180

e foi corrigido com a versão 3.2.2. O problema não deve ocorrer em nenhuma versão depois disso e seu código deve funcionar perfeitamente.

eis
fonte