0% ont trouvé ce document utile (0 vote)
3 vues26 pages

Cours Springboot Java

Le document présente un cours complet sur Spring Boot, couvrant des sujets allant de l'introduction au framework jusqu'à la création d'une API REST sécurisée. Il inclut des chapitres sur l'injection de dépendances, la persistance avec Spring Data JPA, la validation, la gestion des erreurs, et le déploiement avec Docker. Le cours utilise Java 17+, Maven, et aborde des concepts avancés comme la sécurité avec JWT et les tests.

Transféré par

yz28pcnky4
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
3 vues26 pages

Cours Springboot Java

Le document présente un cours complet sur Spring Boot, couvrant des sujets allant de l'introduction au framework jusqu'à la création d'une API REST sécurisée. Il inclut des chapitres sur l'injection de dépendances, la persistance avec Spring Data JPA, la validation, la gestion des erreurs, et le déploiement avec Docker. Le cours utilise Java 17+, Maven, et aborde des concepts avancés comme la sécurité avec JWT et les tests.

Transféré par

yz28pcnky4
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

SPRING BOOT
Cours Complet en Java
Du projet de base à l'API REST sécurisée en production

Spring Boot 3.x • Java 17+ • Maven • JPA • Security • Docker

Mr Roly — May 2026


COURS COMPLET SPRING BOOT Java • Spring Boot 3.x

TABLE DES MATIÈRES


Chapitre 1 — Introduction à Spring Boot
■ Qu'est-ce que Spring Boot ?
■ Spring vs Spring Boot
■ Architecture et auto-configuration
■ Installation & prérequis
Chapitre 2 — Créer son premier projet
■ Spring Initializr
■ Structure du projet Maven
■ Le fichier [Link]
■ Premier démarrage de l'application
Chapitre 3 — Injection de dépendances & IoC
■ Conteneur IoC
■ Annotations @Component, @Service, @Repository
■ @Autowired et injection par constructeur
■ Beans et cycle de vie
Chapitre 4 — Création d'une API REST
■ @RestController & @RequestMapping
■ GET, POST, PUT, DELETE
■ Gestion des paramètres et du corps
■ Codes HTTP & ResponseEntity
Chapitre 5 — Persistance avec Spring Data JPA
■ ORM et Hibernate
■ Entités et annotations JPA
■ JpaRepository & requêtes
■ Relations entre entités
Chapitre 6 — Validation & Gestion des erreurs
■ Bean Validation (@Valid, @NotNull…)
■ @ExceptionHandler & @ControllerAdvice
■ Réponses d'erreur standardisées
Chapitre 7 — Spring Security & JWT
■ Principes de base de Spring Security
■ Authentification et autorisation
■ Implémentation JWT
■ Sécurisation des endpoints
Chapitre 8 — Tests avec Spring Boot

Spring Boot — Cours Complet | 2026 Page 2


■ @SpringBootTest & @WebMvcTest
■ Mockito et mocking
■ Tests de repository avec H2
Chapitre 9 — Configuration avancée & Profils
■ Profils Spring (dev, prod)
■ Externalization de la configuration
■ @ConfigurationProperties
Chapitre 10 — Déploiement avec Docker
■ Dockerfile pour Spring Boot
■ Docker Compose avec PostgreSQL
■ Variables d'environnement
CHAPITRE 1

Introduction à Spring Boot


1.1 Qu'est-ce que Spring Boot ?
Spring Boot est un framework Java open-source développé par Pivotal (VMware) qui simplifie
radicalement la création d'applications Spring. Il adopte une approche « convention over
configuration » : au lieu de configurer manuellement chaque composant, Spring Boot applique des
configurations par défaut intelligentes qui couvrent la grande majorité des cas d'usage.

Ses objectifs principaux :

• Créer des applications Spring stand-alone exécutables avec un simple java -jar
• Embarquer un serveur HTTP (Tomcat, Jetty, Undertow) directement dans le JAR
• Fournir des dépendances « starter » pré-configurées
• Éliminer la configuration XML et le boilerplate code
• Exposer des métriques de production via Actuator

1.2 Spring vs Spring Boot


Critère Spring Framework Spring Boot

Configuration XML ou Java verbeux Auto-configuration

Serveur web Externe (WAR) Embarqué (JAR)

