Spring Boot +Angular+Consul Gateway
Backend (Spring Boot)
Client Entity
package com.emsi.models;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Column;
import jakarta.persistence.Table;
@Entity
@Table(name = "clients") // Specify the table name
public class Client {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id") // Optional, but can be useful for clarity or customization
private Long id;
@Column(name = "nom", nullable = false, length = 100) // Specifies non-null and a maximum length of 100 characters
private String nom;
@Column(name = "prenom", nullable = false, length = 100)
private String prenom;
@Column(name = "tel", length = 15) // Limits the phone number length to 15 characters
private String tel;
@Column(name = "email", nullable = false, unique = true) // Ensures email is unique and non-null
private String email;
@Column(name = "password", nullable = false)
private String password;
// Constructor
public Client() {
}
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
public String getPrenom() {
return prenom;
}
public void setPrenom(String prenom) {
this.prenom = prenom;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Client Repository
package com.emsi.repositories;
import org.springframework.data.jpa.repository.JpaRepository;
import com.emsi.models.Client;
public interface ClientRepository extends JpaRepository {
}
Service Layer
package com.emsi.services;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.emsi.models.Client;
import com.emsi.repositories.ClientRepository;
import java.util.List;
@Service
public class ClientService {
@Autowired
private ClientRepository clientRepository;
public List getAllClients() {
return clientRepository.findAll();
}
public Client getClientById(Long id) {
return clientRepository.findById(id).orElse(null);
}
public Client saveClient(Client client) {
return clientRepository.save(client);
}
public void deleteClient(Long id) {
clientRepository.deleteById(id);
}
}
REST Controller
package com.emsi.controllers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.emsi.models.Client;
import com.emsi.services.ClientService;
import java.util.List;
@CrossOrigin(origins = "http://localhost:4200")
@RestController
@RequestMapping("/api/clients")
public class ClientController {
@Autowired
private ClientService clientService;
@GetMapping
public List getAllClients() {
return clientService.getAllClients();
}
@GetMapping("/{id}")
public Client getClientById(@PathVariable Long id) {
return clientService.getClientById(id);
}
@PostMapping
public Client saveClient(@RequestBody Client client) {
return clientService.saveClient(client);
}
@PutMapping("/{id}")
public Client updateClient(@PathVariable Long id, @RequestBody Client client) {
client.setId(id);
return clientService.saveClient(client);
}
@DeleteMapping("/{id}")
public void deleteClient(@PathVariable Long id) {
clientService.deleteClient(id);
}
}
Consul Gateway
Create a Spring Boot project named api-gateway.pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
Configure application.yml for the gateway:
spring:
application:
name: api-gateway
cloud:
consul:
discovery:
enabled: true
register: true
profiles:
active: consul
server:
port: 8080
cloud:
gateway:
routes:
- id: product-service
uri: lb://product-service
predicates:
- Path=/products/**
- id: client-service
uri: lb://client-service
predicates:
- Path=/clients/**
lb://product-service and lb://order-service use Consul to resolve the actual service locations.
main application class.xml
@SpringBootApplication
public class ApiGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(ApiGatewayApplication.class, args);
}
}
In Consul's UI (typically at http://localhost:8500), you should see product-service, order-service, and api-gateway registered. Access the endpoints via the gateway: http://localhost:8080/products → routes to product-service http://localhost:8080/clients → routes to clients-service
Frontend (Angular)
Introduction
Angular est une plateforme et un framework de développement pour construire des applications web en utilisant TypeScript. Ce tutoriel vous guidera à travers les étapes nécessaires pour installer et configurer Angular sur votre machine.
Étapes à suivre
1.Installer Node.js :
Angular nécessite Node.js pour fonctionner. Téléchargez et installez la dernière version de Node.js à partir du site officiel :
Vérifiez que Node.js est bien installé en exécutant la commande suivante dans un terminal :
2.Installer Angular CLI :
Angular CLI est l'outil officiel pour créer et gérer des projets Angular. Pour l'installer, exécutez la commande suivante :
Vérifiez que l'installation est correcte :
3.Créer un nouveau projet Angular :
Une fois Angular CLI installé, vous pouvez créer un nouveau projet avec la commande :
Suivez les instructions affichées pour configurer votre projet.
4.Exécuter le projet Angular :
Après avoir créé votre projet, entrez dans le dossier du projet :
Puis exécutez l'application avec la commande suivante :
Ouvrez votre navigateur et accédez à http://localhost:4200 pour voir votre application en action.

6.Structure d'un projet Angular :
Angular utilise une architecture modulaire. Voici une brève description des répertoires principaux :
- src/ : Contient tout le code source de votre application.
- app/ : Contient les composants et les services de votre application.
- assets/ : Contient les fichiers statiques comme les images.
7.Déployer l'application :
Pour générer une version de production de votre application Angular, exécutez :
Les fichiers de votre application prête à être déployée se trouvent dans le répertoire dist/
.
Services
ng generate service services/client
ClientService
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Client } from '../models/Client';
@Injectable({
providedIn: 'root'
})
export class ClientService {
private baseUrl = 'http://localhost:8097/api/clients'; // Your Spring Boot API base URL
constructor(private http: HttpClient) { }
// Fetch all clients
getClients(): Observable {
return this.http.get(this.baseUrl);
}
// Fetch a single client by ID
getClient(id: number): Observable {
return this.http.get(`${this.baseUrl}/${id}`);
}
// Create a new client
createClient(client: Client): Observable {
return this.http.post(this.baseUrl, client);
}
// Update a client
updateClient(id: number, client: Client): Observable {
return this.http.put(`${this.baseUrl}/${id}`, client);
}
// Delete a client
deleteClient(id: number): Observable {
return this.http.delete(`${this.baseUrl}/${id}`);
}
}
Client Model :models/Clients
export class Client {
id!: number;
nom!: string;
prenom!: string;
tel!: string;
email!: string;
password!: string;
}
client-list.component.html
ng generate component components/client-list
<div class="client-list-card">
<h2>Client List</h2>
<a routerLink="/add-client">Add Client</a>
<table class="client-table">
<thead>
<tr>
<th>Nom</th>
<th>Prénom</th>
<th>Téléphone</th>
<th>Email</th>
<th>Password</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let client of clients">
<td>{{ client.nom }}</td>
<td>{{ client.prenom }}</td>
<td>{{ client.tel }}</td>
<td>{{ client.email }}</td>
<td>{{ client.password }}</td>
<td>
<a [routerLink]="['/edit-client', client.id]">Edit</a>
<button (click)="deleteClient(client.id)">Delete</button>
</td>
</tr>
</tbody>
</table>
</div>
client-list.component.css
.client-list-card {
max-width: 800px;
margin: 20px auto;
padding: 20px;
border: 1px solid #ccc;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
background-color: #fff;
}
/* Heading */
.client-list-card h2 {
font-size: 24px;
margin-bottom: 20px;
}
/* Button styling */
.add-client-btn {
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
.add-client-btn:hover {
background-color: #0056b3;
}
/* Table styling */
.client-table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
.client-table th, .client-table td {
padding: 12px 15px;
border: 1px solid #ddd;
text-align: left;
}
.client-table th {
background-color: #f2f2f2;
font-weight: bold;
}
.client-table tr:nth-child(even) {
background-color: #f9f9f9;
}
.client-table tr:hover {
background-color: #f1f1f1;
}
CRUD Operations in client/list.component.ts
import { Component, OnInit } from '@angular/core';
import { Client } from '../../../models/Client';
import { ClientService } from '../../../services/client.service';
@Component({
selector: 'app-client-list',
templateUrl: './list.component.html',
styleUrls: ['./list.component.css']
})
export class ClientListComponent implements OnInit {
clients: Client[] = [];
constructor(private clientService: ClientService) {}
ngOnInit(): void {
this.clientService.getClients().subscribe(data => {
this.clients = data;
});
}
deleteClient(id: number): void {
this.clientService.deleteClient(id).subscribe(() => {
this.clients = this.clients.filter(client => client.id !== id);
});
}
}
ng generate component components/client-add
client-add.component.html
<div>
<form (ngSubmit)="addClient()">
<div>
<label for="nom">Nom:</label>
<input type="text" id="nom" [(ngModel)]="client.nom" name="nom" required />
</div>
<div>
<label for="prenom">Prénom:</label>
<input type="text" id="prenom" [(ngModel)]="client.prenom" name="prenom" required />
</div>
<div>
<label for="tel">Téléphone:</label>
<input type="text" id="tel" [(ngModel)]="client.tel" name="tel" required />
</div>
<div>
<label for="email">Email:</label>
<input type="email" id="email" [(ngModel)]="client.email" name="email" required />
</div>
<div>
<label for="password">Password:</label>
<input type="password" id="password" [(ngModel)]="client.password" name="password" required />
</div>
<button type="submit">{{ client.id ? 'Update' : 'Add' }}</button>
</form>
</div>
client-add.component.ts
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { Client } from '../../models/Client';
import { ClientService } from '../../services/client.service';
@Component({
selector: 'app-client-add',
templateUrl: './client-add.component.html',
styleUrls: ['./client-add.component.css']
})
export class ClientAddComponent {
client: Client = new Client();
constructor(private clientService: ClientService, private router: Router) {}
addClient(): void {
this.clientService.createClient(this.client).subscribe(() => {
this.router.navigate(['/clients']);
});
}
}
ng generate component components/client-edit
client-edit.component.html
<div>
<form (ngSubmit)=" updateClient()">
<div>
<label for="nom">Nom:</label>
<input type="text" id="nom" [(ngModel)]="client.nom" name="nom" required />
</div>
<div>
<label for="prenom">Prénom:</label>
<input type="text" id="prenom" [(ngModel)]="client.prenom" name="prenom" required />
</div>
<div>
<label for="tel">Téléphone:</label>
<input type="text" id="tel" [(ngModel)]="client.tel" name="tel" required />
</div>
<div>
<label for="email">Email:</label>
<input type="email" id="email" [(ngModel)]="client.email" name="email" required />
</div>
<div>
<label for="password">Password:</label>
<input type="password" id="password" [(ngModel)]="client.password" name="password" required />
</div>
<button type="submit">{{ client.id ? 'Update' : 'Add' }}</button>
</form>
</div>
client-edit.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { ClientService } from '../../services/client.service';
import { Client } from '../../models/Client';
@Component({
selector: 'app-client-edit',
templateUrl: './client-edit.component.html',
styleUrls: ['./client-edit.component.css']
})
export class ClientEditComponent implements OnInit {
client: Client = new Client();
constructor(
private clientService: ClientService,
private route: ActivatedRoute,
private router: Router
) {}
ngOnInit(): void {
const id = this.route.snapshot.params['id'];
this.clientService.getClient(id).subscribe(data => {
this.client = data;
});
}
updateClient(): void {
const id = this.route.snapshot.params['id'];
this.clientService.updateClient(id, this.client).subscribe(() => {
this.router.navigate(['/clients']);
});
}
}
app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { ClientListComponent } from './components/clients/list/list.component';
import { ClientAddComponent } from './components/client-add/client-add.component';
import { ClientEditComponent } from './components/client-edit/client-edit.component';
const routes: Routes = [
{ path: '', redirectTo: '/clients', pathMatch: 'full' },
{ path: 'clients', component: ClientListComponent },
{ path: 'add-client', component: ClientAddComponent },
{ path: 'edit-client/:id', component: ClientEditComponent }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
app.module.ts
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http'; // Import the HttpClientModule
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { ClientListComponent } from './components/clients/list/list.component';
import { ClientAddComponent } from './components/client-add/client-add.component';
import { ClientEditComponent } from './components/client-edit/client-edit.component';
@NgModule({
declarations: [
AppComponent,
ClientListComponent,
ClientAddComponent,
ClientEditComponent
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule,
FormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Running the Application
Start the Spring Boot backend:
mvn spring-boot:run
Start the Angular frontend:
ng serve
http://localhost:4200
