Integración de Spring Boot 2.6+ con Swagger2
- Integración con versiones anteriores a Spring Boot 2.6
1-1: Configuración en la clase principal de Spring Boot Esta configuración permite ver directamente las rutas al iniciar el proyecto, facilitendo pruebas directas:
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
import java.net.InetAddress;
import java.net.UnknownHostException;
@Slf4j
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) throws UnknownHostException {
ConfigurableApplicationContext appContext = SpringApplication.run(DemoApplication.class, args);
Environment environment = appContext.getEnvironment();
String localIp = InetAddress.getLocalHost().getHostAddress();
String puerto = environment.getProperty("server.port");
String contexto = environment.getProperty("server.servlet.context-path");
log.info("\n----------------------------------------------------------\n\t" +
"Aplicación Demo está corriendo! URLs de acceso:\n\t" +
"Local: \t\thttp://localhost:" + puerto + contexto + "/\n\t" +
"Externo: \thttp://" + localIp + ":" + puerto + contexto + "/\n\t" +
"Interfaz swagger: \thttp://" + localIp + ":" + puerto + contexto + "/swagger-ui.html\n\t" +
"Documentación: \t\thttp://" + localIp + ":" + puerto + contexto + "/doc.html\n" +
"----------------------------------------------------------");
}
}
1-2: Clase de configuración de Swagger
package com.demo.config;
import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;
@Configuration
@EnableSwagger2
public class DocumentacionConfig {
@Bean
public Docket construirApiRest() {
ParameterBuilder parametroToken = new ParameterBuilder();
List<Parameter> parametros = new ArrayList<>();
parametroToken.name("Authorization-Token").description("Token de autenticación").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
parametros.add(parametroToken.build());
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(informacionApi())
.select()
.apis(RequestHandlerSelectors.basePackage("com.demo.controlador"))
.apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build()
.globalOperationParameters(parametros);
}
private ApiInfo informacionApi() {
return new ApiInfoBuilder()
.title("API Documentación Servicio Backend Demo")
.description("Estilo de interfaz RESTful")
.termsOfServiceUrl("http://www.ejemplo.com/")
.version("1.0")
.build();
}
}
1-3: Configuración en archivo YAML o properties
server:
port: 8080
servlet:
context-path: /demoproject
spring:
mvc:
pathmatch:
matching-strategy: ANT_PATH_MATCHER
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/basededatos?characterEncoding=utf8&useSSL=false&autoReconnect=true
username: usuario
password: contraseña
mybatis:
type-aliases-package: com.demo.entidad
mapper-locations: classpath:mapper/*.xml
spring:
web:
resources:
static-locations: classpath:/templates/,classpath:/META-INF/resources/,classpath:/resources/
thymeleaf:
cache: false
1-4: Configuración del archivo POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.1</version>
</parent>
<groupId>com.demo</groupId>
<artifactId>proyectodemo</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Dependencias de Swagger -->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.5.21</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.9.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
1-5: Protección de doucmentación con autenticación Para proteger la documentación de accesos no autorizados, se puede implementar autenticación básica.
1-6: Activación de interfaz mejorada Agregar la dependencia ya mencionada para habilitar la interfaz bootstrap.
1-7: Actualización de la clase de configuración
@Configuration
@EnableSwagger2
@EnableSwaggerBootstrapUI
public class DocumentacionConfig {
// Configuración existente...
}
1-8: Configuración de credenciales en YAML
swagger:
basic:
enable: true
username: administrador
password: contraseñasegura
1-9: Anotaciones comunes de Swagger
En clases controladoras:
@Api(tags = "Gestión de Usuarios")
En métodos de controladores:
@ApiOperation(value = "Obtener usuario por ID", notes = "Recupera un usuario específico")
En parámetros de métodos:
@ApiParam(value = "Identificador único", required = true)
Ejemplo cmopleto:
@ApiOperation(value = "Buscar por identificador")
@GetMapping(value = {"/buscar/{identificador}"})
public ResultadoBusqueda encontrarPorId(
@ApiParam(value = "ID principal", required = true)
@PathVariable String identificador) {
EntidadDatos entidad = servicio.obtenerPorId(identificador);
return ResultadoBusqueda.construir(ResultadoBusqueda.EXITO, "Consulta exitosa", entidad);
}
Parámetros implícitos:
@ApiImplicitParams({
@ApiImplicitParam(name="telefono",value="Número de contacto",required=true,paramType="query",dataType="Long"),
@ApiImplicitParam(name="clave",value="Contraseña",required=true,paramType="query",dataType="String")
})
Respuestas documentadas:
@ApiResponses({
@ApiResponse(code = 200, message = "Operación exitosa"),
@ApiResponse(code = 401, message = "No autorizado"),
@ApiResponse(code = 404, message = "Recurso no encontrado")
})
En clases modelo:
@ApiModel(value="UsuarioModelo", description="Representación de usuario")
En propiedades de modelos:
@ApiModelProperty(value = "Estado" ,required = true, example = "activo")
- Integración con Spring Boot 2.6+
2-1: Configuración actualizada del POM
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.6</version>
</parent>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
2-2: Clase de configuración actualizada
@Configuration
@EnableSwagger2
@Import(BeanValidatorPluginsConfiguration.class)
public class ConfiguracionDocumentacion implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry gestor) {
gestor.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
gestor.addResourceHandler("doc.html")
.addResourceLocations("classpath:/META-INF/resources/");
gestor.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
@Bean(value = "apiPorDefecto")
public Docket apiPorDefecto() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(infoApi())
.select()
.apis(RequestHandlerSelectors.basePackage("com.demo.controladores"))
.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build()
.securitySchemes(Collections.singletonList(esquemaSeguridad()))
.securityContexts(contextosSeguridad())
.globalOperationParameters(configurarTokenEncabezado());
}
@Bean
SecurityScheme esquemaSeguridad() {
return new ApiKey("Authorization-Token", "Authorization-Token", "header");
}
private List<Parameter> configurarTokenEncabezado() {
ParameterBuilder builder = new ParameterBuilder();
List<Parameter> lista = new ArrayList<>();
builder.name("Authorization-Token")
.description("Token de autorización")
.modelRef(new ModelRef("string"))
.parameterType("header")
.required(false)
.build();
lista.add(builder.build());
return lista;
}
private ApiInfo infoApi() {
return new ApiInfoBuilder()
.title("Documentación API Demo Backend")
.version("1.0")
.description("Interfaz API Backend")
.contact(new Contact("Organización", "https://ejemplo.com", "contacto@ejemplo.com"))
.license("Licencia Apache 2.0")
.licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
.build();
}
private List<SecurityContext> contextosSeguridad() {
return new ArrayList(
Collections.singleton(SecurityContext.builder()
.securityReferences(autenticacionPorDefecto())
.forPaths(PathSelectors.regex("^(?!auth).*$"))
.build())
);
}
private List<SecurityReference> autenticacionPorDefecto() {
AuthorizationScope scope = new AuthorizationScope("global", "accesoCompleto");
AuthorizationScope[] scopes = new AuthorizationScope[1];
scopes[0] = scope;
return new ArrayList(
Collections.singleton(new SecurityReference("Authorization-Token", scopes)));
}
}
2-3: Solución de compatibilidad de patrones de ruta En Spring Boot 2.6+, agregar esta configuración en application.yml:
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
2-4: Configuración de autenticación para knife4j
knife4j:
enable: true
production: false
basic:
enable: true
username: admin
password: contraseña123
- Consideración importante sobre Spring Security Cuando el proyecto incluye Spring Security junto con autenticación de Swagger, pueden surgir conflictos que causen fallos de autenticación. En este caso, se debe ajustar la configuración de seguridad para permitir el acceso a los recursos de Swagger.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>