Démarrage Long (beaucoup de config) Rapide (starter)

Courbe d'apprentissageÉlevée Modérée

Flexibilité Maximale Bonne (overridable)

1.3 Architecture & Auto-configuration


Le cœur de Spring Boot repose sur le mécanisme d'auto-configuration. Lors du démarrage, Spring
Boot analyse le classpath, les beans existants et les propriétés définies pour décider automatiquement
quelles configurations appliquer.

■ L'annotation @SpringBootApplication combine @Configuration, @EnableAutoConfiguration et


@ComponentScan.

@SpringBootApplication
public class MonApplication {
public static void main(String[] args) {
[Link]([Link], args);
}
}

1.4 Installation & Prérequis


Environnement requis :

• Java Development Kit (JDK) 17 ou supérieur


• Maven 3.6+ ou Gradle 7+
• IDE : IntelliJ IDEA (recommandé), Eclipse STS, VS Code
• Optionnel : Docker, Postman

# Vérifier la version Java


java -version
# java version "17.0.x" ...

# Vérifier Maven
mvn -version
# Apache Maven 3.9.x
CHAPITRE 2

Créer son Premier Projet


2.1 Spring Initializr
[Link] est l'outil officiel pour générer un projet Spring Boot en quelques clics. Il suffit de choisir :
le gestionnaire de build (Maven/Gradle), le langage (Java/Kotlin/Groovy), la version de Spring Boot, et
les dépendances (starters) dont vous avez besoin.

■■ Utilisez toujours une version Spring Boot stable (LTS). Évitez les versions SNAPSHOT en production.

Dépendances courantes à sélectionner :

• Spring Web — pour créer des APIs REST


• Spring Data JPA — pour la persistance
• H2 Database — base de données en mémoire pour le dev
• Lombok — pour réduire le boilerplate (getters/setters)
• Spring Boot DevTools — rechargement automatique en dev

2.2 Structure du Projet Maven


mon-projet/
■■■ src/
■ ■■■ main/
■ ■ ■■■ java/com/exemple/monprojet/
■ ■ ■ ■■■ [Link] ← Classe principale
■ ■ ■ ■■■ controller/ ← Couche présentation
■ ■ ■ ■■■ service/ ← Logique métier
■ ■ ■ ■■■ repository/ ← Accès aux données
■ ■ ■ ■■■ model/ ← Entités JPA
■ ■ ■ ■■■ dto/ ← Data Transfer Objects
■ ■ ■■■ resources/
■ ■ ■■■ [Link] ← Configuration
■ ■ ■■■ static/ ← Fichiers statiques
■ ■■■ test/
■ ■■■ java/... ← Tests unitaires
■■■ [Link] ← Dépendances Maven

2.3 Le fichier [Link]


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="[Link]
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
</parent>

<groupId>[Link]</groupId>
<artifactId>mon-projet</artifactId>
<version>1.0.0</version>

<properties>
<[Link]>17</[Link]>
</properties>

<dependencies>
<!-- Spring Web (REST) -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- Spring Data JPA -->


<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<!-- Base de données H2 (dev) -->


<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>

<!-- Lombok -->


<dependency>
<groupId>[Link]</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

<!-- Tests -->


<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

2.4 [Link]
# ■■ Serveur ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
[Link]=8080
[Link]-path=/api

# ■■ Base de données ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


[Link]=jdbc:h2:mem:devdb
[Link]-class-name=[Link]
[Link]=sa
[Link]=

# ■■ JPA / Hibernate ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


[Link]-auto=create-drop
[Link]-sql=true
[Link].format_sql=true

# ■■ Console H2 (dev seulement) ■■■■■■■■■■■■■■■■■■■■■■■


[Link]=true
[Link]=/h2-console

■ En production, utilisez [Link] avec [Link]-auto=validate ou none.


CHAPITRE 3

Injection de Dépendances & IoC


3.1 Le Conteneur IoC
L'Inversion of Control (IoC) est le principe central de Spring. Au lieu que vos objets créent eux-mêmes
leurs dépendances, c'est le conteneur Spring (ApplicationContext) qui les instancie et les injecte. Cela
favorise le couplage faible et la testabilité.

3.2 Annotations Stéréotypes


Spring utilise des annotations pour détecter automatiquement les classes à gérer :

