Generación de Documentación de API con Swagger 2 en Spring Boot

Swagger es una herramienta poderosa para la especificación y documentación de interfaces de programación de aplicaciones (API) RESTful. Su integración es notablemente sencilla y ofrece no solo la consulta de la documentación en línea, sino también la capacidad de probar los endpoints de la API directamente desde el navegador. Esta flexibilidad hace que Swagger sea una elección excelente para construir APIs con un estilo REST, aportando elegancia y claridad.

Inclusión de Dependencias

Para añadir la funcionalidad de Swagger a un proyecto Spring Boot, incorpore las siguientes dependencias en el archivo pom.xml de su aplicación:

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.8.0</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.8.0</version>
</dependency>

Clase de Configuración

La configuración de Swagger se centraliza en una clase marcada con @Configuration. Esta clase define un bean Docket, el cual es crucial para personalizar cómo Swagger escaneará su aplicación y generará la documentación.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class ConfiguracionDocumentacionApi {
  
    // Se puede controlar la habilitación de Swagger mediante una propiedad externa
    private final Boolean habilitarDocumentacion = true;

    @Bean
    public Docket definirApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(obtenerInfoApi())
                .enable(habilitarDocumentacion) // Habilitar/deshabilitar Swagger
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.ejemplo.aplicacion.controladores")) // Paquete de los controladores
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo obtenerInfoApi() {
        return new ApiInfoBuilder()
                .title("API de Gestión de Productos")
                .description("Documentación completa para la API de productos.")
                .version("1.0")
                .contact(new Contact("Equipo Tech", "https://www.ejemplo.com", "contacto@ejemplo.com"))
                .build();
    }
}

La anotación @Configuration indica que la clase contiene definiciones de beans de Spring. @EnableSwagger2 activa la funcionalidad de Swagger. El método definirApi() construye el bean Docket, estableciedno la información general de la API (como el título y la descripción) y especificando los paquetes base donde se encuentran los controladores a ser documentados por Swagger.

Anotaciones para la Generación de Documentos

Swagger utiliza un conjunto de anotaciones para declarar qué interfaces deben ser documentadas y con qué detalles. Estas anotaciones permiten especiifcar el nombre de la API, los métodos de solicitud, los parámetros, la información de retorno, y más:

  • @Api: Describe la función de un controladro o un recurso API completo.
  • @ApiOperation: Proporciona detalles sobre una operación específica (un método de la API).
  • @ApiParam: Documenta un parámetro individual de un método.
  • @ApiModel: Se utiliza para describir un modelo de datos (DTO o entidad) que se usa en la API.
  • @ApiModelProperty: Describe una propiedad específica dentro de un modelo de datos @ApiModel.
  • @ApiResponse / @ApiResponses: Documenta las posibles respuestas HTTP de una operación.
  • @ApiImplicitParam / @ApiImplicitParams: Describe parámetros que no están directamente en la firma del método, como cabeceras o parámetros de formulario.
  • @ApiIgnore: Permite excluir una clase o un método de la documentación de Swagger.

Considere el siguiente ejemplo de un controlador RESTful para la gestión de usuarios, ilustrando el uso de estas anotaciones:

package com.ejemplo.aplicacion.controladores;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

@Api(tags = "Servicio de Usuarios")
@RestController
@RequestMapping("/api/v2/usuarios")
public class GestorUsuariosController {

    // Simulación de un repositorio de datos en memoria
    private final Map<Long, EntidadUsuario> baseDeDatosUsuarios = new ConcurrentHashMap<>();
    private final AtomicLong generadorId = new AtomicLong();

    // Clase interna que representa la entidad de Usuario
    static class EntidadUsuario {
        private Long id;
        private String nombreCompleto;
        private int edad;

        public EntidadUsuario() {}
        public EntidadUsuario(Long id, String nombreCompleto, int edad) {
            this.id = id;
            this.nombreCompleto = nombreCompleto;
            this.edad = edad;
        }

        public Long getId() { return id; }
        public void setId(Long id) { this.id = id; }
        public String getNombreCompleto() { return nombreCompleto; }
        public void setNombreCompleto(String nombreCompleto) { this.nombreCompleto = nombreCompleto; }
        public int getEdad() { return edad; }
        public void setEdad(int edad) { this.edad = edad; }
    }

