Jak zaakceptować parametry daty w żądaniu GET do kontrolera Spring MVC?

122

Mam żądanie GET, które wysyła datę w formacie RRRR-MM-DD do kontrolera Spring. Kod kontrolera jest następujący:

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

Żądanie jest wysyłane poprawnie, ponieważ sprawdzam z Firebug. Wyskakuje mi błąd:

Status HTTP 400: Żądanie wysłane przez klienta było niepoprawne pod względem składniowym.

Jak mogę sprawić, by administrator zaakceptował ten format daty? Proszę pomóż. Co ja robię źle?

LittleLebowski
źródło

Odpowiedzi:

250

Ok, rozwiązałem to. Pisanie go dla każdego, kto może być zmęczony po całym dniu ciągłego kodowania i przegapić taką głupią rzecz.

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

Tak, to proste. Po prostu dodaj adnotację DateTimeFormat.

LittleLebowski
źródło
18
Miałem napisać odpowiedź, ale mnie pokonałeś. Możesz również użyć @DateTimeFormat (iso = ISO.DATE), który ma ten sam format. Przy okazji, jeśli możesz, sugeruję skorzystanie z biblioteki Joda DateTime. Wiosna bardzo dobrze to wspiera.
Luciano
Odpowiedź jest ogólnie w porządku, ALE! Czy jest sposób, aby skonfigurować go jako domyślny dla Springa? To trochę przesada, aby umieścić @DateTimeFormatkażdy kontroler, jaki masz ...
thorinkor,
3
@Luciano oczywiście możesz też zrobić @DateTimeFormat (iso = ISO.DATE_TIME)
kiedysktos
2
@thorinkor W Spring Boot możesz ustawić spring.mvc.date-formatatrybut application.propertieslub dodać komponenty bean, które implementują org.springframework.formatinterfejs (rozszerzenie org.springframework.format.datetime.DateFormatterjest prawdopodobnie właściwą drogą). W non-Boot wiosną można sposób i dodać tam fasolę Formatter-wykonawczych. @OverrideaddFormattersWebMvcConfigurerAdapter
UTF_or_Death
10

Oto, co zrobiłem, aby uzyskać sformatowaną datę z interfejsu

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

Możesz go użyć, aby uzyskać to, czego chcesz.

AbdusSalam
źródło
11
Nie rozumiem. Jaki jest sens dodawania @ DateTimeFormat do @ PathVariable, jeśli otrzymasz dateString jako ciąg, a nie jako datę?
ILya Cyclone
7

... lub możesz to zrobić we właściwy sposób i mieć spójną regułę serializacji / deserializacji dat w całej aplikacji. umieść to w application.properties:

spring.mvc.date-format=yyyy-MM-dd
Paul T.
źródło
Nie działa z typami dat Java 8.
Dennis
3

Poniższe rozwiązanie doskonale sprawdza się przy zastosowaniu do butów sprężynowych.

Kontroler:

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

Zatem w programie wywołującym (w moim przypadku jest to strumień sieciowy) musimy przekazywać datę i godzinę w formacie ( „rrrr-MM-dd HH: mm: ss” ).

Strona dzwoniącego:

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

Magazyn:

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

Twoje zdrowie!!

Aman Goel
źródło
2

Jeśli chcesz użyć zmiennej PathVariable, możesz użyć przykładowej metody poniżej (wszystkie metody są i robią to samo):

//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
źródło