Wie akzeptiere ich Datumsparameter in einer GET-Anfrage an Spring MVC Controller?

122

Ich habe eine GET-Anfrage, die ein Datum im Format JJJJ-MM-TT an einen Spring Controller sendet. Der Controller-Code lautet wie folgt:

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

Die Anfrage wird korrekt gesendet, da ich mich bei Firebug erkundige. Ich bekomme den Fehler:

HTTP-Status 400: Die vom Client gesendete Anforderung war syntaktisch falsch.

Wie kann ich den Controller dazu bringen, dieses Datumsformat zu akzeptieren? Bitte helfen Sie. Was mache ich falsch?

LittleLebowski
quelle

Antworten:

250

Ok, ich habe es gelöst. Schreiben Sie es für alle, die nach einem ganzen Tag ununterbrochener Codierung müde sein könnten und eine so dumme Sache verpassen.

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

Ja, das ist einfach. Fügen Sie einfach die DateTimeFormat-Annotation hinzu.

LittleLebowski
quelle
18
Ich wollte eine Antwort schreiben, aber du hast mich geschlagen. Sie können auch @DateTimeFormat (iso = ISO.DATE) verwenden, das das gleiche Format hat. Übrigens, wenn Sie können, schlage ich vor, dass Sie die Joda DateTime-Bibliothek verwenden. Der Frühling unterstützt es sehr gut.
Luciano
Die Antwort ist im Allgemeinen in Ordnung, ABER! Gibt es eine Möglichkeit, es als Standard für Spring zu konfigurieren? Es ist ein bisschen übertrieben, @DateTimeFormatjeden Controller
einzubauen, den
3
@ Luciano natürlich können Sie auch @DateTimeFormat (iso = ISO.DATE_TIME) tun
kiedysktos
2
@thorinkor In Spring Boot können Sie das spring.mvc.date-formatAttribut in festlegen application.propertiesoder Beans hinzufügen, die die org.springframework.formatSchnittstelle implementieren (Erweiterung org.springframework.format.datetime.DateFormatterist wahrscheinlich der richtige Weg). In Nicht-Boot Spring können Sie @Overridedie addFormattersMethode WebMvcConfigurerAdapterund Hinzufügen Ihrer Formatter-implementierenden Beans dort.
UTF_or_Death
10

Dies ist, was ich getan habe, um ein formatiertes Datum vom Frontend zu erhalten

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

Sie können es verwenden, um zu bekommen, was Sie wollen.

AbdusSalam
quelle
11
Ich habe es nicht verstanden. Was bringt es, @ DateTimeFormat zu @ PathVariable hinzuzufügen, wenn Sie dateString als String und nicht als Date erhalten?
ILya Cyclone
7

... oder Sie können es richtig machen und eine kohärente Regel für die Serialisierung / Deserialisierung von Daten in Ihrer gesamten Anwendung festlegen. Fügen Sie dies in application.properties ein:

spring.mvc.date-format=yyyy-MM-dd
Paul T.
quelle
3

Die folgende Lösung funktioniert perfekt für die Federstiefelanwendung.

Regler:

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

Im Aufrufer (in meinem Fall handelt es sich um einen Web-Flux) müssen wir also die Datums- und Uhrzeitangabe in diesem Format ( "JJJJ-MM-TT HH: MM: SS" ) übergeben.

Anruferseite:

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;
}

Repository:

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

Prost!!

Aman Goel
quelle
2

Wenn Sie eine PathVariable verwenden möchten, können Sie unten eine Beispielmethode verwenden (alle Methoden sind und tun dasselbe):

//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 Jesus
quelle