Comment accepter les paramètres de date dans une requête GET à Spring MVC Controller?

122

J'ai une requête GET qui envoie une date au format AAAA-MM-JJ à un contrôleur Spring. Le code du contrôleur est le suivant:

@RequestMapping(value="/fetch" , method=RequestMethod.GET)
    public @ResponseBody String fetchResult(@RequestParam("from") Date fromDate) {
        //Content goes here
    }

La demande est envoyée correctement lorsque je vérifie avec Firebug. J'obtiens l'erreur:

État HTTP 400: la requête envoyée par le client était syntaxiquement incorrecte.

Comment puis-je faire en sorte que le contrôleur accepte ce format de date? Veuillez aider. Qu'est-ce que je fais mal?

LittleLebowski
la source

Réponses:

250

Ok, je l'ai résolu. Écrire pour tous ceux qui pourraient être fatigués après une journée complète de codage non-stop et manquer une chose aussi stupide.

@RequestMapping(value="/fetch" , method=RequestMethod.GET)
    public @ResponseBody String fetchResult(@RequestParam("from") @DateTimeFormat(pattern="yyyy-MM-dd") Date fromDate) {
        //Content goes here
    }

Oui, c'est simple. Ajoutez simplement l'annotation DateTimeFormat.

LittleLebowski
la source
18
J'allais écrire une réponse mais tu m'as battu. Vous pouvez également utiliser @DateTimeFormat (iso = ISO.DATE), qui est du même format. BTW, si vous pouvez, je vous suggère d'utiliser la bibliothèque Joda DateTime. Spring le supporte très bien.
Luciano
La réponse est généralement ok, MAIS! Existe-t-il un moyen de le configurer par défaut sur Spring? C'est un peu exagéré de mettre @DateTimeFormatdans chaque contrôleur que vous avez ...
Thorinkor
3
@Luciano bien sûr, vous pouvez également faire @DateTimeFormat (iso = ISO.DATE_TIME)
kiedysktos
2
@thorinkor Dans Spring Boot, vous pouvez définir l' spring.mvc.date-formatattribut application.propertiesou ajouter des beans qui implémentent l' org.springframework.formatinterface (l'extension org.springframework.format.datetime.DateFormatterest probablement la voie à suivre). Dans non-Boot Spring, vous pouvez utiliser @Overridela addFormattersméthode WebMvcConfigurerAdapteret y ajouter vos beans d'implémentation du formateur.
UTF_or_Death
10

C'est ce que j'ai fait pour obtenir la date formatée à partir du frontal

  @RequestMapping(value = "/{dateString}", method = RequestMethod.GET)
  @ResponseBody
  public HttpStatus getSomething(@PathVariable @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) String dateString) {
   return OK;
  }

Vous pouvez l'utiliser pour obtenir ce que vous voulez.

AbdusSalam
la source
11
Je n'ai pas compris. Quel est l'intérêt d'ajouter @ DateTimeFormat à @ PathVariable si vous recevez dateString sous forme de chaîne et non de date?
ILya Cyclone
7

... ou vous pouvez le faire de la bonne manière et avoir une règle cohérente pour la sérialisation / désérialisation des dates dans toute votre application. mettez ceci dans application.properties:

spring.mvc.date-format=yyyy-MM-dd
Paul T
la source
Ne fonctionne pas avec les types de date Java 8.
Dennis il y a
3

La solution ci-dessous fonctionne parfaitement pour l'application de démarrage à ressort.

Manette:

@GetMapping("user/getAllInactiveUsers")
List<User> getAllInactiveUsers(@RequestParam("date") @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") Date dateTime) {
    return userRepository.getAllInactiveUsers(dateTime);
}

Donc, dans l'appelant (dans mon cas, c'est un flux Web), nous devons passer la date et l'heure dans ce format ( "aaaa-MM-jj HH: mm: ss" ).

Côté appelant:

public Flux<UserDto> getAllInactiveUsers(String dateTime) {
    Flux<UserDto> userDto = RegistryDBService.getDbWebClient(dbServiceUrl).get()
            .uri("/user/getAllInactiveUsers?date={dateTime}", dateTime).retrieve()
            .bodyToFlux(User.class).map(UserDto::of);
    return userDto;
}

Dépôt:

@Query("SELECT u from User u  where u.validLoginDate < ?1 AND u.invalidLoginDate < ?1 and u.status!='LOCKED'")
List<User> getAllInactiveUsers(Date dateTime);

À votre santé!!

Aman Goel
la source
2

Si vous souhaitez utiliser un PathVariable, vous pouvez utiliser un exemple de méthode ci-dessous (toutes les méthodes sont et font la même chose):

//You can consume the path .../users/added-since1/2019-04-25
@GetMapping("/users/added-since1/{since}")
public String userAddedSince1(@PathVariable("since") @DateTimeFormat(pattern = "yyyy-MM-dd") Date since) {
    return "Date: " + since.toString(); //The output is "Date: Thu Apr 25 00:00:00 COT 2019"
}

//You can consume the path .../users/added-since2/2019-04-25
@RequestMapping("/users/added-since2/{since}")
public String userAddedSince2(@PathVariable("since") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) Date since) {
    return "Date: " + since.toString(); //The output is "Date: Wed Apr 24 19:00:00 COT 2019"
}

//You can consume the path .../users/added-since3/2019-04-25
@RequestMapping("/users/added-since3/{since}")
public String userAddedSince3(@PathVariable("since") @DateTimeFormat(pattern = "yyyy-MM-dd") Date since) {
    return "Date: " + since.toString(); //The output is "Date: Thu Apr 25 00:00:00 COT 2019"
}
David Jésus
la source