Estás viendo una versión antigua de esta página. Ve a la versión actual.

Comparar con el actual Ver el historial de la página

« Anterior Versión 6 Siguiente »

Cuando implementamos nuestros servicios REST que devuelven objetos de la lógica de negocio de nuestra aplicación se pueden dar dos casos: los objetos que devolvemos son entidades, nuestros objetos no son entidades.

Si los objetos son entidades, estaremos exponiendo todos sus datos y en muchos casos no querremos enviarlo todo. Por ejemplo si guardase en una entidad los valores usuario y password, no debemos enviar dicho password como respuesta del JSON. Ante esta situación podríamos usar la anotación @JsonIgnore que fuerza que ese campo no se envíe, pero se aplicaría a todos los casos.

Si a partir de una entidad, según el caso, quisiéramos mandar un conjunto de campos diferente, la anotación @JsonIngore no es suficiente. En general las buenas prácticas de uso de servicios REST nos indican que siempre devolvamos objetos DTO y no expongamos las entidades de negocio, por tanto debemos seguir esta directriz.

Para evitar que la generación de la respuesta como DTO añada complejidad a nuestro código, es recomendable usar elementos de la programación funcional disponibles desde Java8. El modo de proceder debería ser similar al siguiente:

  1. Creamos dentro del paquete model ( por ejemplo: es.um.atica.miaplicacion.model) los objetos DTO que vamos a enviar. Si el proyecto es grande y lo tenemos dividido en módulos tendremos diferentes paquetes model por lo que deberemos crear cada DTO en el que corresponda.
  2. Dentro de nuestras entidades creamos un método toDTO() o varios toXXDTO() (siendo XX un indentificador que aporte valor semántico) que devolverá un objeto del tipo DTO con los datos que requiera de la entidad.
  3. Modificamos nuestro método REST para que, a partir de una lista de entidades, devuelva una lista de DTO, para esto usaremos programación funcional

Método tradicional:

@GetMapping("api/{version}/usuarios")
	public List<Usuario> listarUsuarios() {
		return this.usuarioService.findAll(); //Llamamos al servicio de usuarios que devolverá una lista de todos los usuarios del sistema (son Entidades).
	}


Devolviendo DTO con programación funcional:

@GetMapping("api/{version}/usuarios")
	public List<UsuarioDTO> listarUsuarios() {					
		return  this.usuarioService.findAll().parallelStream().map(Usuario::toDTO).collect(Collectors.toList());
	}


La llamada usando programación funcional hace lo siguiente:

  • this.usuarioService.findAll(): devuelve las entidades igual que con la manera tradicional
  • parallelStream(): Crea un stream para procesar la lista de manera paralela. Si no nos importa el orden los stream paralelos aprovechan la potencia de la programación concurrente para optimizar los recorridos.
  • map(Usuario::toDTO): Esta función cambia cada elemento de la lista por el resultado de ejecutar la expresión Lambda o referencia a método que contiene.
    • Usuario::toDTO: Es una referencia a método que ejecuta el método toDTO() de la clase Usuario para cada valor del stream.
  • collect(Collectors.toList()): Devuelve el resultado de procesar el stream como una lista.
  • Sin etiquetas