Annotation Rôle Couche

@Component Bean générique géré par Spring Toutes

@Service Logique métier (alias @Component) Service

@Repository Accès aux données + traduction exceptions Repository

@Controller Contrôleur MVC (vues HTML) Présentation

@RestController @Controller + @ResponseBody REST API

@Configuration Classe de configuration Spring Config

3.3 Injection par constructeur (recommandée)


// ■■ Service ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
@Service
public class EtudiantService {

private final EtudiantRepository repository; // final => immuable

// Injection par constructeur (pas besoin de @Autowired en Java moderne)


public EtudiantService(EtudiantRepository repository) {
[Link] = repository;
}

public List<Etudiant> findAll() {


return [Link]();
}
}

// ■■ Avec Lombok (encore plus concis) ■■■■■■■■■■■■■■■■■


@Service
@RequiredArgsConstructor // génère le constructeur automatiquement
public class EtudiantService {

private final EtudiantRepository repository;


public List<Etudiant> findAll() {
return [Link]();
}
}

3.4 @Bean et configuration manuelle


@Configuration
public class AppConfig {

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

@Bean
@Primary
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
[Link](new JavaTimeModule());
[Link](SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
return mapper;
}
}
CHAPITRE 4

Création d'une API REST


4.1 @RestController & @RequestMapping
Un REST Controller est une classe annotée @RestController qui expose des endpoints HTTP.
Chaque méthode est mappée à une URL et un verbe HTTP grâce aux annotations de mapping.

4.2 CRUD complet — Exemple Étudiant


@RestController
@RequestMapping("/etudiants")
@RequiredArgsConstructor
public class EtudiantController {

private final EtudiantService service;

// GET /etudiants — Lister tous les étudiants


@GetMapping
public ResponseEntity<List<EtudiantDTO>> findAll() {
return [Link]([Link]());
}

// GET /etudiants/{id} — Trouver par ID


@GetMapping("/{id}")
public ResponseEntity<EtudiantDTO> findById(@PathVariable Long id) {
return [Link](id)
.map(ResponseEntity::ok)
.orElse([Link]().build());
}

// POST /etudiants — Créer un étudiant


@PostMapping
public ResponseEntity<EtudiantDTO> create(
@Valid @RequestBody EtudiantDTO dto) {
EtudiantDTO created = [Link](dto);
URI location = [Link]("/etudiants/" + [Link]());
return [Link](location).body(created);
}

// PUT /etudiants/{id} — Mettre à jour


@PutMapping("/{id}")
public ResponseEntity<EtudiantDTO> update(
@PathVariable Long id,
@Valid @RequestBody EtudiantDTO dto) {
return [Link]([Link](id, dto));
}
// DELETE /etudiants/{id} — Supprimer
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
[Link](id);
return [Link]().build();
}

// GET /etudiants/search?nom=Dupont — Recherche par paramètre


@GetMapping("/search")
public ResponseEntity<List<EtudiantDTO>> search(
@RequestParam String nom) {
return [Link]([Link](nom));
}
}

4.3 Codes HTTP et ResponseEntity


Code Signification Utilisation

200 OK Succès GET, PUT réussis

201 Created Ressource créée POST réussi

204 No Content Succès sans corps DELETE réussi

400 Bad Request Requête invalide Validation échouée

401 Unauthorized Non authentifié Token manquant/invalide

403 Forbidden Accès refusé Droits insuffisants

404 Not Found Ressource absente ID inexistant

500 Internal Error Erreur serveur Exception non gérée


CHAPITRE 5

Persistance avec Spring Data JPA


5.1 Entité JPA
@Entity
@Table(name = "etudiants")
@Data // Lombok : getters, setters, equals, hashCode, toString
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Etudiant {

@Id
@GeneratedValue(strategy = [Link])
private Long id;

@Column(nullable = false, length = 100)


private String nom;

@Column(nullable = false, unique = true)


private String email;

@Column(name = "date_naissance")
private LocalDate dateNaissance;

@Enumerated([Link])
private Niveau niveau; // LICENCE_1, LICENCE_2, MASTER_1 ...

@ManyToOne(fetch = [Link])
@JoinColumn(name = "filiere_id")
private Filiere filiere;

@CreationTimestamp
@Column(updatable = false)
private LocalDateTime createdAt;

@UpdateTimestamp
private LocalDateTime updatedAt;
}

