Manejo de datos de formulario codificados por URL en Spring REST

DESCANSO Arriba

Acabo de anunciar el nuevo curso Learn Spring , centrado en los fundamentos de Spring 5 y Spring Boot 2:

>> VER EL CURSO

1. Información general

Para un usuario final, el proceso de envío de formularios es conveniente y, hasta cierto punto, equivale a ingresar datos y hacer clic en un botón de envío. Sin embargo, desde una perspectiva de ingeniería, se necesita un mecanismo de codificación para enviar y recibir de manera confiable estos datos desde el lado del cliente al lado del servidor para el procesamiento de back-end.

Para el alcance de este tutorial, nos centraremos en crear un formulario que envíe sus datos como tipo de contenido application / x-www-form-urlencoded en una aplicación web Spring.

2. Codificación de datos de formulario

El método HTTP más utilizado para el envío de formularios es POST. Sin embargo, para envíos de formularios idempotentes, también podemos usar el método HTTP GET. Y la forma de especificar el método es a través del atributo de método del formulario.

Para los formularios que utilizan el método GET, todos los datos del formulario se envían como parte de la cadena de consulta. Pero, si usamos el método POST, sus datos se envían como parte del cuerpo de la solicitud HTTP.

Además, en el último caso, también podemos especificar la codificación de datos con el atributo enctype del formulario , que puede tomar dos valores, a saber, application / x-www-form-urlencoded y multipart / form-data .

2.1. Aplicación de tipo de medio / x-www-form-urlencoded

Los formularios HTML tienen un valor predeterminado de application / x-www-form-urlencoded para el atributo enctype, ya que se encarga de los casos de uso básicos donde los datos son completamente texto. Sin embargo, si nuestro caso de uso implica datos de archivo de soporte, tendremos que anularlo con un valor de multipart / form-data .

Básicamente, envía los datos del formulario como pares clave-valor separados por un carácter comercial (&). Además, la clave y el valor respectivos se separan con el signo igual (=). Además, todos los caracteres reservados y no alfanuméricos se codifican mediante codificación porcentual.

3. Envío de formularios en el navegador

Ahora que tenemos nuestros conceptos básicos cubiertos, sigamos adelante y veamos cómo podemos manejar los datos de formulario codificados en URL para un caso de uso simple de envío de comentarios en una aplicación web Spring.

3.1. Modelo de dominio

Para nuestro formulario de comentarios, necesitamos capturar el identificador de correo electrónico del remitente junto con el comentario. Entonces, creemos nuestro modelo de dominio en una clase de Feedback :

public class Feedback { private String emailId; private String comment; }

3.2. Crear formulario

Para usar una plantilla HTML simple para crear nuestro formulario web dinámico, necesitaremos configurar Thymeleaf en nuestro proyecto. Después de esto, estamos listos para agregar un punto final / comentarios GET que servirá como vista de comentarios para el formulario :

@GetMapping(path = "/feedback") public String getFeedbackForm(Model model) { Feedback feedback = new Feedback(); model.addAttribute("feedback", feedback); return "feedback"; }

Tenga en cuenta que estamos utilizando la retroalimentación como atributo del modelo para capturar la entrada del usuario. A continuación, creemos la vista de comentarios en la plantilla feedback.html :

Por supuesto, no necesitamos especificar explícitamente el atributo enctype ya que elegirá el valor predeterminado de application / x-www-form-urlencoded .

3.3. Flujo PRG

Dado que aceptamos la entrada del usuario a través del formulario de comentarios del navegador, debemos implementar el flujo de trabajo de envío POST / REDIRECT / GET (PRG) para evitar envíos duplicados .

Primero, implementemos el punto final / web / feedback de POST que actuará como el controlador de acciones para el formulario de comentarios:

@PostMapping( path = "/web/feedback", consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE}) public String handleBrowserSubmissions(Feedback feedback) throws Exception { // Save feedback data return "redirect:/feedback/success"; }

A continuación, podemos implementar el punto final de redirección / comentarios / éxito que atiende una solicitud GET:

@GetMapping("/feedback/success") public ResponseEntity getSuccess() { return new ResponseEntity("Thank you for submitting feedback.", HttpStatus.OK); }

Para validar la funcionalidad del flujo de trabajo de envío de formularios en un navegador, visitemos localhost: 8080 / feedback :

Finalmente, también podemos inspeccionar que los datos del formulario se envían en el formulario codificado en URL:

emailId=abc%40example.com&comment=Sample+Feedback

4. Solicitudes ajenas al navegador

A veces, es posible que no tengamos un cliente HTTP basado en navegador. En cambio, nuestro cliente podría ser una utilidad como cURL o Postman. En tal caso, no necesitamos el formulario web HTML. En su lugar, podemos implementar un punto final / feedback que atienda la solicitud POST:

@PostMapping( path = "/feedback", consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE}) public ResponseEntity handleNonBrowserSubmissions(@RequestBody Feedback feedback) throws Exception { // Save feedback data return new ResponseEntity("Thank you for submitting feedback", HttpStatus.OK); }

En ausencia del formulario HTML en nuestro flujo de datos, no necesariamente necesitamos implementar el patrón PRG. Sin embargo, debemos especificar que el recurso acepta el tipo de medio APPLICATION_FORM_URLENCODED_VALUE .

Finalmente, podemos probarlo con una solicitud cURL:

curl -X POST \ //localhost:8080/feedback \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d 'emailId=abc%40example.com&comment=Sample%20Feedback'

4.1. FormHttpMessageConverter Conceptos básicos

Una solicitud HTTP que envía datos application / x-www-form-urlencoded debe especificar esto en el encabezado Content-Type . Internamente, Spring usa la clase FormHttpMessageConverter para leer estos datos y vincularlos con el parámetro del método.

In cases where our method parameter is of a type MultiValueMap, we can use either the @RequestParam or @RequestBody annotation to bind it appropriately with the body of the HTTP request. That's because the Servlet API combines the query parameters and form data into a single map called parameters, and that includes automatic parsing of the request body:

@PostMapping( path = "/feedback", consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE}) public ResponseEntity handleNonBrowserSubmissions( @RequestParam MultiValueMap paramMap) throws Exception { // Save feedback data return new ResponseEntity("Thank you for submitting feedback", HttpStatus.OK); }

However, for a method parameter of type other than MultiValueMap, such as our Feedback domain object, we must use only the @RequestBody annotation.

5. Conclusion

En este tutorial, aprendimos brevemente sobre la codificación de datos de formularios en formularios web. También exploramos cómo manejar datos codificados en URL para solicitudes HTTP de navegador y no navegador mediante la implementación de un formulario de comentarios en una aplicación web Spring Boot.

Como siempre, el código fuente completo del tutorial está disponible en GitHub.

DESCANSO inferior

Acabo de anunciar el nuevo curso Learn Spring , centrado en los fundamentos de Spring 5 y Spring Boot 2:

>> VER EL CURSO