🔹 Java 8 → 21 : Nouveautés, Exemples et Cas d’usage
🔸 Java 8 (2014)
Nouveautés : Lambdas, Streams, Optional, Functional Interfaces, nouvelle Date/Time
API.
Exemple :
List<String> names = Arrays.asList("Ali", "Mohamed", "Sara");
names.stream()
.filter(name -> name.startsWith("A"))
.forEach(System.out::println);
Pourquoi ? :
o Approche fonctionnelle = code plus concis.
o Streams permettent de manipuler les collections de manière déclarative.
🔸 Java 11 (2018)
Nouveautés : var (typage implicite), HttpClient, nouvelles méthodes String (isBlank,
lines), suppression des modules Java EE.
Exemple :
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com"))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Pourquoi ? :
o HttpClient plus moderne, supporte asynchrone.
o var améliore la lisibilité dans les méthodes complexes.
🔸 Java 17 (2021 - LTS)
Nouveautés : record, sealed classes, pattern matching, nouveaux GC (G1, ZGC).
Exemple :
public record User(String name, int age) {}
User user = new User("Ala", 30);
Pourquoi ? :
o record = POJO immuable avec moins de boilerplate.
o sealed classes limitent les extensions non contrôlées (API plus sûre).
🔸 Java 21 (2023 - LTS)
Nouveautés : Virtual Threads, String Templates (preview), Scoped Values,
Structured Concurrency.
Exemple - Virtual Thread :
Thread.startVirtualThread(() -> {
System.out.println("Running in virtual thread");
});
Pourquoi ? :
o Concurrence massive à moindre coût.
o Remplace ExecutorService classique dans les applications réactives.
🔹 Spring 5, Spring 6 et Spring Boot : Fonctionnalités,
Versions, Cas d’usage
🔸 Spring 5 (2017)
Nouveautés :
o Support du paradigme réactif (WebFlux).
o Intégration avec Java 8 (Optional, Streams, CompletableFuture).
o Compatibilité avec JDK 9+.
Use Case :
o Application réactive non bloquante avec Mono et Flux.
@GetMapping("/user")
public Mono<User> getUser() {
return userService.findByIdAsync();
}
Pourquoi ? :
o Optimisation des ressources pour les applications à forte charge (ex: services de
streaming).
🔸 Spring 6 (2022)
Nouveautés :
o Support natif de GraalVM (AOT compilation).
o Nécessite Java 17+ et Jakarta EE 9+ (javax → jakarta).
o API sécurisée via ProblemDetail et gestion centralisée des erreurs.
Use Case :
o Microservice léger compilé en natif avec GraalVM pour startup rapide.
Pourquoi ? :
o Permet d'atteindre des objectifs Cloud-Native : rapidité, faible empreinte
mémoire.
🔸 Spring Boot (v2.7 à 3.x)
Spring Boot 2.7 : dernière version compatible avec Spring 5 et Java 8-11.
Spring Boot 3.0+ : basé sur Spring 6, Java 17+, Jakarta EE 9+.
Fonctionnalités clés :
o Démarrage rapide (@SpringBootApplication), autoconfiguration.
o Actuator (monitoring), DevTools, profils (application-{profile}.yml).
o Starter dependencies (ex: spring-boot-starter-web, -data-jpa, etc.)
Use Case :
@RestController
@RequestMapping("/api")
public class ProductController {
@GetMapping("/products")
public List<Product> all() {
return productRepository.findAll();
}
}
Pourquoi ? :
o Moins de configuration manuelle → gain de temps.
o Structuration rapide de microservices ou APIs REST.
🔹 Spring Security : Versions, Concepts, Cas d’usage
🔸 Concepts Clés
Authentication vs Authorization :
o Authentication = prouver l'identité.
o Authorization = accès aux ressources.
Filter Chain : enchaînement de filtres qui interceptent les requêtes HTTP.
SecurityContext : contient les détails de l’utilisateur connecté (Authentication).
GrantedAuthority : rôles/permissions.
🔸 Évolution par version
Spring Security 5.x :
o Support de OAuth 2.0 & OIDC.
o Password encoder obligatoire (BCryptPasswordEncoder).
o API reactive (SecurityWebFilterChain).
Spring Security 6.x (Spring Boot 3+):
o Migration complète vers jakarta.*
o Nouveau DSL avec lambdas (authorizeHttpRequests() au lieu de
antMatchers).
🔸 Exemple classique (Spring Boot 2.x - Security 5.x)
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin();
}
}
🔸 Exemple moderne (Spring Boot 3.x - Security 6.x)
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws
Exception {
return http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults())
.build();
}
🔸 Pourquoi ?
Sécurité robuste et configurable à tous les niveaux.
Intégration native avec OAuth2 / JWT / LDAP.
Personnalisation facile pour rôles, endpoints, CORS, CSRF, etc.
Nouvelle API (Spring 6) plus lisible, moins verbeuse.
🔹 Spring Data, JPA, Hibernate, EntityManager : Concepts
et Exemples
🔸 Spring Data JPA
But : Simplifier l'accès aux données via des interfaces sans implémentation explicite.
Exemple :
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByEmail(String email);
}
Pourquoi ? :
o Pas besoin d’écrire de requêtes SQL ou JPQL pour les opérations courantes.
o Génération dynamique des requêtes à partir du nom de la méthode.
🔸 JPA vs Hibernate
JPA : Spécification Java EE (maintenant Jakarta EE) pour la persistance.
Hibernate : Implémentation concrète de JPA (la plus populaire).
🔸 EntityManager
Utilisé dans : approche plus bas niveau que Spring Data.
@PersistenceContext
private EntityManager em;
public List<User> getAllUsers() {
return em.createQuery("SELECT u FROM User u",
User.class).getResultList();
}
Pourquoi ? :
o Contrôle fin sur les requêtes et le cycle de vie des entités.
🔸 Cas d’usage pratique
Utiliser JpaRepository pour la majorité des cas.
Utiliser EntityManager pour :
o Requêtes complexes.
o Transactions manuelles.
o Performance tuning.
🔹 Kafka : Messaging, Topics, Producers & Consumers
🔸 Concepts
Producer : envoie des messages dans un topic.
Consumer : lit les messages d’un topic.
Topic : canal de diffusion des messages.
Broker : instance Kafka.
🔸 Exemple (Spring Boot Kafka)
@Service
public class ProducerService {
@Autowired
private KafkaTemplate<String, String> kafkaTemplate;
public void send(String topic, String message) {
kafkaTemplate.send(topic, message);
}
}
@KafkaListener(topics = "my-topic", groupId = "group_id")
public void listen(String message) {
System.out.println("Received: " + message);
}
🔸 Pourquoi ?
Kafka est ultra performant pour des architectures microservices.
Asynchrone, scalable, tolérant aux pannes.
Idéal pour Event Sourcing, CQRS, logs distribués.
🔹 API First & OpenAPI : Conception et Documentation
🔸 API First
Principe : concevoir l’API avant d’implémenter le code.
Pourquoi ? :
o Permet la collaboration (frontend/backend/devOps) dès le début.
o Favorise la conformité, la réutilisabilité et le mock.
🔸 OpenAPI (ex-Swagger)
Spécification : décrit les endpoints, modèles, réponses HTTP.
Outils : Swagger UI, Swagger Editor, Springdoc-openapi.
🔸 Exemple YAML (OpenAPI 3.0)
openapi: 3.0.1
info:
title: Product API
version: 1.0.0
paths:
/products:
get:
summary: Get all products
responses:
'200':
description: A list of products
🔸 Spring Boot + OpenAPI
@OpenAPIDefinition(info = @Info(title = "Product API", version = "v1"))
@SpringBootApplication
public class App {}
🔹 JUnit, Mockito, TDD, BDD
🔸 JUnit 5
Annotations : @Test, @BeforeEach, @AfterEach, @Nested.
Assertion : assertEquals, assertThrows, assertTrue.
🔸 Mockito
Usage : simuler le comportement des dépendances.
@Mock
UserService userService;
@Test
void testUser() {
when(userService.getName()).thenReturn("Ala");
assertEquals("Ala", userService.getName());
}
🔸 TDD (Test Driven Development)
Cycle : Écrire un test → Écrire le code minimal → Refactoriser.
Pourquoi ? : Moins de bugs, design plus propre.
🔸 BDD (Behavior Driven Development)
Outils : Cucumber, JBehave.
Structure : Given / When / Then.
Feature: Login
Scenario: Successful login
Given user is on login page
When they enter valid credentials
Then they see the dashboard
🔹 Architecture Hexagonale & Microservices
🔸 Hexagonal Architecture (Ports & Adapters)
Principe : séparer la logique métier du monde extérieur.
Composants :
o Domaine (métier pur).
o Ports (interfaces).
o Adapters (implémentations concrètes : REST, DB).
🔸 Pourquoi ?
Testabilité, maintenabilité.
Facile à remplacer une technologie sans toucher à la logique métier.
🔸 Exemple :
interface UserRepositoryPort {
User findById(Long id);
}
class UserService {
UserRepositoryPort port;
// logique métier
}
🔸 Microservices : Concepts & Patterns
Définition : petite application indépendante qui communique via API.
Avantages : Scalabilité, indépendance de déploiement, résilience.
🔸 Patterns courants :
API Gateway : Point d’entrée unique (ex: Spring Cloud Gateway).
Service Registry : Découverte de service (ex: Eureka).
Circuit Breaker : Résilience (ex: Resilience4j).
Event Sourcing / CQRS : Meilleure séparation des responsabilités.
🔸 Use Case
Plateforme e-commerce : services pour commandes, stock, paiement, utilisateur, etc.
🔹 Jenkins & Docker : CI/CD et Conteneurisation
🔸 Jenkins
Fonction : automatisation de build, test, déploiement.
Pipeline :
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'mvn clean install'
}
}
stage('Test') {
steps {
sh 'mvn test'
}
}
}
}
Plugins : GitHub, Docker, SonarQube, Slack.
🔸 Docker
Concepts : Image, Container, Dockerfile.
Exemple Dockerfile :
FROM openjdk:17-jdk
COPY target/app.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
🔸 Pourquoi ?
Déploiement cohérent sur toutes les machines.
Isolation, rapidité, portabilité (dev → test → prod).
Tout cela permet une architecture moderne, modulaire, testable et facilement déployable dans un
contexte cloud/microservices.
🔹 Angular : RxJS, Signals, Binding, Pipes, Directives
🔸 RxJS
Observable : flux de données asynchrones.
Operators : map, filter, switchMap, etc.
this.http.get('/api/users').pipe(map(data =>
data.name)).subscribe(console.log);
Use case : appels API, formulaires réactifs, WebSockets.
🔸 Signals (Angular 16+)
Nouveau modèle réactif basé sur des signaux (comme SolidJS).
const counter = signal(0);
const doubled = computed(() => counter() * 2);
Pourquoi ? :
o Remplace BehaviorSubject, ReplaySubject dans certains cas.
o Meilleure lisibilité, pas de subscribe/unsubscribe.
🔸 Data Binding
One-way : [value]="user.name"
Two-way : [(ngModel)]="user.name"
🔸 Pipes
Fonction : transformer la donnée dans le template.
{{ birthday | date:'shortDate' }}
Custom Pipe :
@Pipe({name: 'capitalize'})
export class CapitalizePipe implements PipeTransform {
transform(value: string): string {
return value.charAt(0).toUpperCase() + value.slice(1);
}
}
🔸 Directives
Structurelles : *ngIf, *ngFor
Attributs : [ngClass], [ngStyle]
Custom Directive :
@Directive({ selector: '[appHighlight]' })
export class HighlightDirective {
constructor(el: ElementRef) {
el.nativeElement.style.backgroundColor = 'yellow';
}
}