@RequestParam no Spring MVC manipulando parâmetros opcionais

186

É possível para um controlador Spring lidar com ambos os tipos de solicitações?

1) http://localhost:8080/submit/id/ID123432?logout=true

2) http://localhost:8080/submit/id/ID123432?name=sam&password=543432

Se eu definir um único controlador do tipo:

 @RequestMapping (value = "/submit/id/{id}", method = RequestMethod.GET,   
 produces="text/xml")
public String showLoginWindow(@PathVariable("id") String id,
                              @RequestParam(value = "logout", required = false) String logout,
                              @RequestParam("name") String username,
                              @RequestParam("password") String password,
                              @ModelAttribute("submitModel") SubmitModel model,
                              BindingResult errors) throws LoginException {...}

a solicitação HTTP com "logout" não é aceita.

Se eu definir dois controladores para manipular cada solicitação separadamente, o Spring reclamará com a exceção "Já existe o método do bean 'Controller' ... mapeado".

luksmir
fonte
2
Leia este artigo: codeflex.co/…
ybonda

Respostas:

224

Você precisa dar required = falsepara namee passwordparâmetros de solicitação também. Isso porque, quando você fornece apenas o logoutparâmetro, ele realmente espera namee, passwordainda assim, eles são obrigatórios.

Funcionou quando você acabou de dar namee passwordporque logoutnão era um parâmetro obrigatório, graças ao required = falsejá dado logout.

SudoRahul
fonte
168

Como parte de Spring 4.1.1agora em diante, agora você tem suporte total ao Java 8 Optional( tíquete original ), portanto, em seu exemplo, as duas solicitações passarão pelo seu ponto de extremidade de mapeamento único, desde que você substitua required=falsepor Opcional para o logout de 3 parâmetros, nome e senha:

@RequestMapping (value = "/submit/id/{id}", method = RequestMethod.GET,   
 produces="text/xml")
public String showLoginWindow(@PathVariable("id") String id,
                              @RequestParam(value = "logout") Optional<String> logout,
                              @RequestParam("name") Optional<String> username,
                              @RequestParam("password") Optional<String> password,
                              @ModelAttribute("submitModel") SubmitModel model,
                              BindingResult errors) throws LoginException {...}
dimitrisli
fonte
2
@VibhavChaddha, você pode usar algo assim: if (idOfUser.isPresent ()) {System.out.println ("idOfUser:" + idOfUser.get ()); }
Cassio Seffrin
10
Aviso Intellij: 'Opcional <Long>' usado como tipo para o parâmetro 'requestTimelineStart' menos ... (Strg + F1) Informações de inspeção: Informa qualquer uso de java.util.Optional <T>, java.util.OptionalDouble, java. util.OptionalInt, java.util.OptionalLong ou com.google.common.base.Optional como o tipo de um campo ou parâmetro. O opcional foi projetado para fornecer um mecanismo limitado para os tipos de retorno do método de biblioteca, onde era necessário haver uma maneira clara de representar "nenhum resultado". O uso de um campo com o tipo java.util.Optional também é problemático se a classe precisar ser serializável, o que java.util.Optional não é.
PeMa
Esta deve ser a nova resposta correta com o Java 8, acredito.
java-addict301
40

Crie 2 métodos que lidam com os casos. Você pode instruir a @RequestMappinganotação a levar em consideração determinados parâmetros ao mapear a solicitação. Dessa forma, você pode dividir isso perfeitamente em 2 métodos.

@RequestMapping (value="/submit/id/{id}", method=RequestMethod.GET, 
                 produces="text/xml", params={"logout"})
public String handleLogout(@PathVariable("id") String id, 
        @RequestParam("logout") String logout) { ... }

@RequestMapping (value="/submit/id/{id}", method=RequestMethod.GET, 
                 produces="text/xml", params={"name", "password"})
public String handleLogin(@PathVariable("id") String id, @RequestParam("name") 
        String username, @RequestParam("password") String password, 
        @ModelAttribute("submitModel") SubmitModel model, BindingResult errors) 
        throws LoginException {...}
M. Deinum
fonte
1
o que acontecerá quando alguém passar logout, nome e senha para o URL? Basta ler a documentação, ela diz que !myParam style expressions indicate that the * specified parameter is not supposed to be present in the request.tem que tentar.
portador do anel
2
Ele encontrará a melhor correspondência, provavelmente tentará usar o handleLoginresto, além de fornecer uma exceção informando que nenhum mapeamento pode ser encontrado.
M. Deinum 28/09/16
3
Apenas uma observação: do ponto de vista da segurança, o logoff deve aceitar apenas solicitações POST, portanto deve haver 2 métodos e não faz sentido manter o URL da mesma forma.
FlasH de Ru