5.2 Repository — JpaRepository


@Repository
public interface EtudiantRepository extends JpaRepository<Etudiant, Long> {

// Spring Data génère automatiquement les requêtes à partir du nom de la méthode


List<Etudiant> findByNom(String nom);

List<Etudiant> findByNomContainingIgnoreCase(String nom);


Optional<Etudiant> findByEmail(String email);

List<Etudiant> findByNiveau(Niveau niveau);

boolean existsByEmail(String email);

// Requête JPQL personnalisée


@Query("SELECT e FROM Etudiant e WHERE [Link] = :filiere AND [Link] = :niveau")
List<Etudiant> findByFiliereAndNiveau(
@Param("filiere") String filiere,
@Param("niveau") Niveau niveau
);

// Requête SQL native


@Query(value = "SELECT * FROM etudiants ORDER BY RAND() LIMIT :n", nativeQuery = true)
List<Etudiant> findRandom(@Param("n") int n);
}

5.3 Relations entre entités


@OneToMany / @ManyToOne :
// Filière (côté One)
@Entity
public class Filiere {
@Id @GeneratedValue(strategy = [Link])
private Long id;
private String nom;

@OneToMany(mappedBy = "filiere", cascade = [Link], fetch = [Link])


private List<Etudiant> etudiants = new ArrayList<>();
}

// Etudiant (côté Many)


@Entity
public class Etudiant {
// ...
@ManyToOne(fetch = [Link])
@JoinColumn(name = "filiere_id")
private Filiere filiere;
}

■■ Évitez [Link] sur les collections — cela peut provoquer des N+1 queries et des problèmes
de performance.
CHAPITRE 6

Validation & Gestion des Erreurs


6.1 Bean Validation
// DTO avec contraintes de validation
public class EtudiantDTO {
private Long id;

@NotBlank(message = "Le nom est obligatoire")


@Size(min = 2, max = 100, message = "Le nom doit avoir entre 2 et 100 caractères")
private String nom;

@NotBlank(message = "L'email est obligatoire")


@Email(message = "Format d'email invalide")
private String email;

@NotNull(message = "La date de naissance est obligatoire")


@Past(message = "La date de naissance doit être dans le passé")
private LocalDate dateNaissance;

@NotNull
@Min(value = 1, message = "L'ID de filière doit être positif")
private Long filiereId;
}

6.2 Gestionnaire d'exceptions global


@RestControllerAdvice
public class GlobalExceptionHandler {

// Erreurs de validation
@ExceptionHandler([Link])
public ResponseEntity<Map<String, Object>> handleValidation(
MethodArgumentNotValidException ex) {

Map<String, String> errors = new HashMap<>();


[Link]().getFieldErrors().forEach(err ->
[Link]([Link](), [Link]())
);

Map<String, Object> body = [Link](


"status", 400,
"error", "Validation échouée",
"errors", errors,
"timestamp", [Link]()
);
return [Link]().body(body);
}
// Ressource non trouvée
@ExceptionHandler([Link])
public ResponseEntity<Map<String, Object>> handleNotFound(
ResourceNotFoundException ex) {
Map<String, Object> body = [Link](
"status", 404,
"error", [Link](),
"timestamp", [Link]()
);
return [Link](HttpStatus.NOT_FOUND).body(body);
}

// Exception générique
@ExceptionHandler([Link])
public ResponseEntity<Map<String, Object>> handleGeneral(Exception ex) {
Map<String, Object> body = [Link](
"status", 500,
"error", "Erreur interne du serveur",
"timestamp", [Link]()
);
return [Link]().body(body);
}
}

6.3 Exception personnalisée


@ResponseStatus(HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String resource, Long id) {
super(resource + " avec l'ID " + id + " introuvable");
}
}

// Utilisation dans le service


public EtudiantDTO findById(Long id) {
return [Link](id)
.map(this::toDTO)
.orElseThrow(() -> new ResourceNotFoundException("Étudiant", id));
}
CHAPITRE 7

Spring Security & JWT


7.1 Dépendances nécessaires
<!-- Spring Security -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

<!-- JWT -->


<dependency>
<groupId>[Link]</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>

