Le développement d'une plateforme de commerce en ligne pour les vêtements traditionnels chinois (Hanfu) requiert une architecture robuste. Ce projet combine une architecture backend avec Spring Boot, un frontend web réactif avec Vue.js et une application mobile multiplateforme via UniApp. L'objectif est de créer un système complet permettant aux utilisateurs de parcourir, commander et gérer les produits de manière transparente sur différentes plateformes.
Stack technique détaillée
Backend : Spring Boot
Spring Boot simplifie le développement des applications Java en fournissant un ensemble d'outils préconfigurés. Sa fonctionnalité de démarrage rapide et ses dépendances intégrées permettent une mise en route immédiate. Le framework supporte nativement des serveurs comme Tomcat et offre une intégration facile avec des bibliothèques de sécurité (Spring Security), de données (Spring Data) et de services cloud (Spring Cloud). Cette modularité accélère le développement et la maintenance des services backand.
Frontend web : Vue.js
Vue.js utilise un DOM virtuel pour optimiser les performances d'interface. Son modèle de liaison de données réactif garantit que l'interface utilisateur se met à jour automatiquement lorsque l'état de l'application change. Cette approche par composants favorise la réutilisabilité du code et une structure claire de l'application, permettant aux développeurs de se concentrer sur la logique métier plutôt que sur les manipulations manuelles du DOM.
Couche de données : MyBatis-Plus
MyBatis-Plus étend les fonctionnalités de MyBatis pour réduire le code boilerplate. Il fournit des annotations et des assistants pour les opérations CRUD courantes, ainsi que des outils de pagination et de requêtes dynamiques. Le générateur de code automatique peut produier des classes d'entités et des interfaces de mapping, accélérant ainsi la mise en place de la couche d'accès aux données pour diverses bases de données relationnelles.
Processus de test du système
La phase de validation est cruciale pour assurer la qualité et la fiabilité de l'application. Une approche de boîte noire est adoptée pour tester les fonctionnalités du point de vue de l'utilisateur, en identifiant les écarts par rapport aux exigences et en corrigeant les défauts.
Objectifs des tests
L'objectif principal est de simuler des scénarios d'utilisation réels pour détecter les problèmes potentiels. Cela permet d'améliorer l'expérience utilisateur en s'assurant que toutes les interactions répondent aux attentes. Les tests vérifient non seulement la fonctionnalité mais aussi la cohérence logique et la robustesse du système face à des entrées inattendues.
Exemples de cas de test fonctionnels
Pour la fonctionnalité de connexion, les tests incluent la validation des identifiants et des codes de vérification. Voici un exemple de structure de test :
| Entrée | Résultat attendu | Résultat observé | Analyse |
|---|---|---|---|
| Nom d'utilisateur : admin, Mot de passe : passe123, Code : correct | Connexion réussie | L'utilisateur accède au tableau de bord | Conforme à l'attente |
| Nom d'utilisateur : admin, Mot de passe : secret999, Code : correct | Message d'erreur de mot de passe | L'interface affiche une erreur de mot de passe | Conforme à l'attente |
| Nom d'utilisateur : (vide), Mot de passe : passe123, Code : correct | Champ nom d'utilisateur obligatoire | Un message d'erreur indique que le nom est requis | Conforme à l'attente |
Pour la gestion des utilisateurs, les tests couvrent les opérations d'ajout, de modification et de suppression. Par exemple :
| Action | Résultat attendu | Résultat observé | Analyse |
|---|---|---|---|
| Ajout d'un nouvel utilisateur avec des informations valides | L'utilisateur apparaît dans la liste | L'enregistrement est visible dans l'interface d'administration | Succès |
| Tentative d'ajout avec un nom d'utilisateur déjà existant | Message d'erreur indiquant une duplication | L'application empêche l'ajout et notifie l'administrateur | Comportement correct |
Conclusion des tests
À l'issue du cycle de test, le système répond aux exigences fonctionnelles spécifiées. Les résultats démontrent une couverture adéquate des scénarios critiques et une expérience utilisateur cohérente. Des ajustements ont été apportés pour renforcer la validation des entrées et la gestion des erreurs, garantissant ainsi une plateforme stable pour le commerce de Hanfu.
Extraits de code révisés
Voici des exemples de code issus de l'implémentation backend. Les noms de variables et la structure logique ont été modifiés pour clarifier l'illustration, tout en conservant la fonctionnalité originale.
Service d'authentification
@IgnoreAuth
@PostMapping("/authentification")
public ResponseEntity connexion(String identifiant, String secret, String captcha, HttpServletRequest requete) {
UtilisateurEntity utilisateur = serviceUtilisateur.recupererParCondition(
new ConditionEntite<utilisateurentity>().eq("identifiant", identifiant)
);
if (utilisateur == null || !utilisateur.getMotDePasse().equals(secret)) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Identifiants incorrects");
}
String jetonAcces = serviceJeton.creerJeton(utilisateur.getId(), identifiant, "utilisateurs", utilisateur.getRole());
return ResponseEntity.ok().body(Collections.singletonMap("jeton", jetonAcces));
}</utilisateurentity>
@Override
public String creerJeton(Long idUtilisateur, String nomUtilisateur, String tableRef, String role) {
JetonEntity jetonExistant = recupererParCondition(
new ConditionEntite<jetonentity>().eq("idutilisateur", idUtilisateur).eq("role", role)
);
String nouveauJeton = GenerateurAleatoire.creerChaine(32);
Date maintenant = new Date();
Date expiration = DateUtils.addHeures(maintenant, 1);
if (jetonExistant != null) {
jetonExistant.setJeton(nouveauJeton);
jetonExistant.setDateExpiration(expiration);
mettreAJour(jetonExistant);
} else {
inserer(new JetonEntity(idUtilisateur, nomUtilisateur, tableRef, role, nouveauJeton, expiration));
}
return nouveauJeton;
}</jetonentity>
Intercepteur d'autorisation
@Component
public class IntercepteurAuthentification implements HandlerInterceptor {
private static final String CLE_JETON = "Authorization";
@Autowired
private ServiceJeton serviceJeton;
@Override
public boolean preHandle(HttpServletRequest requete, HttpServletResponse reponse, Object handler) throws Exception {
// Configuration CORS
reponse.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
reponse.setHeader("Access-Control-Max-Age", "3600");
reponse.setHeader("Access-Control-Allow-Origin", requete.getHeader("Origin"));
if (requete.getMethod().equalsIgnoreCase("OPTIONS")) {
reponse.setStatus(HttpServletResponse.SC_OK);
return false;
}
AnnotationIgnorerAuth annotationIgnorer;
if (handler instanceof HandlerMethod) {
annotationIgnorer = ((HandlerMethod) handler).getMethodAnnotation(AnnotationIgnorerAuth.class);
} else {
return true;
}
String tokenRecu = requete.getHeader(CLE_JETON);
if (annotationIgnorer != null) {
return true;
}
JetonEntity jetonValide = null;
if (StringUtils.hasText(tokenRecu)) {
jetonValide = serviceJeton.validerJeton(tokenRecu);
}
if (jetonValide != null) {
requete.getSession().setAttribute("idUtilisateur", jetonValide.getIdUtilisateur());
requete.getSession().setAttribute("role", jetonValide.getRole());
requete.getSession().setAttribute("nomUtilisateur", jetonValide.getNomUtilisateur());
return true;
}
reponse.setContentType("application/json;charset=UTF-8");
reponse.getWriter().write("{\"erreur\": \"Authentification requise\", \"code\": 401}");
return false;
}
}
Structure de la base de données
La table principale pour la gestion des jetons d'accès est définie comme suit :
CREATE TABLE jetons_acces (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
id_utilisateur BIGINT NOT NULL,
nom_utilisateur VARCHAR(100) NOT NULL,
table_reference VARCHAR(100),
role_utilisateur VARCHAR(100),
jeton VARCHAR(200) NOT NULL,
date_creation TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
date_expiration TIMESTAMP,
INDEX idx_utilisateur (id_utilisateur),
INDEX idx_jeton (jeton)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Des données exemple peuvent être insérées pour initialiser les sessions de test, avec des rôles différents tels que administrateur, vandeur et client.