Spring Boot pour les microservices
Premier microservice
Spring Boot pour les Microservices
Dans ce tutoriel, nous allons créer notre premier microservice avec Spring Boot. Nous allons voir comment configurer le projet, implémenter les fonctionnalités de base et préparer le service pour une architecture microservices.
Configuration du projet
Prérequis
- Java 17 ou supérieur
- Maven ou Gradle
- IDE (IntelliJ IDEA, Eclipse, VS Code)
- Git
Création du projet
-
Utilisation de Spring Initializr
Visitez start.spring.io et configurez votre projet :
- Project: Maven
- Language: Java
- Spring Boot: 3.2.x
- Java: 17
- Dependencies:
- Spring Web
- Spring Data JPA
- H2 Database
- Lombok
- Spring Boot DevTools
-
Structure du projet
src/ ├── main/ │ ├── java/ │ │ └── com/example/ │ │ └── microservice/ │ │ ├── MicroserviceApplication.java │ │ ├── controller/ │ │ ├── service/ │ │ ├── repository/ │ │ ├── model/ │ │ └── config/ │ └── resources/ │ └── application.yml └── test/ └── java/ └── com/example/ └── microservice/
Configuration de base
application.yml
server:
port: 8080
spring:
application:
name: product-service
datasource:
url: jdbc:h2:mem:productdb
driver-class-name: org.h2.Driver
username: sa
password:
jpa:
database-platform: org.hibernate.dialect.H2Dialect
hibernate:
ddl-auto: update
h2:
console:
enabled: true
path: /h2-console
Configuration de base
@SpringBootApplication
public class MicroserviceApplication {
public static void main(String[] args) {
SpringApplication.run(MicroserviceApplication.class, args);
}
}
Implémentation du microservice
Modèle de données
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String description;
private BigDecimal price;
private Integer stock;
}
Repository
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
List<Product> findByPriceLessThan(BigDecimal price);
}
Service
@Service
@Slf4j
public class ProductService {
private final ProductRepository productRepository;
public ProductService(ProductRepository productRepository) {
this.productRepository = productRepository;
}
public List<Product> getAllProducts() {
return productRepository.findAll();
}
public Product getProductById(Long id) {
return productRepository.findById(id)
.orElseThrow(() -> new RuntimeException("Product not found"));
}
public Product createProduct(Product product) {
return productRepository.save(product);
}
public Product updateProduct(Long id, Product product) {
Product existingProduct = getProductById(id);
existingProduct.setName(product.getName());
existingProduct.setDescription(product.getDescription());
existingProduct.setPrice(product.getPrice());
existingProduct.setStock(product.getStock());
return productRepository.save(existingProduct);
}
public void deleteProduct(Long id) {
productRepository.deleteById(id);
}
}
Controller
@RestController
@RequestMapping("/api/products")
@Slf4j
public class ProductController {
private final ProductService productService;
public ProductController(ProductService productService) {
this.productService = productService;
}
@GetMapping
public ResponseEntity<List<Product>> getAllProducts() {
return ResponseEntity.ok(productService.getAllProducts());
}
@GetMapping("/{id}")
public ResponseEntity<Product> getProductById(@PathVariable Long id) {
return ResponseEntity.ok(productService.getProductById(id));
}
@PostMapping
public ResponseEntity<Product> createProduct(@RequestBody Product product) {
return ResponseEntity.status(HttpStatus.CREATED)
.body(productService.createProduct(product));
}
@PutMapping("/{id}")
public ResponseEntity<Product> updateProduct(
@PathVariable Long id,
@RequestBody Product product) {
return ResponseEntity.ok(productService.updateProduct(id, product));
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteProduct(@PathVariable Long id) {
productService.deleteProduct(id);
return ResponseEntity.noContent().build();
}
}
Tests
Test unitaire du service
@SpringBootTest
class ProductServiceTest {
@Autowired
private ProductService productService;
@MockBean
private ProductRepository productRepository;
@Test
void getAllProducts_ShouldReturnAllProducts() {
// Arrange
List<Product> expectedProducts = Arrays.asList(
new Product(1L, "Product 1", "Description 1", new BigDecimal("10.00"), 100),
new Product(2L, "Product 2", "Description 2", new BigDecimal("20.00"), 200)
);
when(productRepository.findAll()).thenReturn(expectedProducts);
// Act
List<Product> actualProducts = productService.getAllProducts();
// Assert
assertEquals(expectedProducts, actualProducts);
}
}
Test d’intégration
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class ProductControllerIntegrationTest {
@Autowired
private TestRestTemplate restTemplate;
@Test
void createProduct_ShouldReturnCreatedProduct() {
// Arrange
Product product = new Product(null, "Test Product", "Test Description",
new BigDecimal("10.00"), 100);
// Act
ResponseEntity<Product> response = restTemplate.postForEntity(
"/api/products", product, Product.class);
// Assert
assertEquals(HttpStatus.CREATED, response.getStatusCode());
assertNotNull(response.getBody());
assertEquals("Test Product", response.getBody().getName());
}
}
Préparation pour les microservices
Configuration de la santé du service
@Configuration
public class HealthConfig {
@Bean
public HealthIndicator productServiceHealthIndicator() {
return new HealthIndicator() {
@Override
public Health health() {
return Health.up()
.withDetail("service", "product-service")
.withDetail("status", "running")
.build();
}
};
}
}
Configuration des métriques
management:
endpoints:
web:
exposure:
include: health,metrics,prometheus
endpoint:
health:
show-details: always
Déploiement
Dockerfile
FROM eclipse-temurin:17-jdk-alpine
VOLUME /tmp
COPY target/*.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
docker-compose.yml
version: '3.8'
services:
product-service:
build: .
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
- SPRING_DATASOURCE_URL=jdbc:h2:mem:productdb
Conclusion
Nous avons créé un microservice de base avec Spring Boot qui :
- Expose une API REST pour la gestion des produits
- Utilise une base de données H2 en mémoire
- Inclut des tests unitaires et d’intégration
- Est prêt pour le déploiement avec Docker
Dans le prochain tutoriel, nous allons implémenter la découverte de services avec Eureka pour permettre à nos microservices de se trouver et communiquer entre eux.
Commentaires
Les commentaires sont alimentés par GitHub Discussions
Connectez-vous avec GitHub pour participer à la discussion