{"id":89046,"date":"2025-07-06T23:27:24","date_gmt":"2025-07-06T16:27:24","guid":{"rendered":"https:\/\/itviec.com\/blog\/?p=89046"},"modified":"2025-07-06T23:27:27","modified_gmt":"2025-07-06T16:27:27","slug":"spring-mvc-la-gi","status":"publish","type":"post","link":"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/","title":{"rendered":"Spring MVC l\u00e0 g\u00ec: H\u01b0\u1edbng d\u1eabn x\u00e2y d\u1ef1ng \u1ee9ng d\u1ee5ng v\u1edbi Spring MVC"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_85 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">N\u1ed9i dung b\u00e0i vi\u1ebft<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/#Spring_MVC_la_gi\" >Spring MVC l\u00e0 g\u00ec?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/#Kien_truc_cot_loi_cua_Spring_MVC\" >Ki\u1ebfn tr\u00fac c\u1ed1t l\u00f5i c\u1ee7a Spring MVC<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/#Cac_khai_niem_va_tinh_nang_quan_trong_cua_Spring_MVC\" >C\u00e1c kh\u00e1i ni\u1ec7m v\u00e0 t\u00ednh n\u0103ng quan tr\u1ecdng c\u1ee7a Spring MVC<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/#Xay_dung_ung_dung_voi_Spring_MVC_co_ban\" >X\u00e2y d\u1ef1ng \u1ee9ng d\u1ee5ng v\u1edbi Spring MVC c\u01a1 b\u1ea3n&nbsp;<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/#11_nguyen_tac_ap_dung_Spring_MVC_hieu_qua\" >11 nguy\u00ean t\u1eafc \u00e1p d\u1ee5ng Spring MVC hi\u1ec7u qu\u1ea3<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/#Tuong_lai_cua_Spring_MVC_va_he_sinh_thai_Spring\" >T\u01b0\u01a1ng lai c\u1ee7a Spring MVC v\u00e0 h\u1ec7 sinh th\u00e1i Spring<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/#Cac_cau_hoi_thuong_gap_ve_Spring_MVC\" >C\u00e1c c\u00e2u h\u1ecfi th\u01b0\u1eddng g\u1eb7p v\u1ec1 Spring MVC<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/#Tong_ket\" >T\u1ed5ng k\u1ebft<\/a><\/li><\/ul><\/nav><\/div>\n\n<p><strong><em>Trong th\u1ebf gi\u1edbi ph\u00e1t tri\u1ec3n \u1ee9ng d\u1ee5ng web b\u1eb1ng Java, Spring MVC n\u1ed5i l\u00ean nh\u01b0 m\u1ed9t trong nh\u1eefng framework m\u1ea1nh m\u1ebd v\u00e0 ph\u1ed5 bi\u1ebfn nh\u1ea5t. Vi\u1ec7c n\u1eafm v\u1eefng Spring MVC kh\u00f4ng ch\u1ec9 l\u00e0 h\u1ecdc m\u1ed9t c\u00f4ng c\u1ee5, m\u00e0 l\u00e0 ti\u1ebfp c\u1eadn m\u1ed9t ph\u01b0\u01a1ng ph\u00e1p lu\u1eadn \u0111\u1ec3 ph\u00e1t tri\u1ec3n \u1ee9ng d\u1ee5ng web m\u1ed9t c\u00e1ch c\u00f3 t\u1ed5 ch\u1ee9c v\u00e0 hi\u1ec7u qu\u1ea3.<\/em><\/strong><\/p>\n\n\n\n<p>\u0110\u1ecdc b\u00e0i vi\u1ebft n\u00e0y \u0111\u1ec3 hi\u1ec3u r\u00f5 h\u01a1n v\u1ec1:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>T\u1ed5ng quan v\u1ec1 Spring MVC v\u00e0 l\u1ee3i \u00edch c\u1ee7a n\u00f3<\/li>\n\n\n\n<li>Ki\u1ebfn tr\u00fac c\u1ed1t l\u00f5i c\u1ee7a Spring MVC<\/li>\n\n\n\n<li>C\u00e1c kh\u00e1i ni\u1ec7m v\u00e0 t\u00ednh n\u0103ng quan tr\u1ecdng&nbsp;<\/li>\n\n\n\n<li>X\u00e2y d\u1ef1ng \u1ee9ng d\u1ee5ng v\u1edbi Spring MVC c\u01a1 b\u1ea3n&nbsp;<\/li>\n\n\n\n<li>\u1ee8ng d\u1ee5ng th\u1ef1c ti\u1ec5n v\u00e0 m\u1eb9o s\u1eed d\u1ee5ng Spring MVC<\/li>\n\n\n\n<li>T\u01b0\u01a1ng lai c\u1ee7a Spring MVC v\u00e0 h\u1ec7 sinh th\u00e1i Spring<\/li>\n<\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>\u0110\u1ecdc chi ti\u1ebft: <strong><a href=\"https:\/\/itviec.com\/blog\/spring-framework-la-gi\/\" target=\"_blank\" rel=\"noreferrer noopener\">Spring l\u00e0 g\u00ec? Spring Framework l\u00e0 g\u00ec?<\/a><\/strong><\/em><\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-spring-mvc-la-gi\"><span class=\"ez-toc-section\" id=\"Spring_MVC_la_gi\"><\/span><strong>Spring MVC l\u00e0 g\u00ec?<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p><strong>Spring MVC<\/strong> l\u00e0 m\u1ed9t module c\u1ed1t l\u00f5i c\u1ee7a <strong><a href=\"https:\/\/itviec.com\/blog\/spring-framework\/\" target=\"_blank\" rel=\"noreferrer noopener\">Spring Framework<\/a><\/strong>, \u0111\u01b0\u1ee3c thi\u1ebft k\u1ebf chuy\u00ean bi\u1ec7t \u0111\u1ec3 x\u00e2y d\u1ef1ng c\u00e1c \u1ee9ng d\u1ee5ng web trong Java. N\u00f3 tri\u1ec3n khai \u0111\u1ea7y \u0111\u1ee7 m\u1eabu ki\u1ebfn tr\u00fac kinh \u0111i\u1ec3n <strong>Model-View-Controller (MVC)<\/strong>, gi\u00fap t\u1ed5 ch\u1ee9c m\u00e3 ngu\u1ed3n m\u1ed9t c\u00e1ch r\u00f5 r\u00e0ng v\u00e0 khoa h\u1ecdc.<\/p>\n\n\n\n<p>Trong h\u1ec7 sinh th\u00e1i Spring, Spring MVC l\u00e0 n\u1ec1n t\u1ea3ng cho vi\u1ec7c ph\u00e1t tri\u1ec3n web. <strong>Spring Boot<\/strong> sau n\u00e0y ra \u0111\u1eddi \u0111\u00e3 gi\u00fap \u0111\u01a1n gi\u1ea3n h\u00f3a vi\u1ec7c c\u1ea5u h\u00ecnh v\u00e0 tri\u1ec3n khai m\u1ed9t \u1ee9ng d\u1ee5ng Spring MVC, nh\u01b0ng &#8220;tr\u00e1i tim&#8221; x\u1eed l\u00fd c\u00e1c y\u00eau c\u1ea7u web v\u1eabn ch\u00ednh l\u00e0 Spring MVC.<\/p>\n\n\n\n<p>Ra \u0111\u1eddi t\u1eeb nh\u1eefng n\u0103m \u0111\u1ea7u c\u1ee7a th\u1eadp ni\u00ean 2000, Spring MVC \u0111\u00e3 tr\u1ea3i qua m\u1ed9t ch\u1eb7ng \u0111\u01b0\u1eddng d\u00e0i ph\u00e1t tri\u1ec3n v\u00e0 tr\u01b0\u1edfng th\u00e0nh, tr\u1edf th\u00e0nh m\u1ed9t trong nh\u1eefng l\u1ef1a ch\u1ecdn h\u00e0ng \u0111\u1ea7u cho l\u1eadp tr\u00ecnh vi\u00ean Java web. S\u1ef1 ph\u1ed5 bi\u1ebfn n\u00e0y \u0111\u1ebfn t\u1eeb vi\u1ec7c n\u00f3 gi\u1ea3i quy\u1ebft hi\u1ec7u qu\u1ea3 c\u00e1c v\u1ea5n \u0111\u1ec1 c\u1ed1 h\u1eefu trong ph\u00e1t tri\u1ec3n web th\u1eddi k\u1ef3 \u0111\u1ea7u, nh\u01b0 s\u1ef1 h\u1ed7n lo\u1ea1n gi\u1eefa logic nghi\u1ec7p v\u1ee5 v\u00e0 giao di\u1ec7n trong c\u00e1c c\u00f4ng ngh\u1ec7 c\u0169 nh\u01b0 JSP\/Servlet.<\/p>\n\n\n\n<p><strong>Nh\u1eefng l\u1ee3i \u00edch ch\u00ednh khi s\u1eed d\u1ee5ng Spring MVC:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Ph\u00e2n t\u00e1ch r\u00f5 r\u00e0ng c\u00e1c th\u00e0nh ph\u1ea7n (Separation of Concerns):<\/strong> \u0110\u00e2y l\u00e0 l\u1ee3i \u00edch l\u1edbn nh\u1ea5t. Logic x\u1eed l\u00fd, d\u1eef li\u1ec7u v\u00e0 giao di\u1ec7n \u0111\u01b0\u1ee3c t\u00e1ch b\u1ea1ch ho\u00e0n to\u00e0n. \u0110i\u1ec1u n\u00e0y gi\u00fap m\u00e3 ngu\u1ed3n d\u1ec5 \u0111\u1ecdc, d\u1ec5 b\u1ea3o tr\u00ec, d\u1ec5 ki\u1ec3m th\u1eed (test) v\u00e0 cho ph\u00e9p c\u00e1c nh\u00f3m ph\u00e1t tri\u1ec3n (backend, frontend) l\u00e0m vi\u1ec7c song song hi\u1ec7u qu\u1ea3 h\u01a1n.<\/li>\n\n\n\n<li><strong>T\u00ednh linh ho\u1ea1t v\u00e0 kh\u1ea3 n\u0103ng t\u00f9y bi\u1ebfn cao:<\/strong> Spring MVC kh\u00f4ng \u00e9p bu\u1ed9c b\u1ea1n ph\u1ea3i theo m\u1ed9t khu\u00f4n m\u1eabu c\u1ee9ng nh\u1eafc. B\u1ea1n c\u00f3 th\u1ec3 t\u1ef1 do l\u1ef1a ch\u1ecdn c\u00f4ng ngh\u1ec7 cho View (JSP, Thymeleaf), c\u00e1ch x\u1eed l\u00fd d\u1eef li\u1ec7u, v\u00e0 c\u1ea5u h\u00ecnh c\u00e1c th\u00e0nh ph\u1ea7n theo nhu c\u1ea7u c\u1ee5 th\u1ec3 c\u1ee7a d\u1ef1 \u00e1n.<\/li>\n\n\n\n<li><strong>T\u00edch h\u1ee3p li\u1ec1n m\u1ea1ch v\u1edbi h\u1ec7 sinh th\u00e1i Spring:<\/strong> L\u00e0 m\u1ed9t ph\u1ea7n c\u1ee7a Spring Framework, n\u00f3 \u0111\u01b0\u1ee3c h\u01b0\u1edfng l\u1ee3i t\u1eeb c\u00e1c t\u00ednh n\u0103ng m\u1ea1nh m\u1ebd kh\u00e1c nh\u01b0 <em>Dependency Injection (DI)<\/em>, <em>Aspect-Oriented Programming (AOP), Spring Security (b\u1ea3o m\u1eadt), <\/em>v\u00e0<em> Spring Data (truy c\u1eadp d\u1eef li\u1ec7u)<\/em>, t\u1ea1o th\u00e0nh m\u1ed9t b\u1ed9 c\u00f4ng c\u1ee5 to\u00e0n di\u1ec7n.<\/li>\n\n\n\n<li><strong>H\u1ed7 tr\u1ee3 m\u1ea1nh m\u1ebd \u0111\u1ec3 x\u00e2y d\u1ef1ng RESTful APIs:<\/strong> V\u1edbi c\u00e1c annotation nh\u01b0 <code>@RestController<\/code> v\u00e0 <code>@ResponseBody<\/code>, vi\u1ec7c x\u00e2y d\u1ef1ng c\u00e1c d\u1ecbch v\u1ee5 web RESTful \u0111\u1ec3 cung c\u1ea5p d\u1eef li\u1ec7u cho c\u00e1c \u1ee9ng d\u1ee5ng single-page (SPA) ho\u1eb7c di \u0111\u1ed9ng tr\u1edf n\u00ean v\u00f4 c\u00f9ng \u0111\u01a1n gi\u1ea3n v\u00e0 tr\u1ef1c quan.<\/li>\n\n\n\n<li><strong>C\u1ed9ng \u0111\u1ed3ng l\u1edbn v\u00e0 t\u00e0i li\u1ec7u phong ph\u00fa:<\/strong> V\u1edbi l\u1ecbch s\u1eed ph\u00e1t tri\u1ec3n l\u00e2u d\u00e0i, Spring MVC s\u1edf h\u1eefu m\u1ed9t c\u1ed9ng \u0111\u1ed3ng ng\u01b0\u1eddi d\u00f9ng \u0111\u00f4ng \u0111\u1ea3o tr\u00ean to\u00e0n th\u1ebf gi\u1edbi. H\u1ea7u h\u1ebft m\u1ecdi v\u1ea5n \u0111\u1ec1 b\u1ea1n g\u1eb7p ph\u1ea3i \u0111\u1ec1u \u0111\u00e3 c\u00f3 ng\u01b0\u1eddi h\u1ecfi v\u00e0 gi\u1ea3i \u0111\u00e1p tr\u00ean c\u00e1c di\u1ec5n \u0111\u00e0n nh\u01b0 Stack Overflow, c\u00f9ng v\u1edbi ngu\u1ed3n t\u00e0i li\u1ec7u ch\u00ednh th\u1ee9c c\u1ef1c k\u1ef3 chi ti\u1ebft.<\/li>\n<\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>\u0110\u1ecdc chi ti\u1ebft: <strong><a href=\"https:\/\/itviec.com\/blog\/mvc-la-gi\/\" target=\"_blank\" rel=\"noreferrer noopener\">MVC l\u00e0 g\u00ec: T\u1ed5ng quan MVC v\u00e0 \u1ee8ng d\u1ee5ng m\u00f4 h\u00ecnh MVC trong l\u1eadp tr\u00ecnh<\/a><\/strong><\/em><\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-ki\u1ebfn-truc-c\u1ed1t-loi-c\u1ee7a-spring-mvc\"><span class=\"ez-toc-section\" id=\"Kien_truc_cot_loi_cua_Spring_MVC\"><\/span><strong>Ki\u1ebfn tr\u00fac c\u1ed1t l\u00f5i c\u1ee7a Spring MVC<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>\u0110\u1ec3 l\u00e0m ch\u1ee7 Spring MVC, \u0111i\u1ec1u ki\u1ec7n ti\u00ean quy\u1ebft l\u00e0 ph\u1ea3i hi\u1ec3u r\u00f5 ki\u1ebfn tr\u00fac n\u1ec1n t\u1ea3ng c\u1ee7a n\u00f3. Ki\u1ebfn tr\u00fac n\u00e0y xoay quanh m\u1eabu thi\u1ebft k\u1ebf <strong>Model-View-Controller (MVC)<\/strong> v\u00e0 m\u1ed9t th\u00e0nh ph\u1ea7n trung t\u00e2m c\u00f3 t\u00ean l\u00e0 <strong>DispatcherServlet<\/strong>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-t\u1ed5ng-quan-v\u1ec1-mo-hinh-mvc-model-view-controller\"><strong>T\u1ed5ng quan v\u1ec1 m\u00f4 h\u00ecnh MVC (Model-View-Controller)<\/strong><\/h3>\n\n\n\n<p>M\u00f4 h\u00ecnh MVC l\u00e0 m\u1ed9t m\u1eabu ki\u1ebfn tr\u00fac ph\u1ea7n m\u1ec1m kinh \u0111i\u1ec3n, gi\u00fap ph\u00e2n t\u00e1ch \u1ee9ng d\u1ee5ng th\u00e0nh ba th\u00e0nh ph\u1ea7n c\u00f3 vai tr\u00f2 ri\u00eang bi\u1ec7t, gi\u00fap m\u00e3 ngu\u1ed3n tr\u1edf n\u00ean c\u00f3 t\u1ed5 ch\u1ee9c v\u00e0 d\u1ec5 qu\u1ea3n l\u00fd.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Model<\/strong>: L\u00e0 n\u01a1i ch\u1ee9a <strong>d\u1eef li\u1ec7u<\/strong> v\u00e0 <strong>logic nghi\u1ec7p v\u1ee5<\/strong> c\u1ee7a \u1ee9ng d\u1ee5ng. N\u00f3 kh\u00f4ng quan t\u00e2m \u0111\u1ebfn vi\u1ec7c d\u1eef li\u1ec7u s\u1ebd \u0111\u01b0\u1ee3c hi\u1ec3n th\u1ecb nh\u01b0 th\u1ebf n\u00e0o. Nhi\u1ec7m v\u1ee5 c\u1ee7a n\u00f3 l\u00e0 x\u1eed l\u00fd, truy xu\u1ea5t v\u00e0 chu\u1ea9n b\u1ecb d\u1eef li\u1ec7u.<\/li>\n\n\n\n<li><strong>View<\/strong>: Ch\u1ecbu tr\u00e1ch nhi\u1ec7m <strong>hi\u1ec3n th\u1ecb<\/strong> d\u1eef li\u1ec7u (Model) cho ng\u01b0\u1eddi d\u00f9ng cu\u1ed1i. View ch\u1ec9 nh\u1eadn d\u1eef li\u1ec7u t\u1eeb Controller v\u00e0 tr\u00ecnh b\u00e0y n\u00f3. V\u00ed d\u1ee5: m\u1ed9t trang JSP, m\u1ed9t template Thymeleaf.<\/li>\n\n\n\n<li><strong>Controller<\/strong>: \u0110\u00f3ng vai tr\u00f2 <strong>\u0111i\u1ec1u ph\u1ed1i vi\u00ean<\/strong>. N\u00f3 ti\u1ebfp nh\u1eadn y\u00eau c\u1ea7u t\u1eeb ng\u01b0\u1eddi d\u00f9ng, t\u01b0\u01a1ng t\u00e1c v\u1edbi <strong>Model<\/strong> \u0111\u1ec3 th\u1ef1c thi c\u00e1c nghi\u1ec7p v\u1ee5, sau \u0111\u00f3 ch\u1ecdn m\u1ed9t <strong>View<\/strong> ph\u00f9 h\u1ee3p \u0111\u1ec3 tr\u1ea3 v\u1ec1 k\u1ebft qu\u1ea3 cho ng\u01b0\u1eddi d\u00f9ng.<\/li>\n<\/ul>\n\n\n\n<p>C\u00e1ch ti\u1ebfp c\u1eadn n\u00e0y gi\u00fap gi\u1ea3m s\u1ef1 ph\u1ee5 thu\u1ed9c l\u1eabn nhau gi\u1eefa c\u00e1c th\u00e0nh ph\u1ea7n, gi\u00fap vi\u1ec7c ph\u00e1t tri\u1ec3n, b\u1ea3o tr\u00ec v\u00e0 ki\u1ec3m th\u1eed tr\u1edf n\u00ean d\u1ec5 d\u00e0ng h\u01a1n r\u1ea5t nhi\u1ec1u.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-cac-thanh-ph\u1ea7n-chinh-va-lu\u1ed3ng-x\u1eed-ly-request\"><strong>C\u00e1c th\u00e0nh ph\u1ea7n ch\u00ednh v\u00e0 lu\u1ed3ng x\u1eed l\u00fd request<\/strong><\/h3>\n\n\n\n<p>Trung t\u00e2m c\u1ee7a ki\u1ebfn tr\u00fac Spring MVC l\u00e0 DispatcherServlet. N\u00f3 ho\u1ea1t \u0111\u1ed9ng nh\u01b0 m\u1ed9t &#8220;Front Controller,&#8221; ngh\u0129a l\u00e0 m\u1ecdi y\u00eau c\u1ea7u HTTP t\u1eeb client \u0111\u1ec1u \u0111i qua n\u00f3 \u0111\u1ea7u ti\u00ean. Sau \u0111\u00f3, DispatcherServlet s\u1ebd \u0111i\u1ec1u ph\u1ed1i y\u00eau c\u1ea7u n\u00e0y \u0111\u1ebfn c\u00e1c th\u00e0nh ph\u1ea7n kh\u00e1c \u0111\u1ec3 x\u1eed l\u00fd.<\/p>\n\n\n\n<p>H\u00e3y c\u00f9ng \u0111i s\u00e2u v\u00e0o t\u1eebng &#8220;nh\u00e2n v\u1eadt&#8221; trong lu\u1ed3ng x\u1eed l\u00fd n\u00e0y:<\/p>\n\n\n\n<p><strong>S\u01a1 \u0111\u1ed3 lu\u1ed3ng x\u1eed l\u00fd m\u1ed9t Request<\/strong><\/p>\n\n\n\n<p>H\u00e3y t\u01b0\u1edfng t\u01b0\u1ee3ng m\u1ed9t y\u00eau c\u1ea7u c\u1ee7a ng\u01b0\u1eddi d\u00f9ng \u0111i qua m\u1ed9t d\u00e2y chuy\u1ec1n s\u1ea3n xu\u1ea5t sau:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"700\" height=\"400\" src=\"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-7.png\" alt=\"\" class=\"wp-image-89052\" srcset=\"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-7.png 700w, https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-7-300x171.png 300w, https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-7-640x366.png 640w, https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-7-200x114.png 200w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/figure>\n\n\n\n<p>B\u00e2y gi\u1edd, h\u00e3y xem vai tr\u00f2 c\u1ee7a t\u1eebng tr\u1ea1m trong d\u00e2y chuy\u1ec1n.<\/p>\n\n\n\n<p><strong>DispatcherServlet (Front Controller)<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Vai tr\u00f2<\/strong>: L\u00e0 c\u1ed5ng v\u00e0o duy nh\u1ea5t c\u1ee7a \u1ee9ng d\u1ee5ng. N\u00f3 ti\u1ebfp nh\u1eadn t\u1ea5t c\u1ea3 c\u00e1c request HTTP, ph\u00e2n t\u00edch ch\u00fang v\u00e0 \u1ee7y quy\u1ec1n cho c\u00e1c th\u00e0nh ph\u1ea7n ph\u00f9 h\u1ee3p x\u1eed l\u00fd.<\/li>\n\n\n\n<li><strong>C\u1ea5u h\u00ecnh<\/strong>: Tr\u01b0\u1edbc \u0111\u00e2y, DispatcherServlet th\u01b0\u1eddng \u0111\u01b0\u1ee3c khai b\u00e1o trong file web.xml. V\u1edbi Spring Boot ho\u1eb7c c\u1ea5u h\u00ecnh d\u1ef1a tr\u00ean Java (Java-based configuration), vi\u1ec7c n\u00e0y \u0111\u01b0\u1ee3c t\u1ef1 \u0111\u1ed9ng h\u00f3a, nh\u01b0ng b\u1ea1n v\u1eabn c\u00f3 th\u1ec3 t\u00f9y ch\u1ec9nh n\u00f3 qua l\u1edbp <code>AbstractAnnotationConfigDispatcherServletInitializer<\/code>.<\/li>\n<\/ul>\n\n\n\n<p><strong>HandlerMapping (Ng\u01b0\u1eddi ch\u1ec9 \u0111\u01b0\u1eddng)<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Vai tr\u00f2<\/strong>: Sau khi nh\u1eadn request, <code>DispatcherServlet<\/code> s\u1ebd h\u1ecfi <code>HandlerMapping<\/code> r\u1eb1ng: &#8220;V\u1edbi URL l\u00e0 \/san-pham\/123, Controller n\u00e0o s\u1ebd x\u1eed l\u00fd?&#8221;. <code>HandlerMapping<\/code> s\u1ebd qu\u00e9t qua c\u00e1c Controller \u0111\u00e3 \u0111\u01b0\u1ee3c \u0111\u1ecbnh ngh\u0129a v\u00e0 t\u00ecm ra ph\u01b0\u01a1ng th\u1ee9c ph\u00f9 h\u1ee3p.<\/li>\n\n\n\n<li><strong>Tri\u1ec3n khai ph\u1ed5 bi\u1ebfn<\/strong>: <code>RequestMappingHandlerMapping<\/code> l\u00e0 tri\u1ec3n khai m\u1eb7c \u0111\u1ecbnh, n\u00f3 t\u00ecm ki\u1ebfm c\u00e1c ph\u01b0\u01a1ng th\u1ee9c \u0111\u01b0\u1ee3c \u0111\u00e1nh d\u1ea5u b\u1eb1ng annotation <code>@RequestMapping<\/code>, <code>@GetMapping<\/code>, <code>@PostMapping<\/code>, v.v.<\/li>\n<\/ul>\n\n\n\n<p><strong>Controller (Ng\u01b0\u1eddi x\u1eed l\u00fd)<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Vai tr\u00f2<\/strong>: \u0110\u00e2y l\u00e0 n\u01a1i logic nghi\u1ec7p v\u1ee5 \u0111\u01b0\u1ee3c th\u1ef1c thi. Controller nh\u1eadn request, t\u01b0\u01a1ng t\u00e1c v\u1edbi c\u00e1c service ho\u1eb7c repository \u0111\u1ec3 x\u1eed l\u00fd d\u1eef li\u1ec7u, sau \u0111\u00f3 \u0111\u00f3ng g\u00f3i k\u1ebft qu\u1ea3 v\u00e0 th\u00f4ng tin v\u1ec1 View s\u1ebd hi\u1ec3n th\u1ecb.<\/li>\n\n\n\n<li><strong>C\u00e1ch t\u1ea1o<\/strong>: B\u1ea1n t\u1ea1o m\u1ed9t class v\u00e0 \u0111\u00e1nh d\u1ea5u n\u00f3 b\u1eb1ng <code>@Controller<\/code> (cho \u1ee9ng d\u1ee5ng web truy\u1ec1n th\u1ed1ng) ho\u1eb7c <code>@RestController<\/code> (\u0111\u1ec3 x\u00e2y d\u1ef1ng RESTful APIs, t\u1ef1 \u0111\u1ed9ng chuy\u1ec3n \u0111\u1ed5i k\u1ebft qu\u1ea3 th\u00e0nh JSON\/XML).<\/li>\n<\/ul>\n\n\n\n<p><strong>ModelAndView (G\u00f3i h\u00e0ng)<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Vai tr\u00f2<\/strong>: L\u00e0 m\u1ed9t \u0111\u1ed1i t\u01b0\u1ee3ng <code>\"container\"<\/code> ti\u1ec7n l\u1ee3i do Controller tr\u1ea3 v\u1ec1. N\u00f3 ch\u1ee9a hai th\u1ee9: <strong>Model<\/strong> (d\u1eef li\u1ec7u c\u1ea7n hi\u1ec3n th\u1ecb, th\u01b0\u1eddng l\u00e0 m\u1ed9t Map) v\u00e0 <strong>t\u00ean logic c\u1ee7a View<\/strong> (m\u1ed9t chu\u1ed7i, v\u00ed d\u1ee5: <code>\"productDetail\"<\/code>).<\/li>\n\n\n\n<li><strong>C\u00e1ch tr\u1ea3 v\u1ec1<\/strong>: Controller s\u1ebd t\u1ea1o m\u1ed9t \u0111\u1ed1i t\u01b0\u1ee3ng ModelAndView, th\u00eam d\u1eef li\u1ec7u v\u00e0o \u0111\u00f3 v\u00e0 tr\u1ea3 v\u1ec1 cho DispatcherServlet.<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>ModelAndView mav = new ModelAndView(\"productDetail\"); mav.addObject(\"product\", productService.getProductById(123)); return mav;<\/code><\/pre>\n\n\n\n<p><strong>ViewResolver (Ng\u01b0\u1eddi phi\u00ean d\u1ecbch)<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Vai tr\u00f2<\/strong>: DispatcherServlet nh\u1eadn ModelAndView v\u00e0 kh\u00f4ng bi\u1ebft <code>\"productDetail\"<\/code> l\u00e0 file n\u00e0o. N\u00f3 s\u1ebd \u0111\u01b0a t\u00ean logic n\u00e0y cho ViewResolver. ViewResolver s\u1ebd &#8220;d\u1ecbch&#8221; t\u00ean logic n\u00e0y th\u00e0nh m\u1ed9t \u0111\u01b0\u1eddng d\u1eabn \u0111\u1ebfn file View c\u1ee5 th\u1ec3.<\/li>\n\n\n\n<li><strong>Tri\u1ec3n khai ph\u1ed5 bi\u1ebfn<\/strong>: InternalResourceViewResolver th\u01b0\u1eddng \u0111\u01b0\u1ee3c d\u00f9ng cho JSP. N\u00f3 s\u1ebd th\u00eam ti\u1ec1n t\u1ed1 (prefix) v\u00e0 h\u1eadu t\u1ed1 (suffix) v\u00e0o t\u00ean logic. V\u00ed d\u1ee5: <code>\"productDetail\"<\/code> s\u1ebd \u0111\u01b0\u1ee3c d\u1ecbch th\u00e0nh <code>\/WEB-INF\/views\/productDetail.jsp<\/code>. ThymeleafViewResolver \u0111\u01b0\u1ee3c d\u00f9ng cho template Thymeleaf.<\/li>\n<\/ul>\n\n\n\n<p><strong>View (Ng\u01b0\u1eddi tr\u00ecnh b\u00e0y)<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Vai tr\u00f2<\/strong>: L\u00e0 tr\u1ea1m cu\u1ed1i c\u00f9ng. View (v\u00ed d\u1ee5: file productDetail.jsp) nh\u1eadn d\u1eef li\u1ec7u t\u1eeb Model, th\u1ef1c hi\u1ec7n c\u00e1c logic hi\u1ec3n th\u1ecb (nh\u01b0 v\u00f2ng l\u1eb7p, \u0111i\u1ec1u ki\u1ec7n) v\u00e0 render ra HTML cu\u1ed1i c\u00f9ng.<\/li>\n\n\n\n<li><strong>C\u00f4ng ngh\u1ec7 th\u01b0\u1eddng d\u00f9ng<\/strong>: JSP, Thymeleaf (khuy\u1ebfn kh\u00edch), FreeMarker, Velocity.<\/li>\n<\/ul>\n\n\n\n<p>Cu\u1ed1i c\u00f9ng, DispatcherServlet nh\u1eadn k\u1ebft qu\u1ea3 HTML t\u1eeb View v\u00e0 g\u1eedi n\u00f3 v\u1ec1 tr\u00ecnh duy\u1ec7t c\u1ee7a ng\u01b0\u1eddi d\u00f9ng d\u01b0\u1edbi d\u1ea1ng m\u1ed9t HTTP Response, k\u1ebft th\u00fac m\u1ed9t chu k\u1ef3 x\u1eed l\u00fd request.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-cac-khai-ni\u1ec7m-va-tinh-nang-quan-tr\u1ecdng-c\u1ee7a-spring-mvc\"><span class=\"ez-toc-section\" id=\"Cac_khai_niem_va_tinh_nang_quan_trong_cua_Spring_MVC\"><\/span><strong>C\u00e1c kh\u00e1i ni\u1ec7m v\u00e0 t\u00ednh n\u0103ng quan tr\u1ecdng c\u1ee7a Spring MVC<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Sau \u0111\u00e2y ch\u00fang ta s\u1ebd \u0111i s\u00e2u v\u00e0o c\u00e1c &#8220;vi\u00ean g\u1ea1ch&#8221; quan tr\u1ecdng \u0111\u00e3 l\u00e0m n\u00ean s\u1ee9c m\u1ea1nh v\u00e0 s\u1ef1 linh ho\u1ea1t c\u1ee7a Spring MVC. \u0110\u00e2y l\u00e0 nh\u1eefng kh\u00e1i ni\u1ec7m v\u00e0 t\u00ednh n\u0103ng b\u1ea1n s\u1ebd s\u1eed d\u1ee5ng h\u00e0ng ng\u00e0y khi l\u00e0m vi\u1ec7c v\u1edbi framework n\u00e0y.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-annotations-ngon-ng\u1eef-giao-ti\u1ebfp-v\u1edbi-framework\"><strong>Annotations &#8211; Ng\u00f4n ng\u1eef giao ti\u1ebfp v\u1edbi framework<\/strong><\/h3>\n\n\n\n<p>Annotations l\u00e0 c\u00e1ch ch\u00ednh \u0111\u1ec3 b\u1ea1n &#8220;ch\u1ec9 th\u1ecb&#8221; cho Spring MVC bi\u1ebft ph\u1ea3i l\u00e0m g\u00ec v\u1edbi code c\u1ee7a b\u1ea1n. Ch\u00fang gi\u00fap gi\u1ea3m thi\u1ec3u c\u1ea5u h\u00ecnh XML r\u01b0\u1eddm r\u00e0 v\u00e0 l\u00e0m cho code tr\u1edf n\u00ean tr\u1ef1c quan h\u01a1n.&nbsp;<\/p>\n\n\n\n<p>D\u01b0\u1edbi \u0111\u00e2y l\u00e0 m\u1ed9t v\u00e0i Annotations b\u1ea1n s\u1ebd th\u01b0\u1eddng xuy\u00ean g\u1eb7p trong qu\u00e1 tr\u00ecnh ph\u00e1t tri\u1ec3n s\u1eed d\u1ee5ng m\u00f4 h\u00ecnh Spring MVC:<\/p>\n\n\n\n<p><strong>1. <code>@Controller<\/code> &amp; <code>@RestController<\/code><\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>@Controller<\/code><\/strong>: \u0110\u00e1nh d\u1ea5u m\u1ed9t class l\u00e0 m\u1ed9t Controller truy\u1ec1n th\u1ed1ng. C\u00e1c ph\u01b0\u01a1ng th\u1ee9c trong class n\u00e0y th\u01b0\u1eddng tr\u1ea3 v\u1ec1 t\u00ean c\u1ee7a m\u1ed9t View (v\u00ed d\u1ee5: t\u00ean file JSP\/Thymeleaf).<\/li>\n\n\n\n<li><strong><code>@RestController<\/code><\/strong>: L\u00e0 s\u1ef1 k\u1ebft h\u1ee3p c\u1ee7a <code>@Controller<\/code> v\u00e0 <code>@ResponseBody<\/code>. N\u00f3 chuy\u00ean d\u00f9ng \u0111\u1ec3 x\u00e2y d\u1ef1ng RESTful APIs, n\u01a1i m\u1ed7i ph\u01b0\u01a1ng th\u1ee9c tr\u1ea3 v\u1ec1 d\u1eef li\u1ec7u (nh\u01b0 JSON\/XML) tr\u1ef1c ti\u1ebfp cho client thay v\u00ec m\u1ed9t View.<\/li>\n<\/ul>\n\n\n\n<p><strong>2. <code>@RequestMapping<\/code> v\u00e0 c\u00e1c bi\u1ebfn th\u1ec3<\/strong>: \u00c1nh x\u1ea1 m\u1ed9t request HTTP t\u1edbi m\u1ed9t ph\u01b0\u01a1ng th\u1ee9c x\u1eed l\u00fd (handler method).<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>@RequestMapping(\"\/users\")<\/code>: C\u00f3 th\u1ec3 x\u1eed l\u00fd m\u1ecdi ph\u01b0\u01a1ng th\u1ee9c HTTP (<code>GET<\/code>, <code>POST<\/code>, etc.).<\/li>\n\n\n\n<li><code>@GetMapping(\"\/users\")<\/code>: Ch\u1ec9 x\u1eed l\u00fd request <code>GET<\/code>.<\/li>\n\n\n\n<li><code>@PostMapping(\"\/users\")<\/code>: Ch\u1ec9 x\u1eed l\u00fd request <code>POST<\/code>.<\/li>\n\n\n\n<li>T\u01b0\u01a1ng t\u1ef1 v\u1edbi <strong><code>@PutMapping<\/code><\/strong>, <strong><code>@DeleteMapping<\/code><\/strong>, <strong><code>@PatchMapping<\/code><\/strong>.<\/li>\n<\/ul>\n\n\n\n<p><strong>3. L\u1ea5y d\u1eef li\u1ec7u t\u1eeb Request:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>@RequestParam<\/code><\/strong>: L\u1ea5y gi\u00e1 tr\u1ecb t\u1eeb query parameter trong URL. V\u00ed d\u1ee5: <code>?id=123<\/code>.<\/li>\n\n\n\n<li><strong><code>@PathVariable<\/code><\/strong>: L\u1ea5y gi\u00e1 tr\u1ecb t\u1eeb m\u1ed9t ph\u1ea7n c\u1ee7a \u0111\u01b0\u1eddng d\u1eabn URI. V\u00ed d\u1ee5: <code>\/users\/{id}<\/code>.<\/li>\n\n\n\n<li><strong><code>@RequestBody<\/code><\/strong>: \u00c1nh x\u1ea1 to\u00e0n b\u1ed9 ph\u1ea7n th\u00e2n (body) c\u1ee7a request (th\u01b0\u1eddng l\u00e0 m\u1ed9t chu\u1ed7i JSON\/XML) v\u00e0o m\u1ed9t \u0111\u1ed1i t\u01b0\u1ee3ng Java (POJO).<\/li>\n<\/ul>\n\n\n\n<p><strong>4. X\u1eed l\u00fd d\u1eef li\u1ec7u tr\u1ea3 v\u1ec1<\/strong>:<\/p>\n\n\n\n<p><strong><code>@ResponseBody<\/code><\/strong>: B\u00e1o cho Spring bi\u1ebft r\u1eb1ng gi\u00e1 tr\u1ecb tr\u1ea3 v\u1ec1 c\u1ee7a ph\u01b0\u01a1ng th\u1ee9c n\u00ean \u0111\u01b0\u1ee3c ghi th\u1eb3ng v\u00e0o body c\u1ee7a HTTP response, thay v\u00ec \u0111\u01b0\u1ee3c ph\u00e2n gi\u1ea3i th\u00e0nh m\u1ed9t View.<\/p>\n\n\n\n<p><code>@RestController<\/code> \u0111\u00e3 t\u00edch h\u1ee3p s\u1eb5n annotation n\u00e0y.<\/p>\n\n\n\n<p><strong>5. L\u00e0m vi\u1ec7c v\u1edbi Model v\u00e0 Session<\/strong>:<\/p>\n\n\n\n<p><strong><code>@ModelAttribute<\/code><\/strong>: C\u00f3 hai c\u00e1ch d\u00f9ng ch\u00ednh:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Tr\u00ean ph\u01b0\u01a1ng th\u1ee9c<\/strong>: Ph\u01b0\u01a1ng th\u1ee9c \u0111\u00f3 s\u1ebd \u0111\u01b0\u1ee3c th\u1ef1c thi tr\u01b0\u1edbc c\u1ea3 handler method, gi\u00e1 tr\u1ecb n\u00f3 tr\u1ea3 v\u1ec1 s\u1ebd \u0111\u01b0\u1ee3c t\u1ef1 \u0111\u1ed9ng th\u00eam v\u00e0o Model.<\/li>\n\n\n\n<li><strong>Tr\u00ean tham s\u1ed1 c\u1ee7a ph\u01b0\u01a1ng th\u1ee9c<\/strong>: L\u1ea5y m\u1ed9t \u0111\u1ed1i t\u01b0\u1ee3ng \u0111\u00e3 c\u00f3 s\u1eb5n trong Model \u0111\u1ec3 s\u1eed d\u1ee5ng.<\/li>\n<\/ul>\n\n\n\n<p><strong><code>@SessionAttributes<\/code><\/strong>: L\u01b0u tr\u1eef c\u00e1c model attribute trong session HTTP, gi\u00fap duy tr\u00ec tr\u1ea1ng th\u00e1i qua nhi\u1ec1u request.<\/p>\n\n\n\n<p><strong>6. X\u00e1c th\u1ef1c d\u1eef li\u1ec7u<\/strong>:<\/p>\n\n\n\n<p><strong><code>@Valid<\/code> \/ <code>@Validated<\/code><\/strong>: K\u00edch ho\u1ea1t c\u01a1 ch\u1ebf ki\u1ec3m tra t\u00ednh h\u1ee3p l\u1ec7 c\u1ee7a d\u1eef li\u1ec7u \u0111\u1ea7u v\u00e0o (v\u00ed d\u1ee5: m\u1ed9t \u0111\u1ed1i t\u01b0\u1ee3ng \u0111\u01b0\u1ee3c g\u1eedi l\u00ean t\u1eeb form).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-x\u1eed-ly-form-form-handling-nbsp\"><strong>X\u1eed l\u00fd Form (Form Handling)&nbsp;<\/strong><\/h3>\n\n\n\n<p>Spring MVC cung c\u1ea5p c\u01a1 ch\u1ebf m\u1ea1nh m\u1ebd \u0111\u1ec3 x\u1eed l\u00fd d\u1eef li\u1ec7u t\u1eeb c\u00e1c form HTML.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Data Binding<\/strong>: Spring c\u00f3 kh\u1ea3 n\u0103ng t\u1ef1 \u0111\u1ed9ng &#8220;bind&#8221; (li\u00ean k\u1ebft) c\u00e1c tr\u01b0\u1eddng d\u1eef li\u1ec7u t\u1eeb m\u1ed9t form (v\u00ed d\u1ee5: username, password) v\u00e0o c\u00e1c thu\u1ed9c t\u00ednh c\u1ee7a m\u1ed9t \u0111\u1ed1i t\u01b0\u1ee3ng Java (th\u01b0\u1eddng g\u1ecdi l\u00e0 <em>Command Object<\/em> ho\u1eb7c <em>Form-backing Object<\/em>).<\/li>\n\n\n\n<li><strong>Form Tags<\/strong>: Khi d\u00f9ng v\u1edbi JSP, Spring cung c\u1ea5p m\u1ed9t th\u01b0 vi\u1ec7n th\u1ebb (form tags) gi\u00fap d\u1ec5 d\u00e0ng t\u1ea1o form v\u00e0 li\u00ean k\u1ebft n\u00f3 v\u1edbi Command Object, c\u0169ng nh\u01b0 hi\u1ec3n th\u1ecb c\u00e1c l\u1ed7i x\u00e1c th\u1ef1c m\u1ed9t c\u00e1ch thu\u1eadn ti\u1ec7n. V\u1edbi Thymeleaf, vi\u1ec7c t\u00edch h\u1ee3p c\u0169ng r\u1ea5t li\u1ec1n m\u1ea1ch.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-xac-th\u1ef1c-d\u1eef-li\u1ec7u-data-validation-nbsp\"><strong>X\u00e1c th\u1ef1c d\u1eef li\u1ec7u (Data Validation)&nbsp;<\/strong><\/h3>\n\n\n\n<p>Vi\u1ec7c \u0111\u1ea3m b\u1ea3o d\u1eef li\u1ec7u ng\u01b0\u1eddi d\u00f9ng nh\u1eadp v\u00e0o l\u00e0 h\u1ee3p l\u1ec7 l\u00e0 m\u1ed9t y\u00eau c\u1ea7u b\u1eaft bu\u1ed9c.Spring t\u00edch h\u1ee3p ho\u00e0n h\u1ea3o v\u1edbi ti\u00eau chu\u1ea9n <strong>Bean Validation (JSR 303\/JSR 380)<\/strong>: B\u1ea1n ch\u1ec9 c\u1ea7n th\u00eam c\u00e1c annotation x\u00e1c th\u1ef1c nh\u01b0 <code>@NotNull<\/code>, <code>@Size(min=6, max=20)<\/code>, <code>@Email<\/code>, <code>@Pattern(regexp=\"...\")<\/code> tr\u1ef1c ti\u1ebfp l\u00ean c\u00e1c tr\u01b0\u1eddng c\u1ee7a \u0111\u1ed1i t\u01b0\u1ee3ng Java.<\/p>\n\n\n\n<p>Khi k\u1ebft h\u1ee3p <code>@Valid<\/code> trong Controller, n\u1ebfu d\u1eef li\u1ec7u kh\u00f4ng h\u1ee3p l\u1ec7, c\u00e1c l\u1ed7i s\u1ebd \u0111\u01b0\u1ee3c ghi l\u1ea1i v\u00e0 b\u1ea1n c\u00f3 th\u1ec3 d\u1ec5 d\u00e0ng hi\u1ec3n th\u1ecb ch\u00fang tr\u00ean View \u0111\u1ec3 th\u00f4ng b\u00e1o cho ng\u01b0\u1eddi d\u00f9ng.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-x\u1eed-ly-ngo\u1ea1i-l\u1ec7-exception-handling-nbsp\"><strong>X\u1eed l\u00fd ngo\u1ea1i l\u1ec7 (Exception Handling)&nbsp;<\/strong><\/h3>\n\n\n\n<p>M\u1ed9t \u1ee9ng d\u1ee5ng t\u1ed1t ph\u1ea3i x\u1eed l\u00fd \u0111\u01b0\u1ee3c c\u00e1c t\u00ecnh hu\u1ed1ng kh\u00f4ng mong mu\u1ed1n.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>@ExceptionHandler<\/code><\/strong>: \u0110\u1eb7t annotation n\u00e0y tr\u00ean m\u1ed9t ph\u01b0\u01a1ng th\u1ee9c b\u00ean trong Controller \u0111\u1ec3 &#8220;b\u1eaft&#8221; v\u00e0 x\u1eed l\u00fd m\u1ed9t lo\u1ea1i ngo\u1ea1i l\u1ec7 c\u1ee5 th\u1ec3 ch\u1ec9 x\u1ea3y ra trong Controller \u0111\u00f3.<\/li>\n\n\n\n<li><strong><code>@ControllerAdvice<\/code> \/ <code>@RestControllerAdvice<\/code><\/strong>: \u0110\u00e2y l\u00e0 c\u00e1ch x\u1eed l\u00fd ngo\u1ea1i l\u1ec7 to\u00e0n c\u1ee5c. B\u1ea1n t\u1ea1o m\u1ed9t class ri\u00eang \u0111\u01b0\u1ee3c \u0111\u00e1nh d\u1ea5u b\u1eb1ng annotation n\u00e0y, v\u00e0 c\u00e1c ph\u01b0\u01a1ng th\u1ee9c @ExceptionHandler b\u00ean trong n\u00f3 s\u1ebd x\u1eed l\u00fd ngo\u1ea1i l\u1ec7 t\u1eeb t\u1ea5t c\u1ea3 c\u00e1c Controller trong \u1ee9ng d\u1ee5ng. \u0110i\u1ec1u n\u00e0y gi\u00fap tr\u00e1nh l\u1eb7p l\u1ea1i code x\u1eed l\u00fd l\u1ed7i.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-interceptors-b\u1ed9-ch\u1eb7n-nbsp\"><strong>Interceptors (B\u1ed9 Ch\u1eb7n)&nbsp;<\/strong><\/h3>\n\n\n\n<p>Interceptor cho ph\u00e9p b\u1ea1n th\u1ef1c thi m\u1ed9t \u0111o\u1ea1n logic tr\u01b0\u1edbc khi request \u0111\u01b0\u1ee3c x\u1eed l\u00fd b\u1edfi Controller, sau khi Controller x\u1eed l\u00fd xong, ho\u1eb7c sau khi View \u0111\u00e3 \u0111\u01b0\u1ee3c render.<\/p>\n\n\n\n<p>Interceptor r\u1ea5t h\u1eefu \u00edch cho c\u00e1c t\u00e1c v\u1ee5 xuy\u00ean su\u1ed1t (cross-cutting concerns) nh\u01b0:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ghi log (logging) m\u1ecdi request.<\/li>\n\n\n\n<li>Ki\u1ec3m tra x\u00e1c th\u1ef1c (authentication) v\u00e0 ph\u00e2n quy\u1ec1n (authorization).<\/li>\n\n\n\n<li>Th\u00eam c\u00e1c thu\u1ed9c t\u00ednh chung v\u00e0o ModelAndView cho m\u1ecdi request.<\/li>\n<\/ul>\n\n\n\n<p><strong>C\u00e1ch t\u1ea1o<\/strong>: Tri\u1ec3n khai interface <code>HandlerInterceptor<\/code> (ho\u1eb7c k\u1ebf th\u1eeba l\u1edbp <code>HandlerInterceptorAdapter<\/code> \u0111\u00e3 l\u1ed7i th\u1eddi) v\u00e0 \u0111\u0103ng k\u00fd n\u00f3 v\u1edbi Spring.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-h\u1ed7-tr\u1ee3-restful-web-services-nbsp\"><strong>H\u1ed7 tr\u1ee3 RESTful Web Services&nbsp;<\/strong><\/h3>\n\n\n\n<p>\u0110\u00e2y l\u00e0 m\u1ed9t trong nh\u1eefng th\u1ebf m\u1ea1nh l\u1edbn nh\u1ea5t c\u1ee7a Spring MVC hi\u1ec7n \u0111\u1ea1i.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>@RestController<\/code><\/strong>: Nh\u01b0 \u0111\u00e3 \u0111\u1ec1 c\u1eadp, \u0111\u00e2y l\u00e0 ch\u00eca kh\u00f3a \u0111\u1ec3 x\u00e2y d\u1ef1ng API.<\/li>\n\n\n\n<li><strong>X\u1eed l\u00fd HTTP Methods<\/strong>: D\u1ec5 d\u00e0ng \u00e1nh x\u1ea1 c\u00e1c h\u00e0nh \u0111\u1ed9ng CRUD (Create, Read, Update, Delete) t\u1edbi c\u00e1c ph\u01b0\u01a1ng th\u1ee9c <code>POST<\/code>, <code>GET<\/code>, <code>PUT<\/code>, <code>DELETE<\/code> t\u01b0\u01a1ng \u1ee9ng.<\/li>\n\n\n\n<li><strong>Content Negotiation<\/strong>: Spring c\u00f3 th\u1ec3 t\u1ef1 \u0111\u1ed9ng chuy\u1ec3n \u0111\u1ed5i \u0111\u1ed1i t\u01b0\u1ee3ng Java tr\u1ea3 v\u1ec1 th\u00e0nh \u0111\u1ecbnh d\u1ea1ng m\u00e0 client y\u00eau c\u1ea7u (v\u00edg d\u1ee5: JSON ho\u1eb7c XML) d\u1ef1a tr\u00ean header Accept c\u1ee7a request.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-t\u1ea3i-t\u1ec7p-len-file-uploading-nbsp\"><strong>T\u1ea3i t\u1ec7p l\u00ean (File Uploading)&nbsp;<\/strong><\/h3>\n\n\n\n<p>Spring MVC \u0111\u01a1n gi\u1ea3n h\u00f3a vi\u1ec7c x\u1eed l\u00fd c\u00e1c t\u1ec7p \u0111\u01b0\u1ee3c t\u1ea3i l\u00ean t\u1eeb client.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>C\u1ea5u h\u00ecnh <\/strong><strong>MultipartResolver<\/strong>: B\u1ea1n c\u1ea7n c\u1ea5u h\u00ecnh m\u1ed9t bean MultipartResolver \u0111\u1ec3 Spring c\u00f3 th\u1ec3 x\u1eed l\u00fd c\u00e1c request multipart (request ch\u1ee9a t\u1ec7p). V\u1edbi Spring Boot, vi\u1ec7c n\u00e0y th\u01b0\u1eddng \u0111\u01b0\u1ee3c t\u1ef1 \u0111\u1ed9ng c\u1ea5u h\u00ecnh khi b\u1ea1n th\u00eam dependency c\u1ea7n thi\u1ebft.<\/li>\n\n\n\n<li><strong>X\u1eed l\u00fd trong Controller<\/strong>: S\u1eed d\u1ee5ng MultipartFile l\u00e0m tham s\u1ed1 trong handler method \u0111\u1ec3 d\u1ec5 d\u00e0ng nh\u1eadn v\u00e0 x\u1eed l\u00fd t\u1ec7p tin \u0111\u01b0\u1ee3c t\u1ea3i l\u00ean.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-da-ngon-ng\u1eef-localization-i18n-nbsp\"><strong>\u0110a ng\u00f4n ng\u1eef (Localization &#8211; i18n)&nbsp;<\/strong><\/h3>\n\n\n\n<p>Spring cung c\u1ea5p c\u01a1 ch\u1ebf to\u00e0n di\u1ec7n \u0111\u1ec3 x\u00e2y d\u1ef1ng c\u00e1c \u1ee9ng d\u1ee5ng h\u1ed7 tr\u1ee3 nhi\u1ec1u ng\u00f4n ng\u1eef. B\u1eb1ng c\u00e1ch s\u1eed d\u1ee5ng c\u00e1c ResourceBundleMessageSource v\u00e0 LocaleResolver, b\u1ea1n c\u00f3 th\u1ec3 d\u1ec5 d\u00e0ng qu\u1ea3n l\u00fd c\u00e1c file ch\u1ee9a chu\u1ed7i v\u0103n b\u1ea3n cho t\u1eebng ng\u00f4n ng\u1eef v\u00e0 hi\u1ec3n th\u1ecb ng\u00f4n ng\u1eef ph\u00f9 h\u1ee3p d\u1ef1a tr\u00ean l\u1ef1a ch\u1ecdn c\u1ee7a ng\u01b0\u1eddi d\u00f9ng ho\u1eb7c c\u00e0i \u0111\u1eb7t tr\u00ecnh duy\u1ec7t.<\/p>\n\n\n\n<p>B\u1ea1n c\u00f3 th\u1ec3 t\u00ecm hi\u1ec3u th\u00eam v\u1ec1 t\u1ea5t c\u1ea3 c\u00e1c kh\u00e1i ni\u1ec7m v\u00e0 t\u00ednh n\u0103ng \u1edf tr\u00ean t\u1ea1i <a href=\"https:\/\/docs.spring.io\/spring-framework\/reference\/web\/webmvc.html\" target=\"_blank\" rel=\"noreferrer noopener\">T\u00e0i li\u1ec7u Spring Web MVC ch\u00ednh th\u1ee9c<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-xay-d\u1ef1ng-\u1ee9ng-d\u1ee5ng-v\u1edbi-spring-mvc-c\u01a1-b\u1ea3n-nbsp\"><span class=\"ez-toc-section\" id=\"Xay_dung_ung_dung_voi_Spring_MVC_co_ban\"><\/span><strong>X\u00e2y d\u1ef1ng \u1ee9ng d\u1ee5ng v\u1edbi Spring MVC c\u01a1 b\u1ea3n&nbsp;<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>L\u00fd thuy\u1ebft s\u1ebd tr\u1edf n\u00ean d\u1ec5 hi\u1ec3u h\u01a1n r\u1ea5t nhi\u1ec1u khi \u0111\u01b0\u1ee3c \u00e1p d\u1ee5ng v\u00e0o th\u1ef1c t\u1ebf. Trong ph\u1ea7n n\u00e0y, ch\u00fang ta s\u1ebd c\u00f9ng nhau x\u00e2y d\u1ef1ng m\u1ed9t \u1ee9ng d\u1ee5ng &#8220;Hello World&#8221; \u0111\u01a1n gi\u1ea3n v\u1edbi Spring MVC v\u00e0 Spring Boot.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-yeu-c\u1ea7u-cai-d\u1eb7t\"><strong>Y\u00eau c\u1ea7u c\u00e0i \u0111\u1eb7t<\/strong><\/h3>\n\n\n\n<p>Tr\u01b0\u1edbc khi b\u1eaft \u0111\u1ea7u, h\u00e3y ch\u1eafc ch\u1eafn r\u1eb1ng b\u1ea1n \u0111\u00e3 c\u00e0i \u0111\u1eb7t c\u00e1c c\u00f4ng c\u1ee5 sau:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Java Development Kit (JDK)<\/strong>: Phi\u00ean b\u1ea3n 17 tr\u1edf l\u00ean.<\/li>\n\n\n\n<li><strong>Maven<\/strong> ho\u1eb7c <strong>Gradle<\/strong>: C\u00f4ng c\u1ee5 qu\u1ea3n l\u00fd th\u01b0 vi\u1ec7n v\u00e0 build d\u1ef1 \u00e1n.<\/li>\n\n\n\n<li><strong>IDE<\/strong>: M\u1ed9t m\u00f4i tr\u01b0\u1eddng ph\u00e1t tri\u1ec3n t\u00edch h\u1ee3p nh\u01b0 <strong>IntelliJ IDEA<\/strong> (Community\/Ultimate) ho\u1eb7c <strong>Eclipse<\/strong>.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-b\u01b0\u1edbc-1-thi\u1ebft-l\u1eadp-d\u1ef1-an-v\u1edbi-spring-initializr\"><strong>B\u01b0\u1edbc 1: Thi\u1ebft l\u1eadp d\u1ef1 \u00e1n (v\u1edbi Spring Initializr)<\/strong><\/h3>\n\n\n\n<p><strong><a href=\"https:\/\/itviec.com\/blog\/spring-initializr-la-gi\/\" target=\"_blank\" rel=\"noreferrer noopener\">Spring Initializr<\/a><\/strong> l\u00e0 c\u00f4ng c\u1ee5 tuy\u1ec7t v\u1eddi gi\u00fap t\u1ea1o nhanh m\u1ed9t b\u1ed9 khung d\u1ef1 \u00e1n Spring Boot v\u1edbi c\u00e1c c\u1ea5u h\u00ecnh c\u01a1 b\u1ea3n.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Truy c\u1eadp trang web: <a href=\"https:\/\/start.spring.io\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>start.spring.io<\/strong><\/a><\/li>\n\n\n\n<li>\u0110i\u1ec1n c\u00e1c th\u00f4ng tin cho d\u1ef1 \u00e1n c\u1ee7a b\u1ea1n:\n<ul class=\"wp-block-list\">\n<li><strong>Project<\/strong>: Maven Project<\/li>\n\n\n\n<li><strong>Language<\/strong>: Java<\/li>\n\n\n\n<li><strong>Spring Boot<\/strong>: Ch\u1ecdn phi\u00ean b\u1ea3n \u1ed5n \u0111\u1ecbnh (v\u00ed d\u1ee5: 3.x.x)<\/li>\n\n\n\n<li><strong>Project Metadata<\/strong>:\n<ul class=\"wp-block-list\">\n<li><strong>Group<\/strong>: com.example<\/li>\n\n\n\n<li><strong>Artifact<\/strong>: spring-mvc-demo<\/li>\n\n\n\n<li><strong>Packaging<\/strong>: Jar<\/li>\n\n\n\n<li><strong>Java<\/strong>: 17<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Trong m\u1ee5c <strong>Dependencies<\/strong>, nh\u1ea5n <strong>&#8220;ADD DEPENDENCIES&#8221;<\/strong> v\u00e0 t\u00ecm ki\u1ebfm, sau \u0111\u00f3 th\u00eam v\u00e0o:\n<ul class=\"wp-block-list\">\n<li>Spring Web: Th\u01b0 vi\u1ec7n c\u1ed1t l\u00f5i cho vi\u1ec7c x\u00e2y d\u1ef1ng \u1ee9ng d\u1ee5ng web, bao g\u1ed3m Spring MVC.<\/li>\n\n\n\n<li>Thymeleaf: Template engine gi\u00fap ch\u00fang ta t\u1ea1o c\u00e1c trang View. (B\u1ea1n c\u0169ng c\u00f3 th\u1ec3 ch\u1ecdn tomcat-embed-jasper n\u1ebfu mu\u1ed1n d\u00f9ng JSP).<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Nh\u1ea5n n\u00fat <strong>&#8220;GENERATE&#8221;<\/strong>. M\u1ed9t file .zip s\u1ebd \u0111\u01b0\u1ee3c t\u1ea3i v\u1ec1.<\/li>\n\n\n\n<li>Gi\u1ea3i n\u00e9n file zip v\u00e0 m\u1edf d\u1ef1 \u00e1n b\u1eb1ng IDE c\u1ee7a b\u1ea1n.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-b\u01b0\u1edbc-2-t\u1ea1o-m\u1ed9t-controller-d\u01a1n-gi\u1ea3n\"><strong>B\u01b0\u1edbc 2: T\u1ea1o m\u1ed9t Controller \u0111\u01a1n gi\u1ea3n<\/strong><\/h3>\n\n\n\n<p>Controller s\u1ebd ti\u1ebfp nh\u1eadn y\u00eau c\u1ea7u t\u1eeb ng\u01b0\u1eddi d\u00f9ng v\u00e0 quy\u1ebft \u0111\u1ecbnh ph\u1ea3i l\u00e0m g\u00ec ti\u1ebfp theo.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Trong IDE, t\u00ecm \u0111\u1ebfn th\u01b0 m\u1ee5c <code>src\/main\/java\/com\/example\/springmvcdemo<\/code>.<\/li>\n\n\n\n<li>T\u1ea1o m\u1ed9t package m\u1edbi t\u00ean l\u00e0 <code>controller<\/code>.<\/li>\n\n\n\n<li>Trong package controller, t\u1ea1o m\u1ed9t class Java m\u1edbi t\u00ean l\u00e0 <code>HelloController<\/code>.<\/li>\n\n\n\n<li>\u0110i\u1ec1n n\u1ed9i dung sau v\u00e0o file <code>HelloController.java<\/code>:<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.example.springmvcdemo.controller;\n\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\n\n@Controller public class HelloController {\n  @GetMapping(\"\/hello\") public String\n      sayHello(@RequestParam(name = \"name\", required = false,\n                             defaultValue = \"World\") String name,\n               Model model) {\n    \/\/ 1. Th\u00eam m\u1ed9t thu\u1ed9c t\u00ednh v\u00e0o Model\n    model.addAttribute(\"message\", name);\n\n    \/\/ 2. Tr\u1ea3 v\u1ec1 t\u00ean c\u1ee7a file View (kh\u00f4ng c\u00f3 \u0111u\u00f4i .html)\n    return \"greeting\";\n  }\n}<\/code><\/pre>\n\n\n\n<p><strong>Gi\u1ea3i th\u00edch:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>@Controller<\/code>: \u0110\u00e1nh d\u1ea5u \u0111\u00e2y l\u00e0 m\u1ed9t Controller.<\/li>\n\n\n\n<li><code>@GetMapping(\"\/hello\")<\/code>: \u00c1nh x\u1ea1 c\u00e1c request HTTP GET c\u00f3 \u0111\u01b0\u1eddng d\u1eabn <code>\/hello<\/code> t\u1edbi ph\u01b0\u01a1ng th\u1ee9c <code>sayHello()<\/code>.<\/li>\n\n\n\n<li><code>@RequestParam(...)<\/code>: L\u1ea5y gi\u00e1 tr\u1ecb c\u1ee7a tham s\u1ed1 name t\u1eeb URL (v\u00ed d\u1ee5: <code>\/hello?name=Gemini<\/code>). N\u1ebfu kh\u00f4ng c\u00f3, gi\u00e1 tr\u1ecb m\u1eb7c \u0111\u1ecbnh l\u00e0 &#8220;World&#8221;.<\/li>\n\n\n\n<li><code>Model model<\/code>: Spring s\u1ebd t\u1ef1 \u0111\u1ed9ng cung c\u1ea5p m\u1ed9t \u0111\u1ed1i t\u01b0\u1ee3ng Model. Ch\u00fang ta d\u00f9ng n\u00f3 \u0111\u1ec3 truy\u1ec1n d\u1eef li\u1ec7u sang cho View.<\/li>\n\n\n\n<li><code>model.addAttribute(\"message\", name)<\/code>: \u0110\u1eb7t m\u1ed9t thu\u1ed9c t\u00ednh t\u00ean l\u00e0 message v\u1edbi gi\u00e1 tr\u1ecb l\u00e0 bi\u1ebfn name v\u00e0o trong Model.<\/li>\n\n\n\n<li><code>return \"greeting\"<\/code>: Tr\u1ea3 v\u1ec1 t\u00ean logic c\u1ee7a View. Spring v\u00e0 Thymeleaf s\u1ebd t\u00ecm file greeting.html trong th\u01b0 m\u1ee5c templates.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-b\u01b0\u1edbc-3-t\u1ea1o-view-s\u1eed-d\u1ee5ng-thymeleaf\"><strong>B\u01b0\u1edbc 3: T\u1ea1o View (s\u1eed d\u1ee5ng Thymeleaf)<\/strong><\/h3>\n\n\n\n<p>View l\u00e0 n\u01a1i hi\u1ec3n th\u1ecb d\u1eef li\u1ec7u cho ng\u01b0\u1eddi d\u00f9ng.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Trong c\u00e2y th\u01b0 m\u1ee5c d\u1ef1 \u00e1n, t\u00ecm \u0111\u1ebfn <code>src\/main\/resources\/templates<\/code>.<\/li>\n\n\n\n<li>T\u1ea1o m\u1ed9t file HTML m\u1edbi trong th\u01b0 m\u1ee5c n\u00e0y v\u00e0 \u0111\u1eb7t t\u00ean l\u00e0 <code>greeting.html<\/code>.<\/li>\n\n\n\n<li>\u0110i\u1ec1n n\u1ed9i dung sau v\u00e0o file <code>greeting.html<\/code>:<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\" xmlns:th=\"http:\/\/www.thymeleaf.org\"&gt;\n&lt;head&gt;\n    &lt;meta charset=\"UTF-8\"&gt;\n    &lt;title&gt;Greeting Page&lt;\/title&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;h1&gt;Hello, &lt;span th:text=\"${message}\"&gt;Guest&lt;\/span&gt;!&lt;\/h1&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n\n\n\n<p><strong>Gi\u1ea3i th\u00edch:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>xmlns:th=\"http:\/\/www.thymeleaf.org\"<\/code>: Khai b\u00e1o \u0111\u1ec3 s\u1eed d\u1ee5ng c\u00e1c thu\u1ed9c t\u00ednh c\u1ee7a Thymeleaf.<\/li>\n\n\n\n<li><code>&lt;span th:text=\"${message}\"&gt;Guest&lt;\/span&gt;<\/code>: \u0110\u00e2y l\u00e0 c\u00fa ph\u00e1p c\u1ee7a Thymeleaf. N\u00f3 s\u1ebd l\u1ea5y gi\u00e1 tr\u1ecb c\u1ee7a thu\u1ed9c t\u00ednh message m\u00e0 ch\u00fang ta \u0111\u00e3 \u0111\u1eb7t trong Controller v\u00e0 ch\u00e8n n\u00f3 v\u00e0o trong th\u1ebb <code>&lt;span&gt;<\/code>. <code>\"Guest\"<\/code> ch\u1ec9 l\u00e0 n\u1ed9i dung gi\u1eef ch\u1ed7, s\u1ebd b\u1ecb thay th\u1ebf khi ch\u1ea1y.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-b\u01b0\u1edbc-4-ch\u1ea1y-\u1ee9ng-d\u1ee5ng-va-ki\u1ec3m-tra\"><strong>B\u01b0\u1edbc 4: Ch\u1ea1y \u1ee9ng d\u1ee5ng v\u00e0 ki\u1ec3m tra<\/strong><\/h3>\n\n\n\n<p>B\u00e2y gi\u1edd l\u00e0 l\u00fac xem th\u00e0nh qu\u1ea3!<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>T\u00ecm \u0111\u1ebfn file <code>SpringMvcDemoApplication.java<\/code> (file c\u00f3 ch\u1ee9a ph\u01b0\u01a1ng th\u1ee9c main).<\/li>\n\n\n\n<li>Ch\u1ea1y file n\u00e0y b\u1eb1ng c\u00e1ch nh\u1ea5n chu\u1ed9t ph\u1ea3i v\u00e0 ch\u1ecdn &#8220;Run&#8221;.<\/li>\n\n\n\n<li>M\u1edf tr\u00ecnh duy\u1ec7t web v\u00e0 truy c\u1eadp v\u00e0o m\u1ed9t trong hai \u0111\u1ecba ch\u1ec9 sau:<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>http:&#47;&#47;localhost:8080\/hello<\/code><\/pre>\n\n\n\n<p>K\u1ebft qu\u1ea3: Trang web hi\u1ec3n th\u1ecb &#8220;Hello, World!&#8221;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>http:&#47;&#47;localhost:8080\/hello?name=Spring<\/code><\/pre>\n\n\n\n<p>K\u1ebft qu\u1ea3: Trang web hi\u1ec3n th\u1ecb &#8220;Hello, Spring!&#8221;<\/p>\n\n\n\n<p>V\u1eady l\u00e0 b\u1ea1n \u0111\u00e3 x\u00e2y d\u1ef1ng v\u00e0 ch\u1ea1y th\u00e0nh c\u00f4ng \u1ee9ng d\u1ee5ng Spring MVC \u0111\u1ea7u ti\u00ean c\u1ee7a m\u00ecnh! T\u1eeb n\u1ec1n t\u1ea3ng n\u00e0y, b\u1ea1n c\u00f3 th\u1ec3 ph\u00e1t tri\u1ec3n th\u00eam nhi\u1ec1u t\u00ednh n\u0103ng ph\u1ee9c t\u1ea1p h\u01a1n.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-11-nguyen-t\u1eafc-ap-d\u1ee5ng-spring-mvc-hi\u1ec7u-qu\u1ea3\"><span class=\"ez-toc-section\" id=\"11_nguyen_tac_ap_dung_Spring_MVC_hieu_qua\"><\/span><strong>11 nguy\u00ean t\u1eafc \u00e1p d\u1ee5ng Spring MVC hi\u1ec7u qu\u1ea3<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>N\u1eafm v\u1eefng c\u00e1c kh\u00e1i ni\u1ec7m c\u01a1 b\u1ea3n l\u00e0 b\u01b0\u1edbc \u0111\u1ea7u ti\u00ean. \u0110\u1ec3 tr\u1edf th\u00e0nh m\u1ed9t l\u1eadp tr\u00ecnh vi\u00ean Spring MVC gi\u1ecfi, b\u1ea1n c\u1ea7n \u00e1p d\u1ee5ng c\u00e1c nguy\u00ean t\u1eafc v\u00e0 kinh nghi\u1ec7m sau v\u00e0o d\u1ef1 \u00e1n th\u1ef1c t\u1ebf:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-thi\u1ebft-k\u1ebf-controller\"><strong>Thi\u1ebft k\u1ebf Controller<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Gi\u1eef Controller &#8220;m\u1ecfng&#8221; (Thin Controllers)<\/strong>: Nguy\u00ean t\u1eafc quan tr\u1ecdng nh\u1ea5t l\u00e0 kh\u00f4ng \u0111\u1eb7t logic nghi\u1ec7p v\u1ee5 ph\u1ee9c t\u1ea1p v\u00e0o Controller. Vai tr\u00f2 ch\u00ednh c\u1ee7a Controller l\u00e0 ti\u1ebfp nh\u1eadn request, g\u1ecdi \u0111\u1ebfn l\u1edbp Service \u0111\u1ec3 x\u1eed l\u00fd logic, v\u00e0 tr\u1ea3 v\u1ec1 ModelAndView ho\u1eb7c d\u1eef li\u1ec7u. \u0110i\u1ec1u n\u00e0y gi\u00fap code d\u1ec5 b\u1ea3o tr\u00ec v\u00e0 ki\u1ec3m th\u1eed h\u01a1n.<\/li>\n\n\n\n<li><strong>S\u1eed d\u1ee5ng HTTP Methods \u0111\u00fang ng\u1eef ngh\u0129a<\/strong>: H\u00e3y t\u00f4n tr\u1ecdng \u00fd ngh\u0129a c\u1ee7a c\u00e1c ph\u01b0\u01a1ng th\u1ee9c HTTP. D\u00f9ng <code>GET<\/code> \u0111\u1ec3 l\u1ea5y d\u1eef li\u1ec7u, <code>POST<\/code> \u0111\u1ec3 t\u1ea1o m\u1edbi, <code>PUT<\/code>\/<code>PATCH<\/code> \u0111\u1ec3 c\u1eadp nh\u1eadt, v\u00e0 <code>DELETE<\/code> \u0111\u1ec3 x\u00f3a. \u0110i\u1ec1u n\u00e0y gi\u00fap c\u00e1c API c\u1ee7a b\u1ea1n tr\u1edf n\u00ean r\u00f5 r\u00e0ng v\u00e0 d\u1ec5 hi\u1ec3u.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-qu\u1ea3n-ly-view-va-model\"><strong>Qu\u1ea3n l\u00fd View v\u00e0 Model<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Tr\u00e1nh logic ph\u1ee9c t\u1ea1p trong View<\/strong>: L\u1edbp View (JSP, Thymeleaf) ch\u1ec9 n\u00ean ch\u1ecbu tr\u00e1ch nhi\u1ec7m hi\u1ec3n th\u1ecb d\u1eef li\u1ec7u. H\u1ea1n ch\u1ebf t\u1ed1i \u0111a c\u00e1c v\u00f2ng l\u1eb7p, \u0111i\u1ec1u ki\u1ec7n ph\u1ee9c t\u1ea1p hay t\u00ednh to\u00e1n trong View. H\u00e3y chu\u1ea9n b\u1ecb s\u1eb5n d\u1eef li\u1ec7u c\u1ea7n thi\u1ebft t\u1eeb Controller.<\/li>\n\n\n\n<li><strong>S\u1eed d\u1ee5ng <code>@ModelAttribute<\/code> hi\u1ec7u qu\u1ea3<\/strong>: D\u00f9ng <code>@ModelAttribute<\/code> tr\u00ean c\u00e1c ph\u01b0\u01a1ng th\u1ee9c \u0111\u1ec3 chu\u1ea9n b\u1ecb c\u00e1c d\u1eef li\u1ec7u chung (v\u00ed d\u1ee5: danh s\u00e1ch c\u00e1c danh m\u1ee5c s\u1ea3n ph\u1ea9m) cho nhi\u1ec1u request trong c\u00f9ng m\u1ed9t Controller, tr\u00e1nh l\u1eb7p l\u1ea1i code.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-b\u1ea3o-m\u1eadt-nbsp\"><strong>B\u1ea3o m\u1eadt&nbsp;<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>T\u00edch h\u1ee3p Spring Security<\/strong>: \u0110\u1ed1i v\u1edbi b\u1ea5t k\u1ef3 \u1ee9ng d\u1ee5ng n\u00e0o c\u1ea7n x\u00e1c th\u1ef1c v\u00e0 ph\u00e2n quy\u1ec1n, <strong>Spring Security<\/strong> l\u00e0 l\u1ef1a ch\u1ecdn h\u00e0ng \u0111\u1ea7u. N\u00f3 t\u00edch h\u1ee3p li\u1ec1n m\u1ea1ch v\u1edbi Spring MVC \u0111\u1ec3 b\u1ea3o v\u1ec7 c\u00e1c endpoint c\u1ee7a b\u1ea1n.<\/li>\n\n\n\n<li><strong>Lu\u00f4n x\u00e1c th\u1ef1c d\u1eef li\u1ec7u \u0111\u1ea7u v\u00e0o (Validate Input)<\/strong>: \u0110\u1eebng bao gi\u1edd tin t\u01b0\u1edfng d\u1eef li\u1ec7u t\u1eeb ng\u01b0\u1eddi d\u00f9ng. H\u00e3y s\u1eed d\u1ee5ng Bean Validation v\u00e0 c\u00e1c k\u1ef9 thu\u1eadt l\u00e0m s\u1ea1ch d\u1eef li\u1ec7u \u0111\u1ec3 ng\u0103n ch\u1eb7n c\u00e1c l\u1ed7 h\u1ed5ng b\u1ea3o m\u1eadt ph\u1ed5 bi\u1ebfn nh\u01b0 <strong>Cross-Site Scripting (XSS)<\/strong> v\u00e0 <strong>SQL Injection<\/strong>. Spring Security c\u0169ng cung c\u1ea5p c\u01a1 ch\u1ebf b\u1ea3o v\u1ec7 ch\u1ed1ng l\u1ea1i <strong>Cross-Site Request Forgery (CSRF)<\/strong>.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-t\u1ed1i-\u01b0u-hi\u1ec7u-nang-nbsp\"><strong>T\u1ed1i \u01b0u hi\u1ec7u n\u0103ng&nbsp;<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Caching<\/strong>: \u0110\u1ed1i v\u1edbi c\u00e1c d\u1eef li\u1ec7u \u00edt thay \u0111\u1ed5i (v\u00ed d\u1ee5: th\u00f4ng tin c\u1ea5u h\u00ecnh, danh s\u00e1ch t\u1ec9nh th\u00e0nh), h\u00e3y \u00e1p d\u1ee5ng c\u01a1 ch\u1ebf caching (b\u1ed9 nh\u1edb \u0111\u1ec7m) \u0111\u1ec3 gi\u1ea3m s\u1ed1 l\u1ea7n truy v\u1ea5n xu\u1ed1ng c\u01a1 s\u1edf d\u1eef li\u1ec7u, gi\u00fap t\u0103ng t\u1ed1c \u0111\u1ed9 ph\u1ea3n h\u1ed3i c\u1ee7a \u1ee9ng d\u1ee5ng.<\/li>\n\n\n\n<li><strong>S\u1eed d\u1ee5ng View ph\u00f9 h\u1ee3p<\/strong>: C\u00e1c template engine hi\u1ec7n \u0111\u1ea1i nh\u01b0 <strong>Thymeleaf<\/strong> th\u01b0\u1eddng \u0111\u01b0\u1ee3c \u01b0a chu\u1ed9ng h\u01a1n JSP v\u00ec c\u00fa ph\u00e1p t\u1ef1 nhi\u00ean v\u00e0 kh\u1ea3 n\u0103ng ho\u1ea1t \u0111\u1ed9ng \u0111\u1ed9c l\u1eadp. Tuy nhi\u00ean, h\u00e3y xem x\u00e9t hi\u1ec7u n\u0103ng c\u1ee7a t\u1eebng lo\u1ea1i trong b\u1ed1i c\u1ea3nh c\u1ee5 th\u1ec3 c\u1ee7a d\u1ef1 \u00e1n.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-vi\u1ebft-unit-test-va-integration-test-nbsp\"><strong>Vi\u1ebft Unit Test v\u00e0 Integration Test&nbsp;<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>S\u1eed d\u1ee5ng MockMvc<\/strong>: Spring MVC cung c\u1ea5p m\u1ed9t framework ki\u1ec3m th\u1eed m\u1ea1nh m\u1ebd l\u00e0 <strong>MockMvc<\/strong>. N\u00f3 cho ph\u00e9p b\u1ea1n th\u1ef1c hi\u1ec7n c\u00e1c request HTTP gi\u1ea3 l\u1eadp \u0111\u1ebfn Controller m\u00e0 kh\u00f4ng c\u1ea7n kh\u1edfi \u0111\u1ed9ng to\u00e0n b\u1ed9 server, gi\u00fap vi\u1ec7c vi\u1ebft unit test v\u00e0 integration test cho t\u1ea7ng web tr\u1edf n\u00ean d\u1ec5 d\u00e0ng v\u00e0 nhanh ch\u00f3ng.<\/li>\n\n\n\n<li><strong>Ki\u1ec3m th\u1eed l\u1edbp Service<\/strong>: V\u00ec logic nghi\u1ec7p v\u1ee5 n\u1eb1m \u1edf l\u1edbp Service, h\u00e3y \u0111\u1ea3m b\u1ea3o r\u1eb1ng b\u1ea1n c\u00f3 \u0111\u1ea7y \u0111\u1ee7 unit test cho c\u00e1c l\u1edbp n\u00e0y.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-\u01b0u-tien-c\u1ea5u-hinh-b\u1eb1ng-java\"><strong>\u01afu ti\u00ean c\u1ea5u h\u00ecnh b\u1eb1ng Java<\/strong><\/h3>\n\n\n\n<p>\u0110\u1ed1i v\u1edbi c\u00e1c d\u1ef1 \u00e1n m\u1edbi, h\u00e3y s\u1eed d\u1ee5ng c\u00e1ch c\u1ea5u h\u00ecnh b\u1eb1ng Java (Java-based configuration). C\u00e1ch ti\u1ebfp c\u1eadn n\u00e0y an to\u00e0n h\u01a1n v\u1ec1 ki\u1ec3u d\u1eef li\u1ec7u, d\u1ec5 d\u00e0ng t\u00e1i c\u1ea5u tr\u00fac (refactor) v\u00e0 \u0111i\u1ec1u h\u01b0\u1edbng trong IDE so v\u1edbi vi\u1ec7c s\u1eed d\u1ee5ng c\u00e1c file XML. Spring Boot \u0111\u00e3 m\u1eb7c \u0111\u1ecbnh s\u1eed d\u1ee5ng ph\u01b0\u01a1ng ph\u00e1p n\u00e0y.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-t\u01b0\u01a1ng-lai-c\u1ee7a-spring-mvc-va-h\u1ec7-sinh-thai-spring\"><span class=\"ez-toc-section\" id=\"Tuong_lai_cua_Spring_MVC_va_he_sinh_thai_Spring\"><\/span><strong>T\u01b0\u01a1ng lai c\u1ee7a Spring MVC v\u00e0 h\u1ec7 sinh th\u00e1i Spring<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Spring MVC kh\u00f4ng ph\u1ea3i l\u00e0 m\u1ed9t c\u00f4ng ngh\u1ec7 \u0111\u1ee9ng y\u00ean. N\u00f3 li\u00ean t\u1ee5c ph\u00e1t tri\u1ec3n c\u00f9ng v\u1edbi to\u00e0n b\u1ed9 h\u1ec7 sinh th\u00e1i Spring \u0111\u1ec3 \u0111\u00e1p \u1ee9ng c\u00e1c y\u00eau c\u1ea7u c\u1ee7a \u1ee9ng d\u1ee5ng hi\u1ec7n \u0111\u1ea1i. D\u01b0\u1edbi \u0111\u00e2y l\u00e0 nh\u1eefng xu h\u01b0\u1edbng \u0111\u1ecbnh h\u00ecnh t\u01b0\u01a1ng lai c\u1ee7a vi\u1ec7c ph\u00e1t tri\u1ec3n web v\u1edbi Spring.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-spring-webflux-lan-gio-m\u1edbi-cho-l\u1eadp-trinh-ph\u1ea3n-h\u1ed3i-reactive\"><strong>Spring WebFlux: L\u00e0n gi\u00f3 m\u1edbi cho l\u1eadp tr\u00ecnh ph\u1ea3n h\u1ed3i (Reactive)<\/strong><\/h3>\n\n\n\n<p>B\u00ean c\u1ea1nh Spring MVC truy\u1ec1n th\u1ed1ng, Spring Framework 5 \u0111\u00e3 gi\u1edbi thi\u1ec7u <strong>Spring WebFlux<\/strong>, m\u1ed9t framework web ho\u00e0n to\u00e0n m\u1edbi \u0111\u01b0\u1ee3c x\u00e2y d\u1ef1ng d\u1ef1a tr\u00ean tri\u1ebft l\u00fd l\u1eadp tr\u00ecnh ph\u1ea3n h\u1ed3i (reactive programming).<\/p>\n\n\n\n<p>Kh\u00f4ng gi\u1ed1ng nh\u01b0 m\u00f4 h\u00ecnh m\u1ed9t lu\u1ed3ng cho m\u1ed7i request (thread-per-request) c\u1ee7a MVC, WebFlux s\u1eed d\u1ee5ng m\u00f4 h\u00ecnh b\u1ea5t \u0111\u1ed3ng b\u1ed9, kh\u00f4ng ch\u1eb7n (non-blocking). N\u00f3 c\u00f3 th\u1ec3 x\u1eed l\u00fd s\u1ed1 l\u01b0\u1ee3ng k\u1ebft n\u1ed1i \u0111\u1ed3ng th\u1eddi c\u1ef1c l\u1edbn ch\u1ec9 v\u1edbi m\u1ed9t s\u1ed1 l\u01b0\u1ee3ng lu\u1ed3ng nh\u1ecf, gi\u00fap ti\u1ebft ki\u1ec7m t\u00e0i nguy\u00ean h\u1ec7 th\u1ed1ng m\u1ed9t c\u00e1ch \u0111\u00e1ng k\u1ec3.<\/p>\n\n\n\n<p><strong>Khi n\u00e0o n\u00ean c\u00e2n nh\u1eafc WebFlux?<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Khi b\u1ea1n c\u1ea7n x\u00e2y d\u1ef1ng c\u00e1c h\u1ec7 th\u1ed1ng c\u00f3 kh\u1ea3 n\u0103ng ch\u1ecbu t\u1ea3i r\u1ea5t cao, c\u00e1c \u1ee9ng d\u1ee5ng streaming d\u1eef li\u1ec7u theo th\u1eddi gian th\u1ef1c (real-time).<\/li>\n\n\n\n<li>C\u00e1c \u1ee9ng d\u1ee5ng c\u00f3 nhi\u1ec1u t\u00e1c v\u1ee5 ch\u1edd \u0111\u1ee3i I\/O (v\u00ed d\u1ee5: g\u1ecdi \u0111\u1ebfn c\u00e1c API kh\u00e1c, truy v\u1ea5n c\u01a1 s\u1edf d\u1eef li\u1ec7u).<\/li>\n\n\n\n<li>Ki\u1ebfn tr\u00fac Microservices c\u1ea7n giao ti\u1ebfp hi\u1ec7u qu\u1ea3 v\u00e0 c\u00f3 kh\u1ea3 n\u0103ng ph\u1ee5c h\u1ed3i l\u1ed7i cao.<\/li>\n<\/ul>\n\n\n\n<p>Tuy nhi\u00ean, <strong>Spring MVC v\u1eabn l\u00e0 l\u1ef1a ch\u1ecdn ho\u00e0n h\u1ea3o<\/strong> v\u00e0 \u0111\u01a1n gi\u1ea3n h\u01a1n cho ph\u1ea7n l\u1edbn c\u00e1c \u1ee9ng d\u1ee5ng web truy\u1ec1n th\u1ed1ng, c\u00e1c \u1ee9ng d\u1ee5ng CRUD, v\u00e0 khi logic nghi\u1ec7p v\u1ee5 l\u00e0 th\u1ee9 chi\u1ebfm nhi\u1ec1u t\u00e0i nguy\u00ean CPU h\u01a1n l\u00e0 I\/O.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-s\u1ef1-phat-tri\u1ec3n-c\u1ee7a-spring-boot\"><strong>S\u1ef1 ph\u00e1t tri\u1ec3n c\u1ee7a Spring Boot<\/strong><\/h3>\n\n\n\n<p><strong><a href=\"https:\/\/itviec.com\/blog\/spring-boot-la-gi\/\" target=\"_blank\" rel=\"noreferrer noopener\">Spring Boot<\/a><\/strong> kh\u00f4ng ph\u1ea3i l\u00e0 t\u01b0\u01a1ng lai xa v\u1eddi m\u00e0 l\u00e0 hi\u1ec7n t\u1ea1i v\u00e0 l\u00e0 m\u1ed9t ph\u1ea7n kh\u00f4ng th\u1ec3 t\u00e1ch r\u1eddi khi l\u00e0m vi\u1ec7c v\u1edbi Spring MVC. S\u1ef1 ra \u0111\u1eddi c\u1ee7a n\u00f3 \u0111\u00e3 thay \u0111\u1ed5i ho\u00e0n to\u00e0n cu\u1ed9c ch\u01a1i.<\/p>\n\n\n\n<p>Nh\u1edd Spring Boot, vi\u1ec7c kh\u1edfi t\u1ea1o v\u00e0 ph\u00e1t tri\u1ec3n m\u1ed9t \u1ee9ng d\u1ee5ng Spring MVC tr\u1edf n\u00ean nhanh ch\u00f3ng v\u00e0 d\u1ec5 d\u00e0ng h\u01a1n bao gi\u1edd h\u1ebft, v\u00ec n\u00f3 ho\u1ea1t \u0111\u1ed9ng d\u1ef1a tr\u00ean nguy\u00ean t\u1eafc &#8220;convention over configuration&#8221; (quy \u01b0\u1edbc c\u1ea5u h\u00ecnh).<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>T\u1ef1 \u0111\u1ed9ng c\u1ea5u h\u00ecnh (Auto-configuration):<\/strong> T\u1ef1 \u0111\u1ed9ng thi\u1ebft l\u1eadp c\u00e1c bean c\u1ea7n thi\u1ebft nh\u01b0 DispatcherServlet, ViewResolver, DataSource&#8230; b\u1ea1n g\u1ea7n nh\u01b0 kh\u00f4ng c\u1ea7n file c\u1ea5u h\u00ecnh n\u00e0o.<\/li>\n\n\n\n<li><strong>M\u00e1y ch\u1ee7 nh\u00fang (Embedded Server):<\/strong> T\u00edch h\u1ee3p s\u1eb5n Tomcat, Jetty ho\u1eb7c Undertow. B\u1ea1n ch\u1ec9 c\u1ea7n ch\u1ea1y m\u1ed9t file JAR duy nh\u1ea5t m\u00e0 kh\u00f4ng c\u1ea7n tri\u1ec3n khai file WAR l\u00ean m\u1ed9t server ri\u00eang bi\u1ec7t.<\/li>\n\n\n\n<li><strong>Qu\u1ea3n l\u00fd dependencies:<\/strong> C\u00e1c g\u00f3i starter (nh\u01b0 spring-boot-starter-web) gi\u00fap b\u1ea1n th\u00eam t\u1ea5t c\u1ea3 c\u00e1c th\u01b0 vi\u1ec7n c\u1ea7n thi\u1ebft v\u1edbi phi\u00ean b\u1ea3n t\u01b0\u01a1ng th\u00edch ch\u1ec9 b\u1eb1ng m\u1ed9t khai b\u00e1o duy nh\u1ea5t.<\/li>\n<\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>\u0110\u1ecdc chi ti\u1ebft: <strong><a href=\"https:\/\/itviec.com\/blog\/huong-dan-spring-boot-tutorial\/\" target=\"_blank\" rel=\"noreferrer noopener\">Spring Boot tutorial chi ti\u1ebft t\u1eeb A-Z cho l\u1eadp tr\u00ecnh vi\u00ean Java<\/a><\/strong><\/em><\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-xu-h\u01b0\u1edbng-microservices-spring-v\u1eabn-la-tr\u1ee5-c\u1ed9t-chinh\"><strong>Xu h\u01b0\u1edbng microservices: Spring v\u1eabn l\u00e0 tr\u1ee5 c\u1ed9t ch\u00ednh<\/strong><\/h3>\n\n\n\n<p>Ki\u1ebfn tr\u00fac microservices, n\u01a1i m\u1ed9t \u1ee9ng d\u1ee5ng l\u1edbn \u0111\u01b0\u1ee3c chia th\u00e0nh nhi\u1ec1u d\u1ecbch v\u1ee5 nh\u1ecf, \u0111\u1ed9c l\u1eadp, \u0111\u00e3 tr\u1edf th\u00e0nh ti\u00eau chu\u1ea9n cho c\u00e1c h\u1ec7 th\u1ed1ng ph\u1ee9c t\u1ea1p.<\/p>\n\n\n\n<p>Spring MVC\/Spring Boot v\u1eabn l\u00e0 n\u1ec1n t\u1ea3ng s\u1ed1 m\u1ed9t \u0111\u1ec3 x\u00e2y d\u1ef1ng c\u00e1c microservice trong th\u1ebf gi\u1edbi Java v\u00ec:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Spring Boot gi\u00fap t\u1ea1o ra c\u00e1c d\u1ecbch v\u1ee5 nh\u1ecf, nh\u1eb9, c\u00f3 th\u1ec3 \u0111\u00f3ng g\u00f3i v\u00e0 ch\u1ea1y \u0111\u1ed9c l\u1eadp m\u1ed9t c\u00e1ch c\u1ef1c k\u1ef3 nhanh ch\u00f3ng.<\/li>\n\n\n\n<li>Spring MVC v\u1edbi <code>@RestController<\/code> gi\u00fap vi\u1ec7c x\u00e2y d\u1ef1ng c\u00e1c RESTful API \u0111\u1ec3 c\u00e1c service giao ti\u1ebfp v\u1edbi nhau tr\u1edf n\u00ean v\u00f4 c\u00f9ng \u0111\u01a1n gi\u1ea3n.<\/li>\n\n\n\n<li>H\u1ec7 sinh th\u00e1i Spring Cloud \u0111\u01b0\u1ee3c x\u00e2y d\u1ef1ng tr\u00ean n\u1ec1n t\u1ea3ng Spring Boot, cung c\u1ea5p \u0111\u1ea7y \u0111\u1ee7 c\u00e1c c\u00f4ng c\u1ee5 c\u1ea7n thi\u1ebft cho m\u1ed9t ki\u1ebfn tr\u00fac microservices nh\u01b0: Service Discovery (Eureka), API Gateway, Distributed Configuration&#8230;<\/li>\n<\/ul>\n\n\n\n<p>T\u00f3m l\u1ea1i, d\u00f9 c\u00e1c m\u00f4 h\u00ecnh m\u1edbi nh\u01b0 WebFlux ra \u0111\u1eddi, Spring MVC &#8211; v\u1edbi s\u1ef1 h\u1ed7 tr\u1ee3 \u0111\u1eafc l\u1ef1c c\u1ee7a Spring Boot v\u1eabn l\u00e0 m\u1ed9t l\u1ef1a ch\u1ecdn c\u1ef1c k\u1ef3 m\u1ea1nh m\u1ebd, ph\u00f9 h\u1ee3p v\u1edbi \u0111\u1ea1i \u0111a s\u1ed1 c\u00e1c b\u00e0i to\u00e1n v\u00e0 l\u00e0 tr\u00e1i tim c\u1ee7a ki\u1ebfn tr\u00fac microservices hi\u1ec7n \u0111\u1ea1i.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-cac-cau-h\u1ecfi-th\u01b0\u1eddng-g\u1eb7p-v\u1ec1-spring-mvc\"><span class=\"ez-toc-section\" id=\"Cac_cau_hoi_thuong_gap_ve_Spring_MVC\"><\/span><strong>C\u00e1c c\u00e2u h\u1ecfi th\u01b0\u1eddng g\u1eb7p v\u1ec1 Spring MVC<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-spring-mvc-co-con-phu-h\u1ee3p-trong-th\u1eddi-d\u1ea1i-c\u1ee7a-react-angular-khong\"><strong>Spring MVC c\u00f3 c\u00f2n ph\u00f9 h\u1ee3p trong th\u1eddi \u0111\u1ea1i c\u1ee7a React\/Angular kh\u00f4ng?<\/strong><\/h3>\n\n\n\n<p><strong>Ho\u00e0n to\u00e0n ph\u00f9 h\u1ee3p.<\/strong> Vai tr\u00f2 c\u1ee7a Spring MVC \u0111\u00e3 thay \u0111\u1ed5i m\u1ed9t ch\u00fat. Thay v\u00ec render c\u00e1c trang HTML ph\u00eda server, gi\u1edd \u0111\u00e2y Spring MVC th\u01b0\u1eddng \u0111\u01b0\u1ee3c d\u00f9ng \u0111\u1ec3 t\u1ea1o ra c\u00e1c <strong>RESTful API<\/strong> (s\u1eed d\u1ee5ng <code>@RestController<\/code>). C\u00e1c framework frontend nh\u01b0 React, Angular, Vue.js s\u1ebd g\u1ecdi \u0111\u1ebfn c\u00e1c API n\u00e0y \u0111\u1ec3 l\u1ea5y d\u1eef li\u1ec7u v\u00e0 t\u1ef1 x\u1eed l\u00fd vi\u1ec7c hi\u1ec3n th\u1ecb tr\u00ean tr\u00ecnh duy\u1ec7t c\u1ee7a ng\u01b0\u1eddi d\u00f9ng.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-toi-co-b\u1eaft-bu\u1ed9c-ph\u1ea3i-dung-l\u1edbp-modelandview-khong\"><strong>T\u00f4i c\u00f3 b\u1eaft bu\u1ed9c ph\u1ea3i d\u00f9ng l\u1edbp <\/strong><strong>ModelAndView<\/strong><strong> kh\u00f4ng?<\/strong><\/h3>\n\n\n\n<p><strong>Kh\u00f4ng b\u1eaft bu\u1ed9c.<\/strong> ModelAndView l\u00e0 m\u1ed9t c\u00e1ch \u0111\u1ec3 tr\u1ea3 v\u1ec1 c\u1ea3 Model v\u00e0 View c\u00f9ng l\u00fac. Tuy nhi\u00ean, c\u00f3 m\u1ed9t c\u00e1ch ti\u1ebfp c\u1eadn ph\u1ed5 bi\u1ebfn v\u00e0 linh ho\u1ea1t h\u01a1n l\u00e0:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Khai b\u00e1o m\u1ed9t tham s\u1ed1 Model trong ph\u01b0\u01a1ng th\u1ee9c c\u1ee7a b\u1ea1n.<\/li>\n\n\n\n<li>D\u00f9ng <code>model.addAttribute(...)<\/code> \u0111\u1ec3 th\u00eam d\u1eef li\u1ec7u.<\/li>\n\n\n\n<li>Tr\u1ea3 v\u1ec1 m\u1ed9t String l\u00e0 t\u00ean c\u1ee7a View.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-li\u1ec7u-h\u1ecdc-spring-mvc-co-con-quan-tr\u1ecdng-trong-nam-2025-khong\"><strong>Li\u1ec7u h\u1ecdc Spring MVC c\u00f3 c\u00f2n quan tr\u1ecdng trong n\u0103m 2025 kh\u00f4ng?<\/strong><\/h3>\n\n\n\n<p><strong>C\u1ef1c k\u1ef3 quan tr\u1ecdng.<\/strong> Spring MVC, \u0111\u1eb7c bi\u1ec7t l\u00e0 khi k\u1ebft h\u1ee3p v\u1edbi Spring Boot, v\u1eabn l\u00e0 ti\u00eau chu\u1ea9n h\u00e0ng \u0111\u1ea7u trong h\u1ec7 sinh th\u00e1i Java \u0111\u1ec3 x\u00e2y d\u1ef1ng c\u00e1c \u1ee9ng d\u1ee5ng web v\u00e0 microservices. H\u00e0ng ng\u00e0n c\u00f4ng ty l\u1edbn v\u00e0 c\u00e1c d\u1ef1 \u00e1n doanh nghi\u1ec7p v\u1eabn \u0111ang s\u1eed d\u1ee5ng v\u00e0 ph\u00e1t tri\u1ec3n \u1ee9ng d\u1ee5ng d\u1ef1a tr\u00ean n\u1ec1n t\u1ea3ng n\u00e0y. N\u1eafm v\u1eefng Spring MVC l\u00e0 m\u1ed9t k\u1ef9 n\u0103ng c\u1ed1t l\u00f5i v\u00e0 c\u00f3 gi\u00e1 tr\u1ecb cao \u0111\u1ed1i v\u1edbi b\u1ea5t k\u1ef3 l\u1eadp tr\u00ecnh vi\u00ean Java n\u00e0o.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-t\u1ed5ng-k\u1ebft\"><span class=\"ez-toc-section\" id=\"Tong_ket\"><\/span><strong>T\u1ed5ng k\u1ebft<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Qua b\u00e0i vi\u1ebft, ch\u00fang ta \u0111\u00e3 kh\u00e1m ph\u00e1 to\u00e0n di\u1ec7n Spring MVC, t\u1eeb ki\u1ebfn tr\u00fac c\u1ed1t l\u00f5i \u0111\u1ebfn c\u00e1c \u1ee9ng d\u1ee5ng th\u1ef1c t\u1ebf. R\u00f5 r\u00e0ng, v\u1edbi s\u1ef1 tr\u1ee3 l\u1ef1c c\u1ee7a Spring Boot, Spring MVC v\u1eabn l\u00e0 m\u1ed9t l\u1ef1a ch\u1ecdn h\u00e0ng \u0111\u1ea7u, c\u1ef1c k\u1ef3 m\u1ea1nh m\u1ebd \u0111\u1ec3 x\u00e2y d\u1ef1ng t\u1eeb c\u00e1c trang web truy\u1ec1n th\u1ed1ng cho \u0111\u1ebfn nh\u1eefng RESTful API ph\u1ee9c t\u1ea1p trong ki\u1ebfn tr\u00fac microservices.<\/p>\n\n\n\n<p>Hy v\u1ecdng b\u00e0i vi\u1ebft \u0111\u00e3 cung c\u1ea5p cho b\u1ea1n m\u1ed9t ngu\u1ed3n th\u00f4ng tin phong ph\u00fa, v\u1eefng ch\u1eafc. Gi\u1edd l\u00e0 l\u00fac b\u1ea1n t\u1ef1 m\u00ecnh b\u1eaft tay v\u00e0o th\u1ef1c h\u00e0nh, b\u1edfi \u0111\u00f3 ch\u00ednh l\u00e0 con \u0111\u01b0\u1eddng t\u1ed1t nh\u1ea5t \u0111\u1ec3 th\u1ef1c s\u1ef1 l\u00e0m ch\u1ee7 c\u00f4ng ngh\u1ec7 n\u00e0y. Ch\u00fac b\u1ea1n th\u00e0nh c\u00f4ng!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Trong th\u1ebf gi\u1edbi ph\u00e1t tri\u1ec3n \u1ee9ng d\u1ee5ng web b\u1eb1ng Java, Spring MVC n\u1ed5i l\u00ean nh\u01b0 m\u1ed9t trong nh\u1eefng framework m\u1ea1nh m\u1ebd v\u00e0 ph\u1ed5 bi\u1ebfn nh\u1ea5t. Vi\u1ec7c n\u1eafm v\u1eefng Spring MVC kh\u00f4ng ch\u1ec9 l\u00e0 h\u1ecdc m\u1ed9t c\u00f4ng c\u1ee5, m\u00e0 l\u00e0 ti\u1ebfp c\u1eadn m\u1ed9t ph\u01b0\u01a1ng ph\u00e1p lu\u1eadn \u0111\u1ec3 ph\u00e1t tri\u1ec3n \u1ee9ng d\u1ee5ng web m\u1ed9t c\u00e1ch c\u00f3 t\u1ed5 [&hellip;]<\/p>\n","protected":false},"author":203,"featured_media":89051,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_gspb_post_css":"","footnotes":""},"categories":[109],"tags":[],"class_list":["post-89046","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-chuyen-mon-it"],"blocksy_meta":[],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.8 (Yoast SEO v27.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Spring MVC l\u00e0 g\u00ec: H\u01b0\u1edbng d\u1eabn x\u00e2y d\u1ef1ng \u1ee9ng d\u1ee5ng v\u1edbi Spring MVC - ITviec Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/\" \/>\n<meta property=\"og:locale\" content=\"vi_VN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Spring MVC l\u00e0 g\u00ec: H\u01b0\u1edbng d\u1eabn x\u00e2y d\u1ef1ng \u1ee9ng d\u1ee5ng v\u1edbi Spring MVC\" \/>\n<meta property=\"og:description\" content=\"Trong th\u1ebf gi\u1edbi ph\u00e1t tri\u1ec3n \u1ee9ng d\u1ee5ng web b\u1eb1ng Java, Spring MVC n\u1ed5i l\u00ean nh\u01b0 m\u1ed9t trong nh\u1eefng framework m\u1ea1nh m\u1ebd v\u00e0 ph\u1ed5 bi\u1ebfn nh\u1ea5t. Vi\u1ec7c n\u1eafm v\u1eefng Spring MVC\" \/>\n<meta property=\"og:url\" content=\"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/\" \/>\n<meta property=\"og:site_name\" content=\"ITviec Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/ITviec\" \/>\n<meta property=\"article:published_time\" content=\"2025-07-06T16:27:24+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-07-06T16:27:27+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/spring-mvc-scaled.png\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"1347\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Tien Tran\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@ITviec\" \/>\n<meta name=\"twitter:site\" content=\"@ITviec\" \/>\n<meta name=\"twitter:label1\" content=\"\u0110\u01b0\u1ee3c vi\u1ebft b\u1edfi\" \/>\n\t<meta name=\"twitter:data1\" content=\"Tien Tran\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u01af\u1edbc t\u00ednh th\u1eddi gian \u0111\u1ecdc\" \/>\n\t<meta name=\"twitter:data2\" content=\"26 ph\u00fat\" \/>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Spring MVC l\u00e0 g\u00ec: H\u01b0\u1edbng d\u1eabn x\u00e2y d\u1ef1ng \u1ee9ng d\u1ee5ng v\u1edbi Spring MVC - ITviec Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/","og_locale":"vi_VN","og_type":"article","og_title":"Spring MVC l\u00e0 g\u00ec: H\u01b0\u1edbng d\u1eabn x\u00e2y d\u1ef1ng \u1ee9ng d\u1ee5ng v\u1edbi Spring MVC","og_description":"Trong th\u1ebf gi\u1edbi ph\u00e1t tri\u1ec3n \u1ee9ng d\u1ee5ng web b\u1eb1ng Java, Spring MVC n\u1ed5i l\u00ean nh\u01b0 m\u1ed9t trong nh\u1eefng framework m\u1ea1nh m\u1ebd v\u00e0 ph\u1ed5 bi\u1ebfn nh\u1ea5t. Vi\u1ec7c n\u1eafm v\u1eefng Spring MVC","og_url":"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/","og_site_name":"ITviec Blog","article_publisher":"https:\/\/www.facebook.com\/ITviec","article_published_time":"2025-07-06T16:27:24+00:00","article_modified_time":"2025-07-06T16:27:27+00:00","og_image":[{"width":2560,"height":1347,"url":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/spring-mvc-scaled.png","type":"image\/png"}],"author":"Tien Tran","twitter_card":"summary_large_image","twitter_creator":"@ITviec","twitter_site":"@ITviec","twitter_misc":{"\u0110\u01b0\u1ee3c vi\u1ebft b\u1edfi":"Tien Tran","\u01af\u1edbc t\u00ednh th\u1eddi gian \u0111\u1ecdc":"26 ph\u00fat"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/#article","isPartOf":{"@id":"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/"},"author":{"name":"Tien Tran","@id":"https:\/\/itviec.com\/blog\/#\/schema\/person\/1595d671c49cfa2a48cd3c0a047a1298"},"headline":"Spring MVC l\u00e0 g\u00ec: H\u01b0\u1edbng d\u1eabn x\u00e2y d\u1ef1ng \u1ee9ng d\u1ee5ng v\u1edbi Spring MVC","datePublished":"2025-07-06T16:27:24+00:00","dateModified":"2025-07-06T16:27:27+00:00","mainEntityOfPage":{"@id":"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/"},"wordCount":6824,"publisher":{"@id":"https:\/\/itviec.com\/blog\/#organization"},"image":{"@id":"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/#primaryimage"},"thumbnailUrl":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/spring-mvc-scaled.png","articleSection":["Chuy\u00ean m\u00f4n IT"],"inLanguage":"vi"},{"@type":"WebPage","@id":"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/","url":"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/","name":"Spring MVC l\u00e0 g\u00ec: H\u01b0\u1edbng d\u1eabn x\u00e2y d\u1ef1ng \u1ee9ng d\u1ee5ng v\u1edbi Spring MVC - ITviec Blog","isPartOf":{"@id":"https:\/\/itviec.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/#primaryimage"},"image":{"@id":"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/#primaryimage"},"thumbnailUrl":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/spring-mvc-scaled.png","datePublished":"2025-07-06T16:27:24+00:00","dateModified":"2025-07-06T16:27:27+00:00","breadcrumb":{"@id":"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/#breadcrumb"},"inLanguage":"vi","potentialAction":[{"@type":"ReadAction","target":["https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/"]}]},{"@type":"ImageObject","inLanguage":"vi","@id":"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/#primaryimage","url":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/spring-mvc-scaled.png","contentUrl":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/spring-mvc-scaled.png","width":800,"height":421,"caption":"spring mvc l\u00e0 g\u00ec - itviec blog"},{"@type":"BreadcrumbList","@id":"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Chuy\u00ean m\u00f4n IT","item":"https:\/\/itviec.com\/blog\/chuyen-mon-it\/"},{"@type":"ListItem","position":2,"name":"Spring MVC l\u00e0 g\u00ec: H\u01b0\u1edbng d\u1eabn x\u00e2y d\u1ef1ng \u1ee9ng d\u1ee5ng v\u1edbi Spring MVC"}]},{"@type":"WebSite","@id":"https:\/\/itviec.com\/blog\/#website","url":"https:\/\/itviec.com\/blog\/","name":"ITviec Blog","description":"IT Jobs &amp; People in Vietnam","publisher":{"@id":"https:\/\/itviec.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/itviec.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"vi"},{"@type":"Organization","@id":"https:\/\/itviec.com\/blog\/#organization","name":"ITviec","url":"https:\/\/itviec.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"vi","@id":"https:\/\/itviec.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2018\/12\/itviec-black-square-facebook.png","contentUrl":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2018\/12\/itviec-black-square-facebook.png","width":1800,"height":1800,"caption":"ITviec"},"image":{"@id":"https:\/\/itviec.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/ITviec","https:\/\/x.com\/ITviec","https:\/\/www.linkedin.com\/company\/itviec","https:\/\/www.youtube.com\/channel\/UCYthAQ3bcGr57M_ag5gHDvQ"]},{"@type":"Person","@id":"https:\/\/itviec.com\/blog\/#\/schema\/person\/1595d671c49cfa2a48cd3c0a047a1298","name":"Tien Tran","image":{"@type":"ImageObject","inLanguage":"vi","@id":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2024\/05\/tien-tran-author-e1715658627643-100x100.jpg","url":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2024\/05\/tien-tran-author-e1715658627643-100x100.jpg","contentUrl":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2024\/05\/tien-tran-author-e1715658627643-100x100.jpg","caption":"Tien Tran"},"url":"https:\/\/itviec.com\/blog\/author\/tien-tran\/"}]}},"_links":{"self":[{"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/posts\/89046","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/users\/203"}],"replies":[{"embeddable":true,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/comments?post=89046"}],"version-history":[{"count":3,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/posts\/89046\/revisions"}],"predecessor-version":[{"id":89053,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/posts\/89046\/revisions\/89053"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/media\/89051"}],"wp:attachment":[{"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/media?parent=89046"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/categories?post=89046"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/tags?post=89046"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}