1. Trang chủ
  2. » Ngoại Ngữ

Développement d’un moteur de planification dans lenvironnement J2EE weblogic

64 118 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 64
Dung lượng 2,77 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Les liens entre la base de données et les fichiers clients .... IFI Solution et l’IFI ont ainsi une coopération active, démontrée par la cérémonie des « Top IFI Awards » qui a lieu tous

Trang 1

 

 

  

Hanoi, Vietnam 

Trang 2

 

Trang 3

Table des matières 

 

1.  Remerciements   7 

2.  Résumé   8 

3.  Abstract   9 

4.  Introduction   10 

5.  Présentation du cadre du stage   11 

5.1.  Présentation du Vietnam   11 

5.2.  Présentation de l’entreprise   12 

5.3.  Contexte de travail   15 

5.3.1  L’équipe   15 

5.3.2  L’environnement de travail   15 

5.3.3  La langue   15 

6.  Présentation du projet   16 

6.1.  Cahier des charges   16 

6.2.  L’architecture de l’application   17 

6.3.  Le déroulement du stage   18 

6.4.  Les liens entre la base de données et les fichiers clients   19 

6.5.  La base de données   22 

6.6.  Les besoins de l’application   23 

Trang 4

6.7.  Les solutions pour le projet   23 

6.7.1  Les ordonnanceurs en Java  23 

6.7.1.1  Qu’est qu’un ordonnanceur ?   23 

6.7.1.2  Planification de tâches avec le JDK ( API Timer)   24 

6.7.1.3  Quartz   25 

6.7.1.4  Au final, quelle solution choisir ?   27 

6.7.1.5  Un exemple de planification avec Quartz   28 

6.7.2  L’accès à la base de données avec hibernate   30 

6.7.2.1  Pourquoi utiliser hibernate ?   31 

6.7.2.2  Présentation   31 

6.7.2.3  Utilisation   32 

7.  Le moteur PortailTV   37 

7.1.  Les composants du moteur  37 

7.2.  Les diagrammes de classes   39 

7.2.1  Connexion   39 

7.2.2  Accès à la base de données (util)   40 

7.2.3  Le moteur   41 

7.2.4  Les servlets   42 

7.2.5  Les classes de mapping   42 

7.3.  La connexion au serveur FTP   43 

7.4.  Manipulation des fichiers CSV   44 

7.5.  Le fonctionnement du moteur de PortailTV   44 

7.6.  Exécution des tâches sur le serveur BEA Weblogic   45 

7.7.  Les fichiers de configuration   48 

7.8.  Les difficultés rencontrées   49 

Trang 5

8.  Conclusion   50 

Trang 6

 

Figure 1 : compétences au sein d’IFI Solution   13 

Figure 2 : les secteurs dans lesquelles IFI Solution travaille   14 

Figure 3 : architecture de l’application Portail TV   17 

Figure 4 : description des fichiers profile clients   19 

Figure 5 : exemple de fichier profile client   19 

Figure 6 : description des fichiers « détails clients »   20 

Figure 7 : exemple de fichier « détails clients »   20 

Figure 8 : description des fichiers « détails consommation »   21 

Figure 9 : exemple de fichier « détails consommations »   21 

Figure 10 : description des fichiers « prévisions météo »   21 

Figure 11 :  exemple de fichier « prévision météo »   22 

Figure 12 : description de fichier « météo »   22 

Figure 13 : exemple de fichier « météo »   22 

Figure 14 : Job « Hello World »   30 

Figure 15 : architecture hibernate   32 

Figure 16 : diagramme de classes de la connexion   39 

Figure 17 : diagramme de classe pour l’accès à la base de données   40 

Figure 18 : diagramme de classes du moteur   41 

Figure 19 : diagramme de classes "servlet"   42 

Figure 20 : classe SuiviConsoGaz   43 

Figure 21 : classes de mapping de la base de données   43 

Figure 22 : exemple de fichier CSV   44 

Figure 23 : administration pour la planification des tâches   48   

 

 

 

Trang 7

