Est-il possible que des valeurs RequestParam vides utilisent la valeur defaultValue?

120

si j'ai un mappage de requête similaire à ce qui suit:

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

Et puis appelez cette demande avec:

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

Je reçois le message d'erreur

Échec de la conversion de la valeur de type «java.lang.String» en type «int»; l'exception imbriquée est java.lang.NumberFormatException: Pour la chaîne d'entrée: "" '

Je peux résoudre ce problème en empêchant le client javascript d'envoyer des paramètres vides, ou en acceptant les valeurs de chaîne et en analysant uniquement si elles ne sont pas vides.

METTRE À JOUR : Les versions ultérieures de Spring implémentent désormais le comportement initialement souhaité.

Je viens de tester cela au printemps 4.3.5 et j'ai constaté que le comportement transformera en fait la valeur nulle en valeur par défaut sans augmenter un NumberFormatException , donc; ma cartographie d'origine fonctionne maintenant très bien.

Je ne sais pas quelle version du printemps ce changement de comportement a été effectué.

Brett Ryan
la source
sûrement le paramètre serait un type Integer pour lever cette exception?
laher le
3
Je ne suis pas expert en ressorts, mais la valeur par défaut est-elle utilisée lorsque vous ne la définissez pas? c'est-à-dire si votre demande sera example.com/test ? comme vous utilisez example.com/test?i= alors i est présent et défini sur "" donc la valeur par défaut n'est pas utilisée
user902383
Merci amir75, Stringtype fourni accidentellement . user902383, c'est correct, mais pour une valeur entière, je préférerais qu'une valeur nulle / vide utilise à la place la valeur par défaut.
Brett Ryan

Réponses:

177

Vous pouvez changer le type @RequestParam en Integer et le rendre inutile. Cela permettrait à votre demande de réussir, mais elle serait alors nulle. Vous pouvez le définir explicitement sur votre valeur par défaut dans la méthode du contrôleur:

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

J'ai supprimé defaultValue de l'exemple ci-dessus, mais vous souhaiterez peut-être l'inclure si vous prévoyez de recevoir des demandes où il n'est pas du tout défini:

http://example.com/test
Mat
la source
6
Juste une mise à jour à ce sujet, les versions récentes de spring ne nécessitent en fait plus la vérification de null car le comportement souhaité a été inclus avec spring que les valeurs vides entraîneront l'utilisation de la valeur par défaut.
Brett Ryan
3
Réponses obsolètes, la meilleure solution est de @AppLend
Jose Pose S
101

Vous pouvez conserver le type primitif en définissant la valeur par défaut, dans votre cas, ajoutez simplement la propriété "required = false" :

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

PS Cette page de la documentation Spring peut être utile: Type d'annotation RequestParam

AppLend
la source
1
Merci, mais vous avez manqué le point de ma question qui est dans le titre. J'ai demandé la possibilité de fournir des paramètres vides /test?i=et depuis iest vide, j'ai la valeur par défaut.
Brett Ryan
5
Quoi qu'il en soit, quand a defaultValueété fourni, required == falseimplicitement
Timur Milovanov
4
Si le paramètre est fourni mais vide, defaultValueil ne prend pas effet.
Brett Ryan
12

Vous pouvez définir RequestParam, en utilisant la classe générique Integer au lieu de int, cela résoudra votre problème.

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

Vous pouvez également faire quelque chose comme ça -

 @RequestParam(value= "i", defaultValue = "20") Optional<Integer> i
Tisha
la source
3
Si vous avez une valeur par défaut, il n'est pas nécessaire d'en faire une option.
Kevin M
1

Cela a été considéré comme un bogue en 2013: https://jira.spring.io/browse/SPR-10180

et a été corrigé avec la version 3.2.2. Le problème ne devrait se produire dans aucune version après cela et votre code devrait fonctionner correctement.

eis
la source