@RequestParam en Spring MVC manejando parámetros opcionales

186

¿Es posible que un controlador Spring maneje ambos tipos de solicitudes?

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

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

Si defino un solo controlador del 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 {...}

no se acepta la solicitud HTTP con "cerrar sesión".

Si defino dos controladores para manejar cada solicitud por separado, Spring se queja con la excepción "Ya hay un método de bean 'Controlador' ... mapeado".

luksmir
fuente
2
Lea este artículo: codeflex.co/…
ybonda

Respuestas:

224

Es necesario dar required = falsea namey passwordparámetros de la petición así. Esto se debe a que, cuando proporciona solo el logoutparámetro, en realidad espera namey password, además de que todavía es obligatorio.

Funcionó cuando acaba de dar namey passwordporque logoutno era un parámetro obligatorio gracias a que required = falseya se dio logout.

SudoRahul
fuente
168

Como parte en Spring 4.1.1adelante, ahora tiene soporte completo de Java 8 Optional( boleto original ), por lo tanto, en su ejemplo, ambas solicitudes irán a través de su punto final de mapeo único siempre que lo reemplace required=falsecon Opcional para su cierre de sesión de 3 parámetros, nombre, contraseña:

@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
fuente
2
@VibhavChaddha puede usar algo como esto: if (idOfUser.isPresent ()) {System.out.println ("idOfUser:" + idOfUser.get ()); }
Cassio Seffrin
10
Advertencia de Intellij: 'Opcional <Long>' usado como tipo para el parámetro 'requestTimelineStart' less ... (Strg + F1) Información de inspección: Informa cualquier uso de java.util.Optional <T>, java.util.OptionalDouble, java. util.OptionalInt, java.util.OptionalLong o com.google.common.base.Optional como el tipo de campo o parámetro. Opcional se diseñó para proporcionar un mecanismo limitado para los tipos de retorno de métodos de biblioteca en los que debía existir una forma clara de representar "sin resultado". Usar un campo con el tipo java.util.Optional también es problemático si la clase necesita ser serializable, que java.util.Optional no lo es.
PeMa
Esta debería ser la nueva respuesta correcta con Java 8, creo.
java-addict301
40

Crea 2 métodos que manejan los casos. Puede indicar a la @RequestMappinganotación que tenga en cuenta ciertos parámetros al asignar la solicitud. De esa manera, puedes dividir esto en 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
fuente
1
¿Qué pasará cuando alguien pase el cierre de sesión, el nombre y la contraseña a la URL? Acabo de leer la documentación, dice que !myParam style expressions indicate that the * specified parameter is not supposed to be present in the request.tengo que probar.
portador del anillo
2
Encontrará la mejor coincidencia, probablemente intentará usar la handleLoginotra, dará una excepción que indica que no se puede encontrar la asignación.
M. Deinum
3
Solo una nota: desde la perspectiva de seguridad, el cierre de sesión solo debe aceptar solicitudes POST, por lo que debe haber 2 métodos y no tiene sentido mantener su URL igual.
FlasH de Ru