7.2 Configuration SecurityFilterChain


@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {

private final JwtAuthFilter jwtAuthFilter;


private final UserDetailsService userDetailsService;

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.csrf(csrf -> [Link]())
.sessionManagement(session -> session
.sessionCreationPolicy([Link]))
.authorizeHttpRequests(auth -> auth
.requestMatchers("/auth/**").permitAll()
.requestMatchers([Link], "/etudiants/**").hasRole("USER")
.requestMatchers("/etudiants/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.addFilterBefore(jwtAuthFilter, [Link])
.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

@Bean
public AuthenticationManager authManager(AuthenticationConfiguration config)
throws Exception {
return [Link]();
}
}

7.3 Service JWT


@Service
public class JwtService {

@Value("${[Link]}")
private String secretKey;

@Value("${[Link]}") // 24h par défaut


private long expiration;

public String generateToken(UserDetails userDetails) {


return [Link]()
.setSubject([Link]())
.setIssuedAt(new Date())
.setExpiration(new Date([Link]() + expiration))
.signWith(getSignKey(), SignatureAlgorithm.HS256)
.compact();
}

public String extractUsername(String token) {


return extractClaim(token, Claims::getSubject);
}

public boolean isTokenValid(String token, UserDetails userDetails) {


return extractUsername(token).equals([Link]())
&& !isTokenExpired(token);
}

private boolean isTokenExpired(String token) {


return extractClaim(token, Claims::getExpiration).before(new Date());
}

private &lt;T&gt; T extractClaim(String token, Function&lt;Claims, T&gt; resolver) {


Claims claims = [Link]()
.setSigningKey(getSignKey()).build()
.parseClaimsJws(token).getBody();
return [Link](claims);
}
private Key getSignKey() {
return [Link]([Link](secretKey));
}
}
CHAPITRE 8

Tests avec Spring Boot


8.1 Test d'intégration — @SpringBootTest
@SpringBootTest(webEnvironment = [Link].RANDOM_PORT)
@AutoConfigureTestDatabase(replace = [Link])
class EtudiantIntegrationTest {

@Autowired
private TestRestTemplate restTemplate;

@Autowired
private EtudiantRepository repository;

@BeforeEach
void setUp() {
[Link]();
}

@Test
void shouldCreateAndRetrieveEtudiant() {
EtudiantDTO dto = new EtudiantDTO();
[Link]("Dupont");
[Link]("dupont@[Link]");

ResponseEntity<EtudiantDTO> response =
[Link]("/etudiants", dto, [Link]);

assertThat([Link]()).isEqualTo([Link]);
assertThat([Link]().getNom()).isEqualTo("Dupont");
}
}

8.2 Test unitaire du Controller — @WebMvcTest


@WebMvcTest([Link])
class EtudiantControllerTest {

@Autowired
private MockMvc mockMvc;

@MockBean
private EtudiantService service;

@Autowired
private ObjectMapper objectMapper;

@Test
void shouldReturnListOfEtudiants() throws Exception {
List<EtudiantDTO> list = [Link](
new EtudiantDTO(1L, "Alice", "alice@[Link]"),
new EtudiantDTO(2L, "Bob", "bob@[Link]")
);
when([Link]()).thenReturn(list);

[Link](get("/etudiants")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.length()").value(2))
.andExpect(jsonPath("$[0].nom").value("Alice"));
}

@Test
void shouldReturn404WhenNotFound() throws Exception {
when([Link](99L))
.thenThrow(new ResourceNotFoundException("Étudiant", 99L));

[Link](get("/etudiants/99"))
.andExpect(status().isNotFound());
}
}

8.3 Test du Repository


@DataJpaTest
class EtudiantRepositoryTest {

@Autowired
private EtudiantRepository repository;

@Test
void shouldFindByEmail() {
Etudiant e = [Link]()
.nom("Test").email("test@[Link]").build();
[Link](e);

Optional<Etudiant> found = [Link]("test@[Link]");


assertThat(found).isPresent();
assertThat([Link]().getNom()).isEqualTo("Test");
}
}
CHAPITRE 9

Configuration Avancée & Profils


9.1 Profils Spring
Les profils permettent de définir des configurations différentes pour chaque environnement
(développement, test, production). Spring Boot charge automatiquement le fichier
application-{profil}.properties correspondant.
# [Link] (commun)
[Link]=mon-api
[Link]=8080

# [Link] (développement)
[Link]=jdbc:h2:mem:devdb
[Link]-sql=true
[Link]=DEBUG

# [Link] (production)
[Link]=jdbc:postgresql://localhost:5432/proddb
[Link]=${DB_USER}
[Link]=${DB_PASS}
[Link]-sql=false
[Link]=WARN

# Activer un profil
# Via propriété
[Link]=dev

# Via variable d'environnement


SPRING_PROFILES_ACTIVE=prod java -jar [Link]

# Via argument JVM


java -[Link]=prod -jar [Link]

9.2 @ConfigurationProperties
# [Link]
[Link]=ma-cle-secrete-tres-longue-256-bits
[Link]=86400000
[Link]-origins=[Link]

@ConfigurationProperties(prefix = "app")
@Component
@Data
public class AppProperties {

private Jwt jwt = new Jwt();


private Cors cors = new Cors();
@Data
public static class Jwt {
private String secret;
private long expiration = 86400000;
}

@Data
public static class Cors {
private List<String> allowedOrigins = new ArrayList<>();
}
}

// Injection
@Service
@RequiredArgsConstructor
public class JwtService {
private final AppProperties props;

// [Link]().getSecret()
// [Link]().getExpiration()
}
CHAPITRE 10

Déploiement avec Docker


10.1 Dockerfile optimisé
# ■■ Étape 1 : Build ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
FROM eclipse-temurin:17-jdk-alpine AS builder
WORKDIR /app

COPY [Link] .
COPY src ./src

# Télécharger les dépendances Maven (mis en cache)


RUN ./mvnw dependency:go-offline -B

# Compiler et packager
RUN ./mvnw package -DskipTests

# ■■ Étape 2 : Runtime ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


FROM eclipse-temurin:17-jre-alpine
WORKDIR /app

# Sécurité : utilisateur non-root


RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring

# Copier uniquement le JAR final


COPY --from=builder /app/target/*.jar [Link]

EXPOSE 8080

ENTRYPOINT ["java", "-XX:+UseContainerSupport", "-XX:MaxRAMPercentage=75.0", "-jar",


"[Link]"]

10.2 Docker Compose — API + PostgreSQL


version: '3.8'

services:
# ■■ Base de données PostgreSQL ■■■■■■■■■■■■■■■■■■■■■■
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: monapp
POSTGRES_USER: ${DB_USER:-admin}
POSTGRES_PASSWORD: ${DB_PASS:-secret}
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U admin"]
interval: 10s
timeout: 5s
retries: 5
networks:
- backend

# ■■ Application Spring Boot ■■■■■■■■■■■■■■■■■■■■■■■■■■


api:
build: .
ports:
- "8080:8080"
environment:
SPRING_PROFILES_ACTIVE: prod
SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/monapp
SPRING_DATASOURCE_USERNAME: ${DB_USER:-admin}
SPRING_DATASOURCE_PASSWORD: ${DB_PASS:-secret}
APP_JWT_SECRET: ${JWT_SECRET}
depends_on:
postgres:
condition: service_healthy
networks:
- backend

volumes:
pgdata:

networks:
backend:

# Lancer l'application
docker compose up --build -d

# Voir les logs


docker compose logs -f api

# Arrêter
docker compose down

■ Utilisez toujours des variables d'environnement (.env) pour les secrets. Ne committez jamais de mots de
passe dans votre code source.
CONCLUSION & PROCHAINES ÉTAPES
Vous disposez maintenant de toutes les bases pour construire des applications Spring Boot
professionnelles : de la configuration initiale à la sécurisation JWT, en passant par la persistance JPA,
la validation, les tests et le déploiement Docker.

Pour aller plus loin, explorez :

• Spring Cloud — microservices, discovery (Eureka), load balancing


• Spring WebFlux — programmation réactive avec Project Reactor
• Spring Batch — traitement de données en masse
• Spring Cache — mise en cache avec Redis ou Caffeine
• Actuator + Micrometer — métriques et monitoring (Prometheus/Grafana)
• OpenAPI / Swagger — documentation automatique de vos APIs

■ Documentation officielle : [Link]

Vous aimerez peut-être aussi