    @ApiOperation(value = "Obtener listado de usuarios", notes = "Recupera una colección de todos los usuarios registrados en el sistema.")
    @GetMapping
    public ResponseEntity<List<EntidadUsuario>> obtenerTodosLosUsuarios() {
        return new ResponseEntity<>(new ArrayList<>(baseDeDatosUsuarios.values()), HttpStatus.OK);
    }

    @ApiOperation(value = "Registrar nuevo usuario", notes = "Crea un nuevo registro de usuario en la base de datos.")
    @ApiImplicitParam(name = "usuarioNuevo", value = "Objeto EntidadUsuario con los detalles del nuevo usuario", required = true, dataType = "EntidadUsuario", paramType = "body")
    @PostMapping
    public ResponseEntity<String> crearUsuario(@RequestBody EntidadUsuario usuarioNuevo) {
        if (usuarioNuevo.getId() == null) {
            usuarioNuevo.setId(generadorId.incrementAndGet());
        }
        baseDeDatosUsuarios.put(usuarioNuevo.getId(), usuarioNuevo);
        return new ResponseEntity<>("Usuario '" + usuarioNuevo.getNombreCompleto() + "' registrado con ID: " + usuarioNuevo.getId(), HttpStatus.CREATED);
    }

    @ApiOperation(value = "Buscar usuario por identificador", notes = "Obtiene los datos de un usuario específico utilizando su ID único.")
    @ApiImplicitParam(name = "identificador", value = "ID del usuario a buscar", required = true, dataType = "Long", paramType = "path")
    @GetMapping("/{identificador}")
    public ResponseEntity<EntidadUsuario> buscarUsuarioPorId(@PathVariable("identificador") Long identificador) {
        EntidadUsuario usuario = baseDeDatosUsuarios.get(identificador);
        if (usuario != null) {
            return new ResponseEntity<>(usuario, HttpStatus.OK);
        }
        return new ResponseEntity<>(HttpStatus.NOT_FOUND);
    }

    @ApiOperation(value = "Actualizar datos de usuario", notes = "Modifica la información de un usuario existente basándose en su ID.")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "identificador", value = "ID del usuario a modificar", required = true, dataType = "Long", paramType = "path"),
            @ApiImplicitParam(name = "datosActualizados", value = "Objeto EntidadUsuario con la nueva información", required = true, dataType = "EntidadUsuario", paramType = "body")
    })
    @PutMapping("/{identificador}")
    public ResponseEntity<String> actualizarUsuario(@PathVariable("identificador") Long identificador, @RequestBody EntidadUsuario datosActualizados) {
        EntidadUsuario existente = baseDeDatosUsuarios.get(identificador);
        if (existente != null) {
            existente.setNombreCompleto(datosActualizados.getNombreCompleto());
            existente.setEdad(datosActualizados.getEdad());
            baseDeDatosUsuarios.put(identificador, existente);
            return new ResponseEntity<>("Usuario con ID " + identificador + " actualizado correctamente.", HttpStatus.OK);
        }
        return new ResponseEntity<>("Usuario con ID " + identificador + " no encontrado para actualizar.", HttpStatus.NOT_FOUND);
    }

    @ApiOperation(value = "Eliminar usuario", notes = "Elimina un usuario del sistema por su identificador único.")
    @ApiImplicitParam(name = "identificador", value = "ID del usuario a eliminar", required = true, dataType = "Long", paramType = "path")
    @DeleteMapping("/{identificador}")
    public ResponseEntity<String> eliminarUsuario(@PathVariable("identificador") Long identificador) {
        if (baseDeDatosUsuarios.containsKey(identificador)) {
            baseDeDatosUsuarios.remove(identificador);
            return new ResponseEntity<>("Usuario con ID " + identificador + " eliminado exitosamente.", HttpStatus.NO_CONTENT);
        }
        return new ResponseEntity<>("Usuario con ID " + identificador + " no encontrado para eliminar.", HttpStatus.NOT_FOUND);
    }

    @ApiIgnore // Esta API será ignorada por Swagger
    @GetMapping("/saludo")
    public String enviarSaludo() {
        return "¡Saludos desde el API de Spring Boot!";
    }
}

Una vez que la aplicación Spring Boot se está ejecutando, la interfaz de usuario interactiva de Swagger UI estará accesible generalmente en la siguiente dirección:

http://localhost:8080/swagger-ui.html

(Asegúrese de modificar el puerto 8080 si su aplicación está configurada para usar uno diferente).

Etiquetas: Spring Boot Swagger REST API Documentación API java

Publicado el 9-10 15:08