Podemos definir perfiles de Spring Boot para que se ejecuten en función del entorno en el que se encuentre la aplicación. Por ejemplo, podemos tener un perfil para desarrollo y otro para producción. Para ello, debemos crear un fichero de propiedades para cada perfil, con el nombre application-{nombre_perfil}.properties
. Por ejemplo, si tenemos un perfil de desarrollo, el fichero se llamará application-dev.properties
. En este fichero, podemos definir las propiedades que queramos, que sobreescribirán a las definidas en el fichero application.properties
. Para activar un perfil, debemos añadir la propiedad spring.profiles.active={nombre_perfil}
en el fichero application.properties
. Si no se define esta propiedad, se ejecutará el perfil por defecto, que es el que no tiene nombre.
De esta manera podemos tener distintos perfiles para distintos entornos, y que se ejecuten en función de la propiedad spring.profiles.active
.
Por ejemplo, si tenemos el siguiente fichero application.properties
:
# PERFIL GLOBAL
## Puerto de la aplicaci�n
# (si has activado https, es por defecto el del SSL)
# Tomamos el puerto de la variable de entorno PORT
server.port=${PORT:6983}
## INDICAMOS EL PERFIL ACTIVO
#Indicamos el perfil por defecto (Base de datos y otros)
# dev: developmet. application-dev.properties
# prod: production. application-prod.properties
spring.profiles.active=dev
Y el siguiente fichero application-dev.properties
:
# PERFIL DE DESARROLLO
# Por ejemplo vamos a meter la base de datos
## Base de datos de desarrollo
# En fichero embebida o en memoria, t� eliges
# spring.datasource.url=jdbc:h2:./productosapirest
spring.datasource.url=jdbc:h2:mem:raquetas
# Usuario y contrase�a de la base de datos
spring.datasource.username=sa
#spring.datasource.password=password
# Habilitamos la consola de H2
http=//localhost:{server.port}/h2-console
# En nuestro caso http://localhost:69680/h2-console
spring.h2.console.enabled=true
# Habilitamos los mensajes sql en el log para ver las consultas
spring.jpa.show-sql=true
# Habilitamos que cargue los datos de prueba en la base de datos
# estos datos los carga del fichero data.sql del directorio resources
spring.jpa.defer-datasource-initialization=true
spring.jpa.hibernate.ddl-auto=create-drop
spring.sql.init.mode=always
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
Y tener el siguiente fichero application-prod.properties
:
# PERFIL DE PRODUCCION
# Por ejemplo vamos a meter la base de datos
spring.datasource.url=jdbc:mysql://localhost:3306/raquetas
spring.datasource.username=root
spring.datasource.password=password
# Driver y opciones
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.ddl-auto=update
Podemos cambiar el perfil llamando a la aplicación con el parámetro --spring.profiles.active={nombre_perfil}
. Por ejemplo, si queremos ejecutar el perfil de producción, ejecutaremos la aplicación de la siguiente manera:
java -jar productosapirest-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod
Los navegadores web implementan una política de seguridad llamada Same Origin Policy, que impide que una página web pueda acceder a recursos de otro dominio. Por ejemplo, si tenemos una página web en el dominio https://www.midominio.com
, no podremos acceder a recursos de otro dominio, como por ejemplo https://www.otrodominio.com
. Esto es así por seguridad, para evitar que una página web pueda acceder a recursos de otro dominio sin nuestro consentimiento.
@Configuration
public class CorsConfig {
/**
* CORS: Configuración más ajustada.
*/
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
// Ajustamos una configuración específica para cada serie de métodos
// Así por cada fuente podemos permitir lo que queremos
// Por ejemplo ene esta configuración solo permitirmos el dominio producto
// Permitimos solo un dominio
// e indicamos los verbos que queremos usar
// Debes probar con uncliente desde ese puerto
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/rest/producto/**")
//.allowedOrigins("http://localhost:6980")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.maxAge(3600);
}
};
}
}
OpenAPI es una especificación para describir APIs REST. Swagger es una herramienta que nos permite generar documentación de APIs REST a partir de la especificación OpenAPI. Para ello, debemos añadir la dependencia de Swagger en nuestro proyecto:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.1.0</version>
</dependency>
El primer paso es configurar Swagger en nuestra aplicación. Para ello, debemos crear una clase de configuración, añadirle los metadatos de Swagger e indicar los endpoints que queremos documentar. Por ejemplo:
@Configuration
class SwaggerConfig {
@Bean
OpenAPI apiInfo() {
return new OpenAPI()
.info(
new Info()
.title("API REST Tenistas Spring Boot 2023")
.version("1.0.0")
.description("API de ejemplo del curso Desarrollo de un API REST con Spring Boot para Profesores/as. 2022/2023")
.termsOfService("https://joseluisgs.dev/docs/license/")
.license(
new License()
.name("CC BY-NC-SA 4.0")
.url("https://joseluisgs.dev/docs/license/")
)
.contact(
new Contact()
.name("José Luis González Sánchez")
.email("[email protected]")
.url("https://joseluisgs.dev")
)
)
.externalDocs(
new ExternalDocumentation()
.description("Repositorio y Documentación del Proyecto y API")
.url("https://github.com/joseluisgs/tenistas-rest-springboot-2022-2023")
);
}
@Bean
GroupedOpenApi httpApi() {
return GroupedOpenApi.builder()
.group("http")
//.pathsToMatch("/api/**") // Todas las rutas
.pathsToMatch("/api/tenistas/**")
//.pathsToMatch("/api/test/**")
.displayName("HTTP-API Tenistas Test")
.build();
}
}
Finalmente podemos acceder a la ruta en: http://localhost:XXXX/swagger-ui/index.html (XXXX es el puerto de nuestra aplicación). Por ejemplo: http://localhost:6980/swagger-ui/index.html
NOTA: No olvides abrir el endpoint de Swagger en el fichero de configuración de Spring Security.
Para ello usaremos las anotaciones
@Operation
: Para documentar un método@Parameter
: Para documentar un parámetro@RequestBody
: Para documentar el cuerpo de una petición@ApiResponse
: Para documentar una respuesta
Un ejemplo de documentación de un método:
@Operation(summary = "Actualiza un Tenista", description = "Actualiza un Tenista dado su id", tags = {"tenistas}"})
@Parameter(name = "id", description = "ID del Tenista", required = true, example = "1")
@ApiResponse(responseCode = "200", description = "Tenista actualizado")
@ApiResponse(responseCode = "404", description = "Tenista no encontrado")
@ApiResponse(responseCode = "400", description = "Tenista no válido")
@PutMapping("/{id}")
public ResponseEntity<TenistaResponseDto> putTenista(
@PathVariable Long id,
@Valid @RequestBody TenistaRequestDto tenista
) {
log.info("putTenista");
return ResponseEntity.ok(
tenistaMapper.toResponse(tenistasService.update(id, tenistaMapper.toModel(tenista)))
);
}
Finalmente entrando en la ruta de Swagger podemos ver la documentación de nuestros endpoints.
Para crear un JAR de nuestra aplicación, debemos ejecutar el comando de Maven:
mvn clean package
Te recuerdo que estos comandos los puedes ejecutar desde el propio IDE, en la pestaña de Maven. Además pasan los test, y si no quieres que los ejecute, puedes usar el comando mvn clean package -DskipTests
.
Si quieres crear un deploy de tu aplicación basado en un perfil, puedes usar el comando mvn clean package -DskipTests -Pprod
. Esto creará un JAR en la carpeta target
de tu proyecto.
mvn clean package -DskipTests -Pprod
Ejecutamos el JAR:
java -jar productosapirest-0.0.1-SNAPSHOT.jar
Podemos crear un contenedor Docker de nuevo usando Maven: mvn spring-boot:build-image
. De nuevo pasan los test y si no quieres que los ejecute, puedes usar el comando mvn spring-boot:build-image -DskipTests
.
mvn spring-boot:build-image -DskipTests
Si todo va bien tendremos el mesanje BUILD SUCCESS
y podremos ver la imagen creada con el comando docker images
.
[INFO] Successfully built image 'docker.io/library/tenistas-profesores:0.0.1-SNAPSHOT'
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 02:43 min
[INFO] Finished at: 2023-05-08T13:49:31+02:00
[INFO] ------------------------------------------------------------------------
Usando docker images podemos ver la imagen creada:
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
paketobuildpacks/run base-cnb dd974fc40e68 7 days ago 90.6MB
paketobuildpacks/builder base 7f032baea455 43 years ago 1.37GB
tenistas-profesores 0.0.1-SNAPSHOT 5a4d54b4e8c1 43 years ago 319MB
Ahora podemos ejecutar el contenedor con el comando docker run -p 6980:6980 tenistas-profesores:0.0.1-SNAPSHOT
. Si todo va bien, podremos acceder a nuestra aplicación en http://localhost:6980/api/tenistas.
docker run -p 6980:6980 tenistas-profesores:0.0.1-SNAPSHOT
Puedes consultar otras formas aquí.