¿Cómo aceptar parámetros de fecha en una solicitud GET a Spring MVC Controller?

122

Tengo una solicitud GET que envía una fecha en formato AAAA-MM-DD a un controlador Spring. El código del controlador es el siguiente:

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

La solicitud se envía correctamente ya que estoy comprobando con Firebug. Me sale el error:

Estado HTTP 400: la solicitud enviada por el cliente era sintácticamente incorrecta.

¿Cómo puedo hacer que el controlador acepte este formato de fecha? Por favor ayuda. ¿Qué estoy haciendo mal?

LittleLebowski
fuente

Respuestas:

250

Ok, lo resolví. Escribiéndolo para cualquiera que pueda estar cansado después de un día completo de codificación sin parar y perderse una cosa tan tonta.

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

Si, es simple. Simplemente agregue la anotación DateTimeFormat.

LittleLebowski
fuente
18
Iba a escribir una respuesta pero me ganaste. También puede usar @DateTimeFormat (iso = ISO.DATE), que es el mismo formato. Por cierto, si puede, le sugiero que use la biblioteca Joda DateTime. Spring lo soporta realmente bien.
Luciano
La respuesta es generalmente buena, ¡PERO! ¿Hay alguna forma de configurarlo como predeterminado en Spring? Es un poco exagerado para poner @DateTimeFormaten cada controlador tiene ...
thorinkor
3
@Luciano, por supuesto, también puede hacer @DateTimeFormat (iso = ISO.DATE_TIME)
kiedysktos
2
@thorinkor En Spring Boot puede establecer el spring.mvc.date-formatatributo application.propertieso agregar beans que implementen la org.springframework.formatinterfaz (extender org.springframework.format.datetime.DateFormatteres probablemente el camino a seguir). En no Boot Spring, puede usar @Overrideel addFormattersmétodo WebMvcConfigurerAdaptery agregar sus beans de implementación del formateador allí.
UTF_or_Death
10

Esto es lo que hice para obtener la fecha formateada desde la interfaz

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

Puedes usarlo para conseguir lo que quieras.

AbdusSalam
fuente
11
No lo entendí. ¿Cuál es el punto de agregar @ DateTimeFormat a @ PathVariable si recibe dateString como String, no como Date?
ILya Cyclone
7

... o puede hacerlo de la manera correcta y tener una regla coherente para la serialización / deserialización de fechas en toda su aplicación. poner esto en application.properties:

spring.mvc.date-format=yyyy-MM-dd
Paul T
fuente
No funciona con los tipos de fecha de Java 8.
Dennis hace
3

La siguiente solución funciona perfectamente para la aplicación de arranque de primavera.

Controlador:

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

Entonces, en la persona que llama (en mi caso es un flujo web), necesitamos pasar la fecha y hora en este formato ( "aaaa-MM-dd HH: mm: ss" ).

Lado de la persona que llama:

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

Repositorio:

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

¡¡Salud!!

Aman Goel
fuente
2

Si desea usar una PathVariable, puede usar un método de ejemplo a continuación (todos los métodos son y hacen lo mismo):

//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 Jesús
fuente