Como aceitar parâmetros de data em uma solicitação GET para o Spring MVC Controller?

122

Eu tenho uma solicitação GET que envia uma data no formato AAAA-MM-DD para um Spring Controller. O código do controlador é o seguinte:

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

A solicitação é enviada corretamente enquanto eu estou verificando com o Firebug. Eu recebo o erro:

Status HTTP 400: A solicitação enviada pelo cliente estava sintaticamente incorreta.

Como posso fazer o controlador aceitar esse formato de data? Por favor ajude. O que estou fazendo de errado?

LittleLebowski
fonte

Respostas:

250

Ok, eu resolvi. Escrevê-lo para qualquer um que possa estar cansado após um dia inteiro de codificação ininterrupta e perder uma coisa tão boba.

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

Sim, é simples. Basta adicionar a anotação DateTimeFormat.

LittleLebowski
fonte
18
Eu ia escrever uma resposta, mas você me venceu. Você também pode usar @DateTimeFormat (iso = ISO.DATE), que é o mesmo formato. BTW, se você pode sugerir que você use a biblioteca Joda DateTime. O Spring suporta muito bem.
Luciano
A resposta é geralmente ok, MAS! Existe uma maneira de configurá-lo como padrão para o Spring? É um pouco exagerado para colocar @DateTimeFormatem cada controlador que você tem ...
thorinkor
3
@Luciano é claro que você pode fazer @DateTimeFormat (iso = ISO.DATE_TIME) bem
kiedysktos
2
@thorinkor No Spring Boot, você pode definir o spring.mvc.date-formatatributo application.propertiesou adicionar beans que implementam a org.springframework.formatinterface (estender org.springframework.format.datetime.DateFormatteré provavelmente o caminho a percorrer). No Boot Spring não, você pode usar @Overrideo addFormattersmétodo WebMvcConfigurerAdaptere adicionar seus beans de implementação do Formatador.
UTF_or_Death 17/02
10

Isto é o que eu fiz para obter a data formatada do front end

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

Você pode usá-lo para obter o que deseja.

AbdusSalam
fonte
11
Não entendi. Qual é o sentido de adicionar @ DateTimeFormat a @ PathVariable se você receber dateString como String, não como Date?
ILya Cyclone 27/11
7

... ou você pode fazê-lo da maneira certa e ter uma regra coerente para serialização / desserialização de datas em todo o aplicativo. coloque isso em application.properties:

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

A solução abaixo funciona perfeitamente para o aplicativo de inicialização por mola.

Controlador:

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

Portanto, no chamador (no meu caso, é um fluxo da Web), precisamos passar a data e hora neste formato ( "aaaa-MM-dd HH: mm: ss" ).

Lado do chamador:

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

Repositório:

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

Felicidades!!

Aman Goel
fonte
2

Se você deseja usar um PathVariable, pode usar um método de exemplo abaixo (todos os métodos são e fazem o mesmo):

//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
fonte