Je  tiens  tout  d’abord  à  remercier  Monsieur  Dinh  Van  Hoan,  mon  responsable  de  stage  au sein de la société IFI Solution. Il s’est montré très disponible durant cinq mois. J’ai pu, grâce à lui,  progresser,  le  questionner  lorsque  j’avais  des  difficultés.  Mes  remerciements  vont également aux employés d’IFI Solution qui m’ont apporté leur aide semaine après semaine durant  toute  la  durée  de  mon  stage  et  plus  particulièrement  Mademoiselle  Tran  Thi  Ngoc Tram et Monsieur Quan. 

Je remercie également Monsieur Alain BOUCHER, Directeur des études de l’IFI et Monsieur 

Ho Tuong Vinh qui m’ont permis d’effectuer ce stage, sans oublier l’équipe enseignante pour leur aide. 

Enfin, mes remerciements vont à Monsieur Rémy Mullot à qui je dois de bénéficier de cette expérience au Vietnam. 

 

Trang 8

2 Résumé 

Ce mémoire est l’aboutissement de cinq mois de stage au sein de la société IFI Solution. Il entre dans le cadre de ma formation en Master, au sein de l’Institut de la Francophonie pour l’Informatique, en partenariat avec l’université de La Rochelle. 

Le  projet  sur  lequel  j’ai  travaillé  provient  d’une  demande  effectuée  par  Edelia  (filiale  du groupe EDF).  Nommé Portail TV, il a pour but de permettre aux clients EDF de visualiser leur consommation d’énergie (électricité, gaz, eau) via un écran de télévision ou internet. Cette application a également pour objectif de diminuer les consommations d’énergie. En effet, le client pourra recevoir des alertes en cas de dépassement d’un niveau de consommation fixé.  

On  distinguera  plusieurs  parties  dans  cette  application.  En  effet,  il  faudra  dans  un  premier temps  récupérer  toutes  les  informations  concernant  les  clients,    traiter  ces  données  et  les insérer dans la base centrale de données. L’objectif sera ensuite de permettre au client de visualiser sa consommation, sa prévision et toutes les données le concernant. 

 

Mots‐clés : Développement, J2EE, Java, Hibernate, JSP, Servlets. 

Trang 9

3 Abstract 

This  memory  is  the  result  of  five  months  spent  training  in  the  company  IFI  Solution.  This 

course  falls  within  the  framework  of  my  Master  at  the  French  Speaking  Institute  for 

Trang 10

