Projet académique réalisé dans le cadre du cours de Programmation Orientée Objet (POO)
à l'Institut des Hautes Études Commerciales de Carthage (IHEC).
- Vue d'ensemble
- Fonctionnalités
- Architecture MVC
- Structure du projet
- Technologies utilisées
- Modèle de données
- Endpoints REST
- Prérequis
- Installation et lancement
- Sécurité
- Principes POO appliqués
- Dépannage
UniMatch est une plateforme communautaire web destinée aux étudiants de l'IHEC Carthage.
Elle centralise les besoins de la vie universitaire : publications, covoiturage, sessions d'étude collectives, échange de documents, messagerie privée et un chatbot IA intégré.
L'application repose sur un backend Spring Boot qui expose une API REST, et un frontend en HTML/CSS/JavaScript servi statiquement par le même serveur.
| Module | Description |
|---|---|
| Authentification | Inscription, connexion, déconnexion. Session stockée côté navigateur (localStorage). |
| Publications | Fil d'actualité : annonces, questions, offres, événements. Système de likes. |
| Covoiturage | Proposer ou réserver un trajet domicile/fac. Gestion des places disponibles. |
| Study Together | Organiser ou rejoindre des sessions de révision en groupe par matière. |
| Échanges de documents | Proposer et accepter des échanges de cours/ressources entre étudiants. |
| Messagerie privée | Échange de messages directs entre deux étudiants. |
| Notifications | Alertes en temps réel (réservation, échange accepté, nouveau message…). |
| Chatbot IA | Assistant conversationnel intégré, propulsé par l'API Anthropic (Claude). |
| Tableau de bord admin | Statistiques globales, gestion des utilisateurs (activation/désactivation, rôle admin). |
Le projet suit le patron MVC (Modèle — Vue — Contrôleur) appliqué à une API REST Spring Boot :
┌─────────────────────────────────────────────────────────────┐
│ VUE (HTML / CSS / JavaScript) │
│ src/main/resources/static/ │
│ • Pages HTML rendues par le navigateur │
│ • Appels fetch() vers l'API REST │
│ • Bootstrap 5 + CSS personnalisé │
└─────────────────────────────────────────────────────────────┘
│ HTTP / JSON
▼
┌─────────────────────────────────────────────────────────────┐
│ CONTRÔLEUR (Spring REST Controllers) │
│ com.ihec.unimatch.controller.api.* │
│ • Reçoit les requêtes HTTP │
│ • Valide les entrées │
│ • Délègue le traitement aux Services │
│ • Renvoie les réponses JSON │
└─────────────────────────────────────────────────────────────┘
│ Appel de méthode
▼
┌─────────────────────────────────────────────────────────────┐
│ MODÈLE (Entités + Repositories + Services) │
│ com.ihec.unimatch.model.* │
│ • entity/ : classes JPA mappées sur les tables MySQL │
│ • repository/ : interfaces Spring Data (requêtes SQL auto) │
│ • service/ : logique métier (règles, validations) │
│ • dto/ : objets de transfert (LoginRequest, etc.) │
└─────────────────────────────────────────────────────────────┘
│ JPA / Hibernate
▼
┌───────────┐
│ MySQL │
│unimatch_db│
└───────────┘
Séparation des responsabilités :
- La Vue ne connaît pas la base de données — elle communique uniquement via l'API.
- Le Contrôleur ne contient pas de logique métier — il orchestre et délègue.
- Le Modèle est indépendant du frontend — on peut remplacer le HTML par React ou mobile sans toucher au backend.
unimatch/
├── pom.xml # Configuration Maven + dépendances
├── unimatch_db.sql # Script SQL (schéma + données initiales)
├── README.md
└── src/main/
├── java/com/ihec/unimatch/
│ │
│ ├── UnimatchApplication.java # Point d'entrée Spring Boot
│ │
│ ├── controller/ # ── CONTRÔLEURS ──────────────────
│ │ ├── SpaController.java # Routage des pages HTML (GET /)
│ │ └── api/
│ │ ├── UserController.java
│ │ ├── PostController.java
│ │ ├── CovoiturageController.java
│ │ ├── StudyTogetherController.java
│ │ ├── EchangeController.java
│ │ ├── MessageController.java
│ │ ├── NotificationController.java
│ │ ├── ReservationController.java
│ │ ├── StatistiquesController.java
│ │ ├── ChatbotController.java
│ │ └── GlobalExceptionHandler.java
│ │
│ ├── model/ # ── MODÈLE ────────────────────────
│ │ ├── entity/ # Entités JPA (tables MySQL)
│ │ │ ├── UserEntity.java
│ │ │ ├── PostEntity.java
│ │ │ ├── PostLikeEntity.java
│ │ │ ├── CovoiturageEntity.java
│ │ │ ├── StudyTogetherEntity.java
│ │ │ ├── EchangeEntity.java
│ │ │ ├── MessageEntity.java
│ │ │ ├── NotificationEntity.java
│ │ │ └── ReservationEntity.java
│ │ ├── repository/ # Spring Data JPA (requêtes auto)
│ │ │ ├── UserRepository.java
│ │ │ ├── PostRepository.java
│ │ │ ├── PostLikeRepository.java
│ │ │ ├── CovoiturageRepository.java
│ │ │ ├── StudyTogetherRepository.java
│ │ │ ├── EchangeRepository.java
│ │ │ ├── MessageRepository.java
│ │ │ ├── NotificationRepository.java
│ │ │ └── ReservationRepository.java
│ │ ├── service/ # Logique métier
│ │ │ ├── UserService.java
│ │ │ ├── PostService.java
│ │ │ ├── CovoiturageService.java
│ │ │ ├── StudyTogetherService.java
│ │ │ ├── EchangeService.java
│ │ │ ├── MessageService.java
│ │ │ ├── NotificationService.java
│ │ │ ├── ReservationService.java
│ │ │ ├── StatistiquesService.java
│ │ │ ├── ChatbotService.java
│ │ │ └── ServiceException.java
│ │ └── dto/ # Objets de transfert
│ │ ├── LoginRequest.java
│ │ ├── MessageRequest.java
│ │ ├── NotificationRequest.java
│ │ └── StatistiquesDTO.java
│ │
│ └── chatbot/
│ └── ChatbotApiClient.java # Client HTTP vers l'API Anthropic
│
└── resources/
├── application.properties # Configuration Spring Boot + MySQL
└── static/ # ── VUE (frontend) ────────────────
├── index.html # Page d'accueil
├── login.html # Connexion
├── register.html # Inscription
├── dashboard.html # Tableau de bord
├── posts.html # Fil de publications
├── publier.html # Créer une publication
├── covoiturage.html # Covoiturages
├── study.html # Study Together
├── echanges.html # Échanges de documents
├── messages.html # Messagerie privée
├── notifications.html # Notifications
├── admin.html # Administration
├── css/
│ └── style.css # Styles personnalisés (thème IHEC)
└── js/
├── auth.js # Authentification + utilitaires globaux
├── api.js # Fonctions d'appel API
└── chatbot.js # Widget chatbot IA
| Couche | Technologie | Version |
|---|---|---|
| Backend | Spring Boot | 3.3.5 |
| ORM | Spring Data JPA / Hibernate | géré par Boot |
| Base de données | MySQL | 8.x |
| Sécurité | spring-security-crypto (BCrypt) | géré par Boot |
| Sérialisation | Jackson (JSON) | géré par Boot |
| Frontend | HTML5 / CSS3 / JavaScript (ES6+) | — |
| CSS Framework | Bootstrap | 5.3 |
| IA | API Anthropic (Claude) | — |
| Build | Maven | 3.8+ |
| Java | JDK | 17 |
9 tables reliées par clés étrangères :
users ──┬── posts (1 utilisateur → N publications)
├── post_likes (1 utilisateur → N likes)
├── covoiturages (1 conducteur → N trajets)
├── studytogether (1 organisateur → N sessions)
├── echanges (1 proposeur + 1 récepteur → N échanges)
├── messages (1 expéditeur + 1 destinataire → N messages)
├── notifications (1 utilisateur → N notifications)
└── reservations (1 utilisateur → N réservations)
Les tables sont générées automatiquement par Hibernate au démarrage (ddl-auto=update).
Le fichier unimatch_db.sql contient le schéma complet et des données d'exemple.
Base URL : http://localhost:8081
| Méthode | URL | Description |
|---|---|---|
| GET | /api/users |
Liste des utilisateurs actifs |
| GET | /api/users/{id} |
Utilisateur par ID |
| GET | /api/users/email/{email} |
Utilisateur par email |
| GET | /api/users/recherche?q= |
Recherche par nom/prénom/filière |
| GET | /api/users/admin/tous |
Tous les utilisateurs (admin) |
| POST | /api/users |
Inscription |
| POST | /api/users/login |
Authentification |
| PUT | /api/users/{id} |
Modifier le profil |
| PUT | /api/users/{id}/activer |
Activer un compte |
| PUT | /api/users/{id}/toggle-admin |
Accorder/retirer le rôle admin |
| DELETE | /api/users/{id} |
Désactiver un compte (soft delete) |
| Méthode | URL | Description |
|---|---|---|
| GET | /api/posts |
Toutes les publications |
| GET | /api/posts/{id} |
Publication par ID |
| GET | /api/posts/user/{userId} |
Publications d'un utilisateur |
| GET | /api/posts/recherche?motCle= |
Recherche par mot-clé |
| POST | /api/posts?userId= |
Créer une publication |
| PUT | /api/posts/{id}/liker |
Ajouter un like |
| DELETE | /api/posts/{id} |
Supprimer |
| Méthode | URL | Description |
|---|---|---|
| GET | /api/covoiturages |
Tous les trajets |
| GET | /api/covoiturages/disponibles |
Trajets avec places restantes |
| GET | /api/covoiturages/{id} |
Trajet par ID |
| GET | /api/covoiturages/conducteur/{userId} |
Trajets d'un conducteur |
| GET | /api/covoiturages/recherche?lieu= |
Recherche par lieu |
| POST | /api/covoiturages?conducteurId= |
Proposer un trajet |
| PUT | /api/covoiturages/{id} |
Modifier |
| PUT | /api/covoiturages/{id}/reserver |
Réserver une place |
| DELETE | /api/covoiturages/{id} |
Supprimer |
| Méthode | URL | Description |
|---|---|---|
| GET | /api/studytogether |
Toutes les sessions |
| GET | /api/studytogether/disponibles |
Sessions avec places |
| GET | /api/studytogether/{id} |
Session par ID |
| GET | /api/studytogether/recherche?matiere= |
Recherche par matière |
| POST | /api/studytogether?organisateurId= |
Créer une session |
| PUT | /api/studytogether/{id} |
Modifier |
| PUT | /api/studytogether/{id}/rejoindre |
Rejoindre |
| DELETE | /api/studytogether/{id} |
Supprimer |
| Méthode | URL | Description |
|---|---|---|
| GET | /api/echanges |
Tous les échanges |
| GET | /api/echanges/{id} |
Échange par ID |
| GET | /api/echanges/user/{userId} |
Échanges d'un utilisateur |
| GET | /api/echanges/statut/{statut} |
Filtrer par statut |
| POST | /api/echanges?proposeurId=&recepteurId= |
Proposer un échange |
| PUT | /api/echanges/{id}/statut?statut=ACCEPTE |
Changer le statut |
| DELETE | /api/echanges/{id} |
Supprimer |
| Méthode | URL | Description |
|---|---|---|
| GET | /api/messages/recus/{userId} |
Boîte de réception |
| GET | /api/messages/envoyes/{userId} |
Messages envoyés |
| POST | /api/messages?expediteurId= |
Envoyer un message |
| PUT | /api/messages/{id}/lu |
Marquer comme lu |
| DELETE | /api/messages/{id} |
Supprimer |
| Méthode | URL | Description |
|---|---|---|
| GET | /api/notifications/user/{userId} |
Notifications d'un utilisateur |
| POST | /api/notifications |
Créer une notification |
| PUT | /api/notifications/{id}/lue |
Marquer comme lue |
| PUT | /api/notifications/user/{userId}/lues |
Tout marquer comme lu |
| DELETE | /api/notifications/{id} |
Supprimer |
| Méthode | URL | Description |
|---|---|---|
| GET | /api/reservations/user/{userId} |
Réservations d'un utilisateur |
| POST | /api/reservations/covoiturage?userId=&covoiturageId= |
Réserver un trajet |
| POST | /api/reservations/study?userId=&studyId= |
Rejoindre une session |
| PUT | /api/reservations/{id}/annuler |
Annuler |
| DELETE | /api/reservations/{id} |
Supprimer |
| Méthode | URL | Description |
|---|---|---|
| GET | /api/statistiques |
Compteurs globaux (dashboard admin) |
| POST | /api/chatbot/message |
Envoyer un message au chatbot IA |
| POST | /api/chatbot/reinitialiser |
Réinitialiser la conversation |
| Outil | Version minimale | Vérification |
|---|---|---|
| JDK | 17 | java -version |
| Maven | 3.8 | mvn -version |
| MySQL | 8.x | mysql --version |
git clone https://github.com/TON_USERNAME/unimatch.git
cd unimatchAssurez-vous que MySQL tourne sur le port 3306.
Adaptez si besoin src/main/resources/application.properties :
spring.datasource.url=jdbc:mysql://localhost:3306/unimatch_db?useSSL=false&serverTimezone=UTC&createDatabaseIfNotExist=true
spring.datasource.username=root
spring.datasource.password=La base unimatch_db et toutes les tables sont créées automatiquement au premier démarrage.
Pour importer les données d'exemple :
mysql -u root -p < unimatch_db.sqlDéfinir la variable d'environnement avant de lancer :
# Linux / macOS
export ANTHROPIC_API_KEY=votre-clé-ici
# Windows PowerShell
$env:ANTHROPIC_API_KEY = "votre-clé-ici"mvn clean spring-boot:runhttp://localhost:8081
- Les mots de passe sont hachés avec BCrypt avant stockage — jamais en clair en base de données.
- La vérification au login utilise
BCryptPasswordEncoder.matches()sans jamais déhacher. - La clé API Anthropic est chargée depuis une variable d'environnement (
ANTHROPIC_API_KEY) et n'est pas versionnée. - Les sessions sont gérées côté client via
localStorage(pas de cookies serveur).
| Principe | Exemple dans le projet |
|---|---|
| Encapsulation | Tous les attributs des entités sont private, accessibles uniquement via getters/setters |
| Abstraction | JpaRepository masque toutes les requêtes SQL ; ServiceException abstrait les erreurs métier |
| Héritage | Les repositories étendent JpaRepository<T, ID> et héritent de toutes ses méthodes CRUD |
| Polymorphisme | GlobalExceptionHandler gère différents types d'exceptions avec un comportement adapté à chacun |
| Composition | Les services composent un repository (injection par constructeur) plutôt que d'en hériter |
| Single Responsibility | Chaque classe a un rôle unique : entité = données, repository = accès BD, service = logique, contrôleur = HTTP |
| Séparation des couches | Le contrôleur ne touche jamais le repository directement — il passe obligatoirement par le service |
Port 8081 déjà utilisé
# Windows — trouver et arrêter le processus
netstat -ano | findstr :8081
taskkill /PID <PID> /FErreur de connexion MySQL
- Vérifier que MySQL est démarré
- Vérifier le mot de passe dans
application.properties - S'assurer que l'utilisateur a les droits sur
unimatch_db
Chatbot ne répond pas
- Vérifier que la variable
ANTHROPIC_API_KEYest définie - Vérifier la connexion internet (appel vers l'API externe)
Impossible de se connecter avec un ancien compte
- Les comptes créés avant l'ajout du hachage BCrypt ont des mots de passe en clair incompatibles.
- Solution : recréer le compte via la page d'inscription.
Projet réalisé dans le cadre du cours de POO — IHEC Carthage — Année 2025/2026.