You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- beanlànhữngmodulechínhcủachươngtrình,
đượctạoravàquảnlýbởiSpringIoCcontainer.
- Cácbeancóthểphụthuộclẫnnhau, nhưvídụvềDisplayHomeController,
CountServicevàcountComponent.
SựphụthuộcnàyđượcmôtảchoIoCbiếtnhờcơchếDependencyinjection.
- Dùng@Componentlênclasslàclassđólàmộtbean.
- KhiứngdụngSpringchạy, SpringIoCcontainersẽquéttoànbộpackages,
tìmracácbeanvàđưavàoApplicationContext. CơchếđólàComponentscanVídụvềbeanvàautowired:
@Service@Component//Khi chúng ta có nhiều bean cùng loại, //chúng ta sử dụng @Primary để ưu tiên cao //hơn cho một loại bean cụ thể@Primary@Qualifier("load")
publicclasscountComponentimplementsCountService {
privateintloadCounter;
@Bean(name = "load")
@OverridepublicintLoadCount() {
returnloadCounter++;
}
}
@Service@Component@Qualifier("load2")
publicclasscountComponent2implementsCountService {
privateintloadCounter;
@Bean(name = "load2")
@OverridepublicintLoadCount() {
loadCounter++;
returnloadCounter;
}
}
@Service@Component@Qualifier("load3")
publicclasscountComponent3implementsCountService {
@Bean(name = "load3")
@OverridepublicintLoadCount() {
return3;
}
}
@Getter@Setter@ControllerpublicclassDisplayHomeController {
privateCategoryJobServicecategoryJobService;
privateLaborServicelaborService;
privateJobServicejobService;
privateJobDetailServicejobDetailService;
privateJobDetailRepojobDetailRepo;
privateLaborRepolaborRepo;
privatePostServicepostService;
//countComponent countComponent2, countComponent3 là các bean// tương dương new countComponent();, countComponent2();, countComponent3();@Qualifier("load")
privateCountServicecountService;
@Qualifier("load2")
privateCountServicecountService2;
@Qualifier("load3")
privateCountServicecountService3;
//Sử dụng annotation @Autowired để báo cho Spring //biết tự động tìm và inject bean phù hợp vào vị //trí đặt annotation.@Autowired//injectpublicDisplayHomeController(CountServicecountService, CountServicecountService2, CountServicecountService3) {
this.countService = countService;
this.countService2 = countService2;
this.countService3 = countService3;
}
@GetMapping("/")
privateStringindex(){
System.out.println("Bean 1: "+countService.LoadCount());
System.out.println("Bean 2: "+countService2.LoadCount());
System.out.println("Bean 3: "+countService3.LoadCount());
}
}
Bean life cycle (Vòng đời của bean)
-Khởitạo(Instantiation): Tronggiaiđoạnnày,Springtạoramộtphiênbảnmớicủabean.Điềunàycóthểxảyrathôngquaviệctạomộtđốitượngmớihoặcthôngquaviệclấymộtđốitượngtừmộtnơikhác,chẳnghạntừmộtpoolđốitượng.-Thiếtlậpcácthuộctính(PopulateProperties): Saukhibeanđượctạora,Springsẽthiếtlậpcácgiátrịchocácthuộctínhcủabean,baogồmcácdependencyđượcinjectthôngquacácannotationnhư @Autowired.-Gọicáccallback(CallingCallbacks): Saukhicácthuộctínhđãđượcthiếtlập,Springsẽgọicáccallbackđểchophépbeanthựchiệncácthaotáckhởitạohoặctùychỉnh.Cáccallbacknàycóthểlà @PostConstruct(đượcgọisaukhibeanđượckhởitạovàtấtcảcácthuộctínhđãđượcthiếtlập)hoặccácphươngthứckhácdongườidùngđịnhnghĩa.-Sửdụngbean(BeanReadyforUse):
Beanởtrongtrạngtháisẵnsàngđểsửdụng.Ởgiaiđoạnnày,beancóthểđượcchiasẻvàsửdụngbởicácthànhphầnkháctrongứngdụng.-Hủybỏbean(BeanDestruction): KhiứngdụnghoặccontainerSpringbịđóng,hoặckhikhôngcòncầnthiếtnữa,Springsẽhủybỏbean.Tronggiaiđoạnnày,Springgọicáccallbackhủybỏđểchophépbeanthựchiệncáctácvụdọndẹphoặcgiảiphóngtàinguyên.ví dụ:
importjavax.annotation.PostConstruct;importjavax.annotation.PreDestroy;importorg.springframework.stereotype.Service;
@ServicepublicclassTaskService{privateExternalNotificationServicenotificationService;
@PostConstructpublicvoidinit(){// Kết nối đến hệ thống thông báo khi bean được khởi tạonotificationService=newExternalNotificationService();notificationService.connect();System.out.println("TaskService initialized");}publicvoidcreateTask(Tasktask){// Thực hiện tạo tác vụ và gửi thông báo// Sử dụng notificationService để gửi thông báonotificationService.sendNotification("New task created: "+task.getTitle());}// Các phương thức khác của TaskService
@PreDestroypublicvoidcleanup(){// Đóng kết nối đến hệ thống thông báo khi bean bị hủy bỏif(notificationService!=null){notificationService.disconnect();}System.out.println("TaskService cleanup");}}
@Modifying
Annotation @Modifying được sử dụng để chỉ định rằng truy vấn JPA hoặc
Hibernate hiện tại không phải là một truy vấn chỉ đọc mà là một truy vấn
sửa đổi dữ liệu (như INSERT, UPDATE, DELETE). Trong trường hợp này,
bạn đang thực hiện một truy vấn DELETE, vì vậy cần phải thêm @Modifying
để cho Spring Data JPA biết rằng đây là một truy vấn thay đổi dữ liệu.
@Transactional
Annotation @Transactional được sử dụng để chỉ định rằng phương thức
cần được thực hiện trong một giao dịch. Điều này đảm bảo rằng toàn
bộ quá trình thực thi phương thức sẽ được quản lý trong một giao dịch
và có thể được rollback nếu có lỗi xảy ra. Việc xóa dữ liệu là một hành động
thay đổi trạng thái của cơ sở dữ liệu, do đó, cần được thực hiện trong
một giao dịch để đảm bảo tính toàn vẹn của dữ liệu.
-Lifecyclecủacomponenttrongreactjslàquátrìnhtừkhitạora,thayđổivàhủybỏcomponent.Gồm3giai đoạn:
+Tạora(Mounting)-Ví dụ:
importReact,{useState}from'react';constView=()=>{return(<div>
Hello world!
</div>);};constApp=()=>{const[show,setShow]=useState(0);return(<div><buttononClick={()=>setShow(!show)}>Show</button>{show&&<View/>}</div>);};exportdefaultCounter;-TrongvídụnàykhibấmShowcomponentViewsẽđượcmountedvàrenderragiaodiện+Thayđổi(Updating)-Ví dụ:
importReact,{useState}from'react';constCounter=()=>{const[count,setCount]=useState(0);constincrement=()=>{setCount(prevCount=>prevCount+1);};return(<div><p>Count: {count}</p><buttononClick={increment}>Increment</button></div>);};exportdefaultCounter;-TrongtrườnghợpnàymỗikhiclickIncrementbiếncountsẽđượcupdategiátrịmớivàcomponentsẽupdating(rerender)lạivàthayđổigiátrịbiếncounttrêngiaodiện+Hủybỏ(UnMounting)-Ví dụ:
importReact,{useState}from'react';importReact,{useState,useEffect}from'react';constSlowComponent=()=>{const[count,setCount]=useState(0);useEffect(()=>{constfetchData=async()=>{try{// Một tác vụ chậm, ví dụ: gửi request mạngconstresponse=awaitfetch('https://api.example.com/slow-request');constdata=awaitresponse.json();console.log(data);setCount(count+1);}catch(error){console.error('Error:',error);}};fetchData();// Cleanup khi component unmountreturn()=>{// Hủy bỏ các tài nguyên không cần thiết ở đây, ví dụ: event listeners, subscriptionsconsole.log('Cleanup executed');};},[]);// Tham số thứ hai là mảng rỗng, chỉ chạy một lần sau khi component mountreturn(<div><p>Count: {count}</p></div>);};constApp=()=>{const[show,setShow]=useState(0);return(<div><buttononClick={()=>setShow(!show)}>Show</button>{show&&<SlowComponent/>}</div>);};-Trongvídụnàykhibấm"Show"thìSlowComponentsẽđượcmountvàrenderragiaodiệnsauđóbấmtiếp"Make Slow Request"thìhàmfetchDatasẽchạyvà1requestsẽgửiđitrongthờigianrequestgửiđinếubấmtiếp"Show"thìSlowComponentsẽbị(unmount)ẩnđilúcnàynếukcócleanuptronghàmuseEffectthìhàmfetchDatavẫnhoạtđộngđiềunàysẽlàmtiêutốntàinguyêncủaứngdụng
KNOWLEDGE HOOKS IN REACT JS
useState hook
-KhisửdụnguseStatereactsẽchophépcomponentrenderlạivàthayđổilạigiátrịmàchúngtamuốnhiểnthịragiaodiện.Cònnếuthựchiệnkiểugánbiếnbìnhthườngthìcomponentsẽkhôngrerendervàgiátrịmàchúngtamuốnhiểnthịragiaodiệnsẽkhôngthayđổi
ví dụ:
importReact,{useState}from'react';functionView(){//giá trị mặc định của biến name sẽ là Tuongconst[name,setName]=useState("Tuong");return(<div><p>My name: {name}</p><buttononClick={()=>{setName("Tran The Tuong");// sử dụng setName thì biến name sẽ cập nhật// lại thành Tran The Tuong và component sẽ re render lại và hiển thị // ra Tran The Tuong//name = "Tran The Tuong" còn nếu làm thế này thì biến name vẫn sẽ//cập nhật thành Tran The Tuong tuy nhiên component sẽ không re render // nên giá trị hiển thị ra vẫn là Tuong}}>
Click me
</button></div>);}
useEffect hook
-KhisửdụnguseEffectchúngsẽphảitruyềnvàohàmcallback-HàmcallbacktronguseEffectsẽluônđượcgọikhicomponentmountedrerender-KhidùnguseEffectsẽcó3trườnghợpmàchúngtasửdụngđếnđólànhữngtrg hợp sau:
useEffect(()=>{});+sửdụnguseEffectchỉtruyềnvàohàmcallbackuseEffect(()=>{},[]);+sửdụnguseEffecttruyềnvào1mảngrỗnguseEffect(()=>{},[depen]);+sửdụnguseEffecttruyềnvào1mảngchứacácdependency(sựphụthuộc)+Hàmcallbacksẽđượcgọilạimỗikhidependencythayđổi+ví dụ:
importReact,{useState}from'react';functionView(){const[name,setName]=useState("");const[type,setType]=useState("posts");// Mỗi lần gõ vào input component // sẽ (mounted) re render lại và// hàm callback sẽ được gọi// Hàm useEffect sẽ thực thi sau khối lệnh returnuseEffect(()=>{// gõ vào input 10 lần Mounted sẽ in ra 10 lầnconsole.log("Mounted");});useEffect(()=>{//Mounted sẽ in ra 1 lần mỗi khi component mounted và renderconsole.log("Mounted!!!");},[]);useEffect(()=>{//api sẽ được gọi mỗi khi component mount// và mỗi lần biến type sẽ thay đổi// api sẽ được gọi trong trg hợp này// biến type đã đc truyền vào là dependency//api sẽ mặc định gọi posts vì biến type//có giá trị mặc định là posts//khi type thay đổi component sẽ re render ra//giá trị thay đổi theo biến typefetch("https://jsonplaceholder.typicode.com/"+type).then(res=>res.json()).then(apis=>{setApi(apis);});//trường hợp này change name vẫn sẽ in ra mỗi khi//component mount tuy nhiên khi 1 biến khác không//phải dependency là biến name mà thay đổi thì//component sẽ re render nhưng change name không được//in ra còn nếu biến name thay đổi thì change name//sẽ được in ra ví dụ:// gõ vào input name 10 lần thì change name sẽ in ra 10 lầnconsole.log("change name");},[type]);//trường hợp này Mounted vẫn sẽ in ra mỗi khi//component re render nó sẽ được gọi// trước khối lệnh return// Tuy nhiên nếu khối lệnh gọi trc này lỗi// điều đó sẽ làm lỗi ứng dụng//đây là 1 ví dụ:console.log(a);leta=1;console.log("Mounted");return(<div>{tabs.map(tab=><buttonstyle={type===tab ? {background: "#333",color: 'white'} : {}}onClick={()=>{setType(tab);}}key={tab}>{tab}</button>)}{/*Khối lệnh thực thi này sẽ thực thi trước useEffect*/}{console.log(name)}<inputvalue={title}onChange={e=>setName(e.target.value)}/></div>);}
Ask and Answer
1.OnclicktrênhtmlkhácgìvớionclicktrênJS=>2.Submitformcónhữngcáchnào ? (Onsubmitvàonclick)=>Onsubmitvàonclick3.XửlýbấtđồngbộtrongcallAPInhưthếnào ?
=>cáchxửlýbấtđồngbộtrongcallAPIlàsửdụngpromisetrongpromisesẽcó3hàmhanderlà.then(),.catch()và.finally()-.then()sẽchạykhiPromisethànhcông.ĐôikhibạncũngcóthểsửdụngđểxửlýtrạngtháithấtbạicủaPromise.-.catch()sẽchạychỉkhiPromisethấtbại.-.finally()sẽchạykhiPromisechạyxong,khôngquantrọnglàthànhcônghaythấtbại.-sửdụngAsync/await-Cáchcuốicùngđểxửlýbấtđồngbộlàsửdụngasync/await.Async/awaitđượcgiớithiệuởES8,chúngđượccấutạotừ2phần.Phầnđầutiênlàfunctionasync.Hàmnàysẽđượctựđộngthựcthibấtđồngbộ.GiátrịnótrảvềlàmộtPromise.VìtrảvềPromisenênbạnsẽphảisửdụngcáchandlercủaPromiseđểxửlýgiátrịnày.-Phầnthứhaicủaasync/awaitlàoperatorawait.OperatornàysẽđượcdùngcùngvớimộtPromise.NósẽkhiếnchofunctionasynctạmdừngchođếnkhiPromiseđóchạyxong.NgaysauđónósẽlấygíatrịcủaPromisemàchofunctionasynctiếptụcchạy.-Cácfunctionasyncđềubấtđồngbộ,khibịpausebởiawaitthìphầncodecònlạivẫnchạybìnhthườngvìfunctionđấykhôngblockmainthread.KhiPromisechạyxongthìhàmasyncsẽchạytiếpvàtrảvềgiátrịcủaPromise.-Mộtđiềuquantrọnghơnlàawaitphảiđượcviếttronghàmasyncnếukhôngthìsẽgặplỗisyntaxerror.-example :
asyncfunctionmakeAPICall(){// Show notification about API callconsole.log('Bắt đầu gọi API.');// Create a Promise to make the API callconstdataPromise=newPromise((resolve,reject)=>{setTimeout(()=>{console.log('Nhận data từ API.');resolve('Gọi API thành công.');},2000);});returndataReceived=awaitdataPromise}functionprocessAPIData(){console.log('Xử lý data');};functionreadTheData(){console.log('Đọc data.');};// Hàm này sẽ chạy ngay sau async makeAPICall// và chạy trước tất cả các hàm khác.functionsomeOtherFunction(){console.log('Some other function not related to API.')}makeAPICall// add handle cho status thành công.then(result=>{console.log(result);processAPIData();readTheData();})// add handle cho status thất bại.catch(error=>{console.log(`Có lỗi xảy ra: ${error}.`)})// bạn có thể thêm finally() ở đây// .finally(() => {})someOtherFunction();4.Submitformbằngonsubmitthìdatagửivềserverđượctạorabằngcáchnào ?
=>5.Chobàitoán : a=[1,2,3,4];b=a;a[0]=5;hỏib[0]=mấy ? Giảithích ?
=>bgánchoavàa[0]=5thìb[0]=56.GETkhácPOSTchỗnào ? CóthểdùngPOSTbằngGETđượckhông ?
=>GETkhácPOSTởchỗlàGETlàdùngđểlấydữliệu(data)cònPOSTlàpushthêmdữliệu7.Truthyvàfalsy ?
=>8.Kếtquảcủa(true&&false||true||false&&true)làgì ?
=>true,vìsẽưutiênlấytruenêncặp1làtrue&&falselấytrue,2làtrue,3làfalse&&truesẽlấytruenên=>true||true||true.Kếtquảbằng=true