Le projet réalisé conjointement avec Thibaud FAURE devait utiliser les données des clients et ensuite leur permettre de visualiser ses données via un écran de télévision ou internet. A la demande  du  client,  les  contraintes  imposées  était  d’utiliser  l’architecture  SOA  (service‐

 

Trang 11

5 Présentation du cadre du stage 

5.1 Présentation du Vietnam 

Une  des  particularités  de  ce  stage  réside  dans  le  fait  qu’il  s’est  déroulé  au  Vietnam.  Il  me paraît important de parler de ce pays, dont les coutumes de vie, culture d’entreprise et vie culturelles sont différentes de ce que je connais en France. 

C’est  donc  une  expérience  extrêmement  enrichissante  autant  sur  le  plan  de  l’expérience professionnelle que du point de vue sociologique.  

Voici une présentation succincte du Vietnam :  

Le Vietnam et sa République Socialiste est l'un des pays de l'Asie du Sud‐Est qui connait une   des plus importantes croissances économiques avec plus de 8% en 2007 ; une enquête socio‐économique en Asie‐Pacifique rapporte que le Vietnam poursuivra son développement sur 

Trang 12

5.2 Présentation de l’entreprise 

 

Fondée début 2003, la société IFI Solution, située à Hanoi au Vietnam, est spécialisée dans le développement  informatique  en  offshore.  Ses  clients  sont  donc  principalement  des entreprises européennes souhaitant externaliser un projet à l’étranger. Elle a été créée par des  anciens  étudiants  de  l’IFI  et  a  donc  maintenant  plus  de  6  ans  d’expérience  dans  les services de sous‐traitance de logiciel. 

La société propose un éventail de services d’offshore programming qui sont divisés en trois catégories  :  le  développement  logiciel,  la  certification/vérification,  et  le  développement Web. 

Elle  est  bien  sûr  en  mesure  de  développer  tous  ses  projets  sur  plates‐formes  Windows, Linux/Unix et Mac OS. Grâce à l’accomplissement de travaux dans des domaines très variés, IFI  Solution  a  su  acquérir  de  l’expérience  et  de  la  notoriété.  Que  ce  soit  dans  le  domaine médical, de l’aviation, des télé‐services ou des grands groupes industriels, sa polyvalence et ses  compétences  lui  permettent  de  répondre  à  de  nombreuses  offres.  Elle  fait  ainsi  partie des dix meilleures entreprises du Vietnam dans le domaine de la sous‐traitance de logiciels pour des entreprises européennes. Elle est également numéro un dans la sous‐traitance de logiciels embarqués pour le marché français. 

Les  différentes  compétences  que  possèdent  les  employés  d’IFI  Solution  sont  répertoriées dans le tableau ci‐dessous : 

Trang 13

Figure 1 : compétences au sein d’IFI Solution 

A ce jour, l’objectif d’IFI Solution est de devenir un leader de l’offshore informatique et de conquérir de nouveaux clients issus des petites et moyennes entreprises en Europe et aux États‐Unis. 

Les  ingénieurs  d’IFI  Solution  sont  diplômés  des  prestigieuses  universités  vietnamiennes  et étrangères,  dont  fait  partie  l’IFI.  Ils  ont  pour  la  plupart  un  Master  Informatique,  et  ont  eu une ou plusieurs expériences professionnelles à l’étranger. De plus, au sein de l’entreprise, 

tous les employés sont conduits à parler en Anglais, voire en Français pour ceux d’entre eux 

l’ayant étudié au Vietnam ou pratiqué durant leur stage de fin d’études en France (de deux mois à quatre ans). 

IFI Solution et l’IFI ont ainsi une coopération active, démontrée par la cérémonie des « Top IFI Awards » qui a lieu tous les ans et durant laquelle des étudiants de l’IFI reçoivent des prix 

de  la  part  d’IFI  Solution,  prix  décernés  aux  étudiants  du  Master  de  l'IFI  qui  ont  obtenu  les meilleurs résultats dans les modules jugés utiles pour leur réussite au sein d'une entreprise. Ces « Awards » sont donc décernés pour les meilleurs résultats dans les cours "Génie logiciel avancé"  et  "Français  et  communication"  ainsi  qu’à  l’étudiant  ayant  eu  la  meilleure progression dans le cours "Français et communication". 

Trang 14

IFI  Solution  a  depuis  2003  acquis  des  connaissances  dans  les  domaines  et  secteurs répertoriés dans le tableau qui suit : [8] 

 

Figure 2 : les secteurs dans lesquelles IFI Solution travaille 

De  plus,  IFI  Solution  a  obtenu  la  normalisation  ISO  9001  :  2000  ,  apportant  une  vision sérieuse  de  leur  entreprise  vis‐à‐vis  de  leurs  clients  actuels  ou  clients  potentiels.  En  effet, cette  norme  spécifie  les  exigences  relatives  au  système  de  management  de  la  qualité lorsqu'un organisme : 

1. doit démontrer son aptitude à fournir régulièrement un produit conforme aux exigences des clients et aux exigences réglementaires applicables, 

2.  vise  à  accroître  la  satisfaction  de  ses  clients  par  l'application  efficace  du  système,  y compris  les  processus  pour  l'amélioration  continue  du  système  et  l'assurance  de  la conformité aux exigences des clients et aux exigences réglementaires applicables. 

Trang 15

5.3 Contexte de travail 

5.3.1 L’équipe 

Mon stage s’est déroulé sous la responsabilité de Mr DINH Van Hoan, mon tuteur de stage 

au sein d’IFI Solution. Dans ce cadre, il simulait les attentes du client, de sorte que, chaque semaine,  un  rapport  ainsi  qu’une  discussion  à  propos  de  l’avancement  du  projet  soient effectués. 

Trang 17

Base de données 

Station météo 

Fichiers CSV 

Figure 3 : architecture de  l’application Portail TV  

Trang 18

 Le  schéma  de  l’application  désirée  se  compose  comme  suit.  Le  client  va  envoyer  ses 

données  de  consommation  par  l’intermédiaire  d’un  modem ;  celles‐ci  seront  envoyées  de 

manière  journalière  au  serveur  FTP.  Les  données  météo  seront  également  envoyées  de  la 

que  les  servlets  dans  un  environnement  de  développement  Eclipse.  Cette  démarche,  qui 

s’est  déroulée  sur  plusieurs  semaines,  m’a  permis  de  faire  connaissance  avec  l’équipe  du 

Découverte de l’entreprise, des projets déjà

réalisés Réalisation d’u planning Travail sur

Trang 19

Le  codage  et  le  déploiement  sous  Weblogic  8.1  se  sont  avérés  plus  longs  que  prévu  en  raison d’un mauvais choix de l’environnement de développement : utilisation de Java 1.5 au lieu de Java 1.4.2.  

6.4 Les liens entre la base de données et les fichiers  clients 

Voici les fichiers clients présents sur le serveur FTP  qu’il faut utiliser afin de mettre à jour la base de données : 

Trang 22

6.5 La base de données 

Elle  comporte  un  grand  nombre  de  classes  mais  seules  certaines  nous  seront  utiles.  Un problème  intervient  assez  rapidement :  les  fichiers  d’entrées  ne  correspondent  pas exactement  à  la  base  de  données.  En  effet,  les  fichiers  exemples  ne  proviennent  pas  de France et ne sont pas similaires aux champs de la base. Avec l’aide des chefs de projets qui 

Trang 23

6.6 Les besoins de l’application 

Cette application est destinée au client Edelia (filiale d’EDF).  Il faut donc prévoir un grand nombre  d’utilisateurs.  Les  fichiers  présents  sur  le  serveur  FTP  sont  donc  volumineux  et comportent  un  grand  nombre  d’enregistrements.  Il  y  aura  donc  une  contrainte  de performance  qui  va  apparaỵtre.  En  effet,  un  client  Edelia  doit  pouvoir  consulter  sa consommation dans les 24 heures suivant l’envoi de ses données de consommation.  

Pour  éviter  de  surcharger  le  réseau  et  utiliser  de  la  bande  passante  inutilement,  on  va planifier les tâches de téléchargement de fichiers et de mise à jour de base de données. D’ó 

le  besoin  de  moteur  de  planification.  Ceci  permet  également  d’effectuer  des  tâches  sans intervention humaines. 

Un autre point important est la réutilisabilité de l’application. En effet, les fichiers en entrée peuvent  être  changés  ainsi  que  la  base  de  données.  Le  code  doit  donc  être  réutilisable facilement. C’est pour cela qu’il faut choisir les solutions adéquates. 

6.7 Les solutions pour le projet 

Une des fonctionnalités de l’application était la planification de tâches. Plusieurs solutions se sont  donc  présentées  à  moi.  Une  précision  qu’il  est  utile  de  rajouter  est  que  la  méthode choisie devait être gratuite. J’ai donc effectué une longue recherche sur les solutions les plus adéquates  afin  de  planifier  des  tâches  en  Java,  l’objectif  final  étant  de  choisir  la  mieux adaptée à l’application. 

Trang 24

ne pas détériorer les temps de réponse. Depuis la version 1.4, java permet d'effectuer des planifications  de  tâche  simples.  Cependant  les  applications  d'entreprise  exigent  des possibilités  de  reprise  après  panne,  haute  disponibilité,  etc…  C'est  ce  que  propose  Quartz, une librairie open‐source. [1] 

Le  Timer,  comme  tous  les  scheduler  ne  peut  pas  empêcher  l’apparition  des  retards.  Mais généralement les schedulers proposent des solutions pour les minimiser ou les contourner 

en amortissant le retard d’une tâche sur les suivantes, quitte à ne pas respecter un intervalle défini. De plus la probabilité et le temps moyen des retards augmentent avec le nombre de tâches, surtout si plusieurs sont programmées en même temps. Et dans ce cas, le Timer n’est pas  adapté.  La  raison  réside  dans  son  implémentation.  Il  dispose  d’une  file  d’attente  de tâches ordonnées par date croissante de prochain démarrage et d’un thread de traitement. L’algorithme implémenté est simple : le thread se met en attente de la première tâche de la file. Lorsque la date d’exécution est atteinte, le thread appelle la méthode run(), met à jour 

la  prochaine  date  d’exécution  de  la  tâche  et  se  remet  en  attente.  La  présence  d’un  seul thread  de  traitement  interdit  d’optimiser  les  exécutions  concurrentes  de  tâches. Malheureusement  ce  mode  d’utilisation  est  fréquent  sur  les  applications  d’entreprise, généralement  distribuées.  Dans  une  application  distribuée  plusieurs  tâches  peuvent 

Trang 25

facilement s’exécuter en parallèle pour optimiser l’utilisation des ressources. Une tâche peut effectuer un calcul tandis qu’une seconde effectue des requêtes sur une base de données, et une  troisième  effectue  un  transfert  de  fichier…  Le  Timer  n’est  donc  pas  optimal  dans  ce genre d’application, mais tel n’est pas son but, d’autant qu’il existe une spécification pour un Timer « j2ee » géré par un conteneur de serveur d’application. D’autres points font du Timer 

    Quartz  est  une  librairie  java  offrant  des  fonctions  de  planification  de  tâches.  Elle  est 

développée  par  le  projet  open  source  OpenSymphony  qui  est  responsable  d’une  dizaine d’autres  sous‐projets  tel  que  WebWork.  Ces  sous‐projets  sont  principalement  dans  le domaine  du  développement  de  composants  J2EE  en  recherchant  avant  tout  la  simplicité d’intégration et d’utilisation. 

Il peut être autant utilisé sur des projets de grande envergure que sur de petits projets et permet la planification simple et complexe de tâches. A titre d’exemple, vous pouvez définir qu’une tâche soit exécutée tous les jours à telle heure, toutes les 24 heures, ou bien encore   tous les lundis et mercredis de chaque semaine. Dès lors, Quartz  permet un large éventail 

de possibilités au niveau des planifications et peut répondre ainsi aux besoins de chacun, au cas par cas. 

Trang 26

Quartz  permet  donc  d’exécuter  à  des  moments  très  précis  des  tâches  qui  seraient  par exemple  nécessaires  pour  effectuer  de  la  maintenance  quotidienne,  des  migrations  de données ou encore le nettoyage répétitif de répertoires données[3]. 

Voici une liste non‐exhaustive des possibilités de planification: 

• Planification  fournissant  un  paramétrage  très  fin.  On  peut  faire  des  tâches 

ponctuelles à une date précise, des tâches répétitives avec un nombre de répétitions paramétré  et  un  délai  entre  chaque  appel,  ou  bien  utiliser  une  expression  cron (chaîne de caractères) pour des planifications plus précises. 

• Séparation  entre  les  tâches  exécutables  ("Jobs")  et  les  planifications  ("Triggers"). 

On en tire une grande souplesse dans la gestion de l'ordonnancement. 

• Gestion  d'erreur.  Les  Jobs  peuvent  remonter  des  JobExecutionException  qui 

indiquent  le  comportement  à  adopter  par  le  Scheduler.  On  peut  relancer  le  Job immédiatement, supprimer le trigger qui l'a invoqué ou supprimer tous les Triggers. 

On peut aussi définir un comportement pour une planification ratée (ie. pas exécutée 

à la bonne date). 

• Jobs  avec  ou  sans  états.  Quartz  gère  les  données  afférentes  aux  tâches  dans  un 

JobDataStore  qui  permet  à  chacune  des  tâches  de  récupérer  des  paramètres  et/ou 

de modifier des données de son contexte. Pour chaque Job, on peut spécifier si les données doivent être maintenues entre chaque appel ou non. Notez bien qu'un Job StateFull ne peut s'exécuter en mode parallèle. 

• Persistance  des  Jobs.  On  peut  configurer  Quartz  pour  sauvegarder  en  base  de 

Trang 27

• Le multithreading : il prend en charge plusieurs tâches afin de pouvoir les gérer en parallèle. 

• La persistance des tâches : celle‐ci permet de garder en mémoire l'ordonnancement dans le cas d'une panne de machine par exemple.[4] 

En outre, Quartz s'inscrit dans le projet OpenSymphony. Quartz est opensource et se trouve entièrement compatible avec Apache Software License ou encore avec le serveur Weblogic. Enfin, l'installation est très simple. Il suffit de télécharger Quartz puis d'ajouter les librairies suivantes dans le classpath de l'application : 

• lib/quartz.jar [librairie principale] 

• lib/commons‐logging.jar 

• lib/quartz‐weblogic.jar 

6.7.1.4 Au final, quelle solution choisir ? 

Trang 28

6.7.1.5 Un exemple de planification avec Quartz 

Il  existe  principalement  trois  types  d’objets  :  le  Scheduler,  les  Jobs  et  les  Triggers.  Un  Job (travail)  représente  une  tâche  à  exécuter,  un  Trigger  (déclencheur),  le  mécanisme  de planification  d’une  tâche.  Concernant  les  relations,  un  job  peut  être  utilisé  par  plusieurs trigger, mais un trigger n’est associé qu’à un seul job. 

La classe Test correspond à l’ordonnanceur (scheduler). On va déclarer chaque tâche qu’on souhaite  exécuter  et  avec  quel  intervalle  de  temps.  Dans  l’exemple  suivant  la  tâche  ou encore  le  job  sera  exécuté  toutes  les  20  secondes,  ceci  étant  défini  dans  l’expression  cron suivante : "0/20 * * * * ?". 

public class Test {

public void run() throws Exception {

SchedulerFactory sf = new StdSchedulerFactory();

Scheduler sched = sf.getScheduler();

JobDetail job = new JobDetail("job1", "group1",

HelloWorld.class);

CronTrigger trigger = new CronTrigger("trigger1",

"group1", "job1","group1", "0/20 * * * * ?");

trigger.setPriority(10);

sched.addJob(job, true );

Trang 29

Date ft = sched.scheduleJob(trigger);

* Quartz requires a public empty constructor so that the

* scheduler can instantiate the class whenever it needs

// This job simply prints out its job name and the

// date and time that it is running

String jobName = context.getJobDetail().getFullName();

System.out.println("Job download says Hello World: " jobName

+ " executing at " new Date());

}

}

Le  résultat de  l’exécution  de  cet  exemple  sous  l’environnement  de  développement  Eclipse est le suivant : 

Trang 30

Figure 14 : Job « Hello World »

 

Le job « HelloWorld » est bien exécuté toutes les 20 secondes comme on peut le voir sur la console Eclipse. 

Dans  cet  exemple,  un  seul  job  est  lancé  ce  qui  n’est  pas  le  cas  dans  notre  application.  On utilisera donc un système de priorité afin de gérer les accès concurrents. 

Trang 31

6.7.2.1 Pourquoi utiliser hibernate ? 

Hibernate  va  permettre  d’améliorer  la  communication  entre  une  base  de  données relationnelle (celle utilisée) et l’univers objet. Sans utilisation de ce type de framework, on fait face à des problèmes de performance et des développement onéreux. 

Les fonctionnalités du framework hibernate et ses avantages sont divers. En voici une liste : 

• gère la persistance des données 

• abstraction de la couche de données 

• permet la communication entre bases de données relationnelles et environnement objet 

Dans  notre  cas,  le  framework  hibernate  permettra  de  rendre  l’application  évolutive (notamment  si  l’on  souhaite  changer  de  base  de  données),  mais  également  de  gagner  du temps  en  développement  et  enfin  il  améliorera  les  performances  lorsqu’il  s’agira  de manipuler un volume important de données. 

6.7.2.2 Présentation 

Hibernate  est  un  framework  open  source  gérant  la  persistance  des  objets  en  base  de données relationnelles. 

Hibernate est adaptable en termes d'architecture, il peut donc être utilisé aussi bien dans un développement client lourd, que dans un environnement web léger de type Apache Tomcat 

Trang 32

de BEA Weblogic. 

Il apporte une solution aux problèmes d'adaptation entre le paradigme objet et les SGBD en remplaçant  les  accès  à  la  base  de  données  par  des  appels  à  des  méthodes  objet  de  haut niveau[5]. 

de données relationnelle) est définie par un fichier xml, d'ó mapping objet‐relationnel. 

6.7.2.3 Utilisation 

L’utilisation d’hibernate nécessite plusieurs étapes : 

¾ Création du fichier de configuration xml. 

Ngày đăng: 27/10/2016, 22:55

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w