{"id":89206,"date":"2025-07-10T15:49:44","date_gmt":"2025-07-10T08:49:44","guid":{"rendered":"https:\/\/itviec.com\/blog\/?p=89206"},"modified":"2025-07-10T15:49:47","modified_gmt":"2025-07-10T08:49:47","slug":"spring-mvc-tutorial","status":"publish","type":"post","link":"https:\/\/itviec.com\/blog\/spring-mvc-tutorial\/","title":{"rendered":"Spring MVC tutorial: H\u01b0\u1edbng d\u1eabn x\u00e2y \u1ee9ng d\u1ee5ng web 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-tutorial\/#Kien_thuc_tong_quan_ve_Spring_MVC\" >Ki\u1ebfn th\u1ee9c t\u1ed5ng quan 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-2\" href=\"https:\/\/itviec.com\/blog\/spring-mvc-tutorial\/#Spring_MVC_tutorial_Thuc_hanh_xay_dung_ung_dung_voi_Spring_MVC\" >Spring MVC tutorial: Th\u1ef1c h\u00e0nh x\u00e2y d\u1ef1ng \u1ee9ng d\u1ee5ng v\u1edbi 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-tutorial\/#Phan_2_Xu_ly_Form_%E2%80%93_Them_cong_viec_moi\" >Ph\u1ea7n 2: X\u1eed l\u00fd Form &#8211; Th\u00eam c\u00f4ng vi\u1ec7c m\u1edbi<\/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-tutorial\/#Huong_%E2%80%9Cnang_cap%E2%80%9D_ung_dung\" >H\u01b0\u1edbng &#8220;n\u00e2ng c\u1ea5p&#8221; \u1ee9ng d\u1ee5ng<\/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-tutorial\/#Cac_cau_hoi_thuong_gap_ve_Spring_MVC_tutorial\" >C\u00e1c c\u00e2u h\u1ecfi th\u01b0\u1eddng g\u1eb7p v\u1ec1 Spring MVC tutorial<\/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-tutorial\/#Tong_ket_Spring_MVC_tutorial\" >T\u1ed5ng k\u1ebft Spring MVC tutorial<\/a><\/li><\/ul><\/nav><\/div>\n\n<p><strong><em>Khi nh\u1eafc \u0111\u1ebfn h\u1ec7 sinh th\u00e1i Java, Spring MVC lu\u00f4n l\u00e0 l\u1ef1a ch\u1ecdn h\u00e0ng \u0111\u1ea7u. Nh\u01b0ng l\u00e0m th\u1ebf n\u00e0o \u0111\u1ec3 \u00e1p d\u1ee5ng n\u00f3 m\u1ed9t c\u00e1ch hi\u1ec7u qu\u1ea3 v\u00e0o c\u00f4ng vi\u1ec7c? B\u00e0i vi\u1ebft Spring MVC tutorial sau kh\u00f4ng ch\u1ec9 l\u00e0 m\u1ed9t b\u00e0i h\u01b0\u1edbng d\u1eabn th\u00f4ng th\u01b0\u1eddng m\u00e0 n\u00f3 l\u00e0 m\u1ed9t h\u00e0nh tr\u00ecnh th\u1ef1c chi\u1ebfn, n\u01a1i b\u1ea1n s\u1ebd h\u1ecdc c\u00e1ch t\u01b0 duy nh\u01b0 m\u1ed9t nh\u00e0 ph\u00e1t tri\u1ec3n th\u1ef1c th\u1ee5, x\u00e2y d\u1ef1ng m\u1ed9t \u1ee9ng d\u1ee5ng web t\u1eeb con s\u1ed1 0 v\u00e0 trang b\u1ecb nh\u1eefng k\u1ef9 n\u0103ng s\u1eb5n s\u00e0ng cho c\u00e1c d\u1ef1 \u00e1n trong t\u01b0\u01a1ng lai.\u00a0<\/em><\/strong><\/p>\n\n\n\n<p>\u0110\u1ecdc b\u00e0i vi\u1ebft Spring MVC tutorial n\u00e0y \u0111\u1ec3 hi\u1ec3u th\u00eam v\u1ec1:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Nh\u1eefng ki\u1ebfn th\u1ee9c t\u1ed5ng quan v\u1ec1 Spring MVC<\/li>\n\n\n\n<li>C\u00e1ch x\u00e2y d\u1ef1ng \u1ee9ng d\u1ee5ng v\u1edbi Spring MVC<\/li>\n\n\n\n<li>C\u00e1c h\u01b0\u1edbng n\u00e2ng c\u1ea5p \u1ee9ng d\u1ee5ng Spring MVC l\u00ean &#8220;t\u1ea7m cao m\u1edbi&#8221;<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-ki\u1ebfn-th\u1ee9c-t\u1ed5ng-quan-v\u1ec1-spring-mvc\"><span class=\"ez-toc-section\" id=\"Kien_thuc_tong_quan_ve_Spring_MVC\"><\/span><strong>Ki\u1ebfn th\u1ee9c t\u1ed5ng quan v\u1ec1 Spring MVC<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>\u0110\u1ec3 x\u00e2y d\u1ef1ng th\u00e0nh c\u00f4ng m\u1ed9t \u1ee9ng d\u1ee5ng web v\u1edbi Spring MVC, vi\u1ec7c \u0111\u1ea7u ti\u00ean l\u00e0 n\u1eafm v\u1eefng c\u00e1c kh\u00e1i ni\u1ec7m n\u1ec1n t\u1ea3ng:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-mo-hinh-mvc-model-view-controller\"><strong>M\u00f4 h\u00ecnh MVC (Model &#8211; View &#8211; Controller)<\/strong><\/h3>\n\n\n\n<p>V\u1ec1 c\u1ed1t l\u00f5i, Spring MVC tu\u00e2n th\u1ee7 nghi\u00eam ng\u1eb7t m\u00f4 h\u00ecnh ki\u1ebfn tr\u00fac <strong>Model &#8211; View &#8211; Controller<\/strong>, gi\u00fap t\u1ed5 ch\u1ee9c code m\u1ed9t c\u00e1ch r\u00f5 r\u00e0ng v\u00e0 hi\u1ec7u qu\u1ea3:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Model:<\/strong> L\u00e0 n\u01a1i ch\u1ee9a d\u1eef li\u1ec7u c\u1ee7a \u1ee9ng d\u1ee5ng. \u0110\u00e2y th\u01b0\u1eddng l\u00e0 c\u00e1c \u0111\u1ed1i t\u01b0\u1ee3ng Java \u0111\u01a1n gi\u1ea3n (POJO) \u0111\u1ea1i di\u1ec7n cho c\u00e1c th\u1ef1c th\u1ec3 nh\u01b0 User, Product, hay Order.<\/li>\n\n\n\n<li><strong>View:<\/strong> Ch\u1ecbu tr\u00e1ch nhi\u1ec7m hi\u1ec3n th\u1ecb d\u1eef li\u1ec7u cho ng\u01b0\u1eddi d\u00f9ng. Trong c\u00e1c d\u1ef1 \u00e1n hi\u1ec7n \u0111\u1ea1i, View th\u01b0\u1eddng l\u00e0 c\u00e1c file template nh\u01b0 Thymeleaf ho\u1eb7c JSP.<\/li>\n\n\n\n<li><strong>Controller:<\/strong> \u0110\u00f3ng vai tr\u00f2 l\u00e0 &#8220;b\u1ed9 n\u00e3o&#8221; trung t\u00e2m, ti\u1ebfp nh\u1eadn c\u00e1c y\u00eau c\u1ea7u t\u1eeb ng\u01b0\u1eddi d\u00f9ng, t\u01b0\u01a1ng t\u00e1c v\u1edbi Model \u0111\u1ec3 x\u1eed l\u00fd logic v\u00e0 cu\u1ed1i c\u00f9ng quy\u1ebft \u0111\u1ecbnh View n\u00e0o s\u1ebd \u0111\u01b0\u1ee3c tr\u1ea3 v\u1ec1.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-lu\u1ed3ng-ho\u1ea1t-d\u1ed9ng-c\u1ee7a-m\u1ed9t-yeu-c\u1ea7u-trong-spring-mvc-request-flow\"><strong>Lu\u1ed3ng ho\u1ea1t \u0111\u1ed9ng c\u1ee7a m\u1ed9t y\u00eau c\u1ea7u trong Spring MVC (Request Flow)<\/strong><\/h3>\n\n\n\n<p>Lu\u1ed3ng ho\u1ea1t \u0111\u1ed9ng c\u1ee7a m\u1ed9t y\u00eau c\u1ea7u trong Spring MVC di\u1ec5n ra m\u1ed9t c\u00e1ch tu\u1ea7n t\u1ef1 v\u00e0 c\u00f3 t\u1ed5 ch\u1ee9c. M\u1ecdi th\u1ee9 b\u1eaft \u0111\u1ea7u khi client g\u1eedi y\u00eau c\u1ea7u, y\u00eau c\u1ea7u n\u00e0y s\u1ebd \u0111\u01b0\u1ee3c <strong>DispatcherServlet<\/strong> (b\u1ed9 \u0111i\u1ec1u ph\u1ed1i trung t\u00e2m) ti\u1ebfp nh\u1eadn. DispatcherServlet sau \u0111\u00f3 s\u1ebd t\u00ecm \u0111\u1ebfn <strong>Controller<\/strong> t\u01b0\u01a1ng \u1ee9ng \u0111\u1ec3 x\u1eed l\u00fd. Controller l\u00e0m vi\u1ec7c v\u1edbi d\u1eef li\u1ec7u (Model), sau \u0111\u00f3 tr\u1ea3 k\u1ebft qu\u1ea3 v\u1ec1 l\u1ea1i cho DispatcherServlet, v\u00e0 cu\u1ed1i c\u00f9ng View s\u1ebd \u0111\u01b0\u1ee3c render \u0111\u1ec3 g\u1eedi ph\u1ea3n h\u1ed3i (Response) v\u1ec1 cho client.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-cac-annotation-chu-thich-quan-tr\u1ecdng-nh\u1ea5t\"><strong>C\u00e1c Annotation (ch\u00fa th\u00edch) quan tr\u1ecdng nh\u1ea5t:<\/strong><\/h3>\n\n\n\n<p>\u0110\u1ec3 bi\u1ebfn lu\u1ed3ng ho\u1ea1t \u0111\u1ed9ng tr\u00ean th\u00e0nh code, Spring cung c\u1ea5p c\u00e1c <strong>Annotation (ch\u00fa th\u00edch)<\/strong> c\u1ef1c k\u1ef3 m\u1ea1nh m\u1ebd v\u00e0 ti\u1ec7n l\u1ee3i. \u0110\u00e2y l\u00e0 nh\u1eefng c\u00f4ng c\u1ee5 kh\u00f4ng th\u1ec3 thi\u1ebfu:<\/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.<\/li>\n\n\n\n<li><strong><code>@RequestMapping<\/code><\/strong>, <strong><code>@GetMapping<\/code><\/strong>, <strong><code>@PostMapping<\/code><\/strong>: D\u00f9ng \u0111\u1ec3 \u00e1nh x\u1ea1 (map) m\u1ed9t URL c\u1ee5 th\u1ec3 v\u1edbi m\u1ed9t ph\u01b0\u01a1ng th\u1ee9c x\u1eed l\u00fd trong Controller.<\/li>\n\n\n\n<li><strong><code>@RequestParam<\/code><\/strong>: Gi\u00fap b\u1ea1n d\u1ec5 d\u00e0ng l\u1ea5y c\u00e1c tham s\u1ed1 t\u1eeb URL (v\u00ed d\u1ee5: <code>?name=John<\/code>).<\/li>\n\n\n\n<li><strong><code>@ModelAttribute<\/code><\/strong>: D\u00f9ng \u0111\u1ec3 li\u00ean k\u1ebft d\u1eef li\u1ec7u \u0111\u01b0\u1ee3c g\u1eedi l\u00ean t\u1eeb m\u1ed9t form HTML v\u1edbi m\u1ed9t \u0111\u1ed1i t\u01b0\u1ee3ng Model c\u1ee7a b\u1ea1n.<\/li>\n<\/ul>\n\n\n\n<p>Nh\u1eefng kh\u00e1i ni\u1ec7m tr\u00ean ch\u00ednh l\u00e0 nh\u1eefng vi\u00ean g\u1ea1ch \u0111\u1ea7u ti\u00ean v\u00e0 quan tr\u1ecdng nh\u1ea5t \u0111\u1ec3 b\u1ea1n x\u00e2y d\u1ef1ng n\u00ean m\u1ed9t \u1ee9ng d\u1ee5ng web ho\u00e0n ch\u1ec9nh. \u0110\u1ec3 t\u00ecm hi\u1ec3u s\u00e2u h\u01a1n v\u1ec1 c\u00e1ch c\u00e1c th\u00e0nh ph\u1ea7n n\u00e0y k\u1ebft h\u1ee3p v\u1edbi nhau v\u00e0 xem h\u01b0\u1edbng d\u1eabn chi ti\u1ebft t\u1eebng b\u01b0\u1edbc trong m\u1ed9t d\u1ef1 \u00e1n th\u1ef1c t\u1ebf, m\u1eddi b\u1ea1n \u0111\u1ecdc ti\u1ebfp ph\u1ea7n h\u01b0\u1edbng d\u1eabn th\u1ef1c h\u00e0nh d\u01b0\u1edbi \u0111\u00e2y.<\/p>\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: <a href=\"https:\/\/itviec.com\/blog\/spring-mvc-la-gi\/\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>Spring MVC l\u00e0 g\u00ec: H\u01b0\u1edbng d\u1eabn x\u00e2y d\u1ef1ng \u1ee9ng d\u1ee5ng v\u1edbi Spring MVC<\/strong><\/a><\/em><\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-spring-mvc-tutorial-th\u1ef1c-hanh-xay-d\u1ef1ng-\u1ee9ng-d\u1ee5ng-v\u1edbi-spring-mvc\"><span class=\"ez-toc-section\" id=\"Spring_MVC_tutorial_Thuc_hanh_xay_dung_ung_dung_voi_Spring_MVC\"><\/span><strong>Spring MVC tutorial: Th\u1ef1c h\u00e0nh x\u00e2y d\u1ef1ng \u1ee9ng d\u1ee5ng v\u1edbi Spring MVC<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Trong ph\u1ea7n n\u00e0y, ch\u00fang ta s\u1ebd t\u1ea1o ra m\u1ed9t \u1ee9ng d\u1ee5ng qu\u1ea3n l\u00fd c\u00f4ng vi\u1ec7c (To-Do List) \u0111\u01a1n gi\u1ea3n. Qua Spring MVC tutorial sau \u0111\u00e2y, b\u1ea1n s\u1ebd h\u1ecdc \u0111\u01b0\u1ee3c c\u00e1ch hi\u1ec3n th\u1ecb d\u1eef li\u1ec7u, x\u1eed l\u00fd ng\u01b0\u1eddi d\u00f9ng nh\u1eadp li\u1ec7u qua form v\u00e0 c\u1eadp nh\u1eadt giao di\u1ec7n m\u1ed9t c\u00e1ch linh ho\u1ea1t. C\u1ee5 th\u1ec3:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Hi\u1ec3u v\u00e0 \u00e1p d\u1ee5ng m\u00f4 h\u00ecnh MVC:<\/strong> Ph\u00e2n t\u00e1ch r\u00f5 r\u00e0ng lu\u1ed3ng d\u1eef li\u1ec7u (Model), giao di\u1ec7n (View), v\u00e0 logic x\u1eed l\u00fd (Controller).<\/li>\n\n\n\n<li><strong>T\u1ea1o Controller \u0111\u1ec3 x\u1eed l\u00fd request:<\/strong> S\u1eed d\u1ee5ng c\u00e1c annotation <code>@Controller<\/code>, <code>@GetMapping<\/code>, v\u00e0 <code>@PostMapping<\/code> \u0111\u1ec3 \u0111i\u1ec1u h\u01b0\u1edbng c\u00e1c y\u00eau c\u1ea7u c\u1ee7a ng\u01b0\u1eddi d\u00f9ng.<\/li>\n\n\n\n<li><strong>X\u00e2y d\u1ef1ng giao di\u1ec7n \u0111\u1ed9ng v\u1edbi Thymeleaf:<\/strong> Truy\u1ec1n d\u1eef li\u1ec7u t\u1eeb Controller ra View (Model.addAttribute) v\u00e0 hi\u1ec3n th\u1ecb ch\u00fang m\u1ed9t c\u00e1ch linh ho\u1ea1t (<code>th:text<\/code>, <code>th:each<\/code>).<\/li>\n\n\n\n<li><strong>X\u1eed l\u00fd Form m\u1ed9t c\u00e1ch chuy\u00ean nghi\u1ec7p:<\/strong> N\u1eafm b\u1eaft d\u1eef li\u1ec7u ng\u01b0\u1eddi d\u00f9ng nh\u1eadp v\u00e0o b\u1eb1ng <code>@ModelAttribute<\/code> v\u00e0 th\u1ef1c hi\u1ec7n k\u1ef9 thu\u1eadt <strong>Post-Redirect-Get (PRG)<\/strong> \u0111\u1ec3 t\u1ea1o ra tr\u1ea3i nghi\u1ec7m ng\u01b0\u1eddi d\u00f9ng t\u1ed1t h\u01a1n v\u00e0 tr\u00e1nh l\u1ed7i.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-ph\u1ea7n-1-t\u1ea1o-trang-ch\u1ee7-hello-world\"><strong>Ph\u1ea7n 1: T\u1ea1o trang ch\u1ee7 &#8220;Hello, World!&#8221;<\/strong><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-b\u01b0\u1edbc-1-t\u1ea1o-controller-d\u1ea7u-tien-homecontroller-java\"><strong>B\u01b0\u1edbc 1: T\u1ea1o Controller \u0111\u1ea7u ti\u00ean (<\/strong><strong>HomeController.java<\/strong><strong>)<\/strong><\/h4>\n\n\n\n<p><strong>M\u1ee5c \u0111\u00edch:<\/strong> T\u1ea1o ra m\u1ed9t &#8220;b\u1ed9 n\u00e3o&#8221; c\u00f3 kh\u1ea3 n\u0103ng l\u1eafng nghe v\u00e0 ph\u1ea3n h\u1ed3i l\u1ea1i c\u00e1c y\u00eau c\u1ea7u t\u1eeb ng\u01b0\u1eddi d\u00f9ng khi h\u1ecd truy c\u1eadp v\u00e0o trang ch\u1ee7 c\u1ee7a \u1ee9ng d\u1ee5ng. \u0110\u00e2y l\u00e0 th\u00e0nh ph\u1ea7n Controller trong m\u00f4 h\u00ecnh MVC.<\/p>\n\n\n\n<p><strong>C\u00e1ch l\u00e0m:<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>T\u1ea1o m\u1ed9t class Java m\u1edbi t\u00ean l\u00e0 <code>HomeController<\/code>.<\/li>\n\n\n\n<li>S\u1eed d\u1ee5ng annotation <code>@Controller<\/code> \u0111\u1ec3 b\u00e1o cho Spring bi\u1ebft r\u1eb1ng \u0111\u00e2y l\u00e0 m\u1ed9t bean \u0111\u1eb7c bi\u1ec7t, ch\u1ecbu tr\u00e1ch nhi\u1ec7m x\u1eed l\u00fd c\u00e1c request web.<\/li>\n\n\n\n<li>B\u00ean trong class, t\u1ea1o m\u1ed9t ph\u01b0\u01a1ng th\u1ee9c <code>showHomePage()<\/code>. Ph\u01b0\u01a1ng th\u1ee9c n\u00e0y s\u1ebd \u0111\u01b0\u1ee3c g\u1ecdi khi c\u00f3 ng\u01b0\u1eddi truy c\u1eadp v\u00e0o trang ch\u1ee7.<\/li>\n\n\n\n<li>S\u1eed d\u1ee5ng annotation <code>@GetMapping(\"\/\")<\/code> \u0111\u1ec3 \u00e1nh x\u1ea1 (map) ph\u01b0\u01a1ng th\u1ee9c n\u00e0y v\u1edbi URL g\u1ed1c (\/) c\u1ee7a trang web th\u00f4ng qua ph\u01b0\u01a1ng th\u1ee9c <code>GET<\/code>.<\/li>\n\n\n\n<li>Ph\u01b0\u01a1ng th\u1ee9c s\u1ebd tr\u1ea3 v\u1ec1 m\u1ed9t String. String n\u00e0y ch\u00ednh l\u00e0 t\u00ean logic c\u1ee7a View m\u00e0 ch\u00fang ta mu\u1ed1n hi\u1ec3n th\u1ecb.<\/li>\n<\/ol>\n\n\n\n<p><strong>V\u00ed d\u1ee5 code (<\/strong><strong>HomeController.java<\/strong><strong>):<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.example.todomvc.controller;\n\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.GetMapping;\n\n@Controller\npublic class HomeController {\n\n\u00a0\u00a0\u00a0\u00a0@GetMapping(\"\/\")\n\u00a0\u00a0\u00a0\u00a0public String showHomePage() {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ Tr\u1ea3 v\u1ec1 t\u00ean c\u1ee7a file view (kh\u00f4ng bao g\u1ed3m \u0111u\u00f4i .html)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return \"home\";\n\u00a0\u00a0\u00a0\u00a0}\n}<\/code><\/pre>\n\n\n\n<p><strong>Output:&nbsp;<\/strong><\/p>\n\n\n\n<p>B\u1ea3n th\u00e2n \u0111o\u1ea1n code n\u00e0y khi ch\u1ea1y s\u1ebd kh\u00f4ng t\u1ea1o ra b\u1ea5t k\u1ef3 giao di\u1ec7n c\u00f3 th\u1ec3 nh\u00ecn th\u1ea5y n\u00e0o. &#8220;Output&#8221; c\u1ee7a n\u00f3 l\u00e0 m\u1ed9t t\u00edn hi\u1ec7u n\u1ed9i b\u1ed9 b\u00ean trong Spring MVC. Khi ph\u01b0\u01a1ng th\u1ee9c <code>showHomePage()<\/code> \u0111\u01b0\u1ee3c th\u1ef1c thi, n\u00f3 tr\u1ea3 v\u1ec1 chu\u1ed7i &#8220;home&#8221;. \u0110\u00e2y l\u00e0 t\u00ean logic c\u1ee7a View.<\/p>\n\n\n\n<p><strong>Gi\u1ea3i th\u00edch:&nbsp;<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Khi ng\u01b0\u1eddi d\u00f9ng truy c\u1eadp http:\/\/localhost:8080\/, DispatcherServlet c\u1ee7a Spring s\u1ebd t\u00ecm ki\u1ebfm xem c\u00f3 ph\u01b0\u01a1ng th\u1ee9c n\u00e0o \u0111\u01b0\u1ee3c \u0111\u0103ng k\u00fd \u0111\u1ec3 x\u1eed l\u00fd URL \/ v\u1edbi ph\u01b0\u01a1ng th\u1ee9c GET hay kh\u00f4ng.&nbsp;<\/li>\n\n\n\n<li>Nh\u1edd <code>@GetMapping(\"\/\")<\/code>, n\u00f3 s\u1ebd t\u00ecm th\u1ea5y ph\u01b0\u01a1ng th\u1ee9c <code>showHomePage()<\/code>. Ph\u01b0\u01a1ng th\u1ee9c n\u00e0y th\u1ef1c thi v\u00e0 tr\u1ea3 v\u1ec1 chu\u1ed7i &#8220;home&#8221;. Spring MVC s\u1ebd hi\u1ec3u r\u1eb1ng n\u00f3 c\u1ea7n ph\u1ea3i t\u00ecm m\u1ed9t template t\u00ean l\u00e0 home \u0111\u1ec3 hi\u1ec3n th\u1ecb cho ng\u01b0\u1eddi d\u00f9ng.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\"><\/ul>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-b\u01b0\u1edbc-2-hi\u1ec3n-th\u1ecb-danh-sach-cong-vi\u1ec7c-va-form-them-m\u1edbi\"><strong>B\u01b0\u1edbc 2: Hi\u1ec3n th\u1ecb danh s\u00e1ch c\u00f4ng vi\u1ec7c v\u00e0 Form th\u00eam m\u1edbi<\/strong><\/h4>\n\n\n\n<p><strong>M\u1ee5c \u0111\u00edch:<\/strong> T\u1ea1o ra giao di\u1ec7n ng\u01b0\u1eddi d\u00f9ng (file HTML) m\u00e0 ng\u01b0\u1eddi d\u00f9ng s\u1ebd nh\u00ecn th\u1ea5y. \u0110\u00e2y l\u00e0 th\u00e0nh ph\u1ea7n View trong m\u00f4 h\u00ecnh MVC.<\/p>\n\n\n\n<p><strong>C\u00e1ch l\u00e0m:<\/strong> Spring Boot v\u1edbi Thymeleaf \u0111\u01b0\u1ee3c c\u1ea5u h\u00ecnh m\u1eb7c \u0111\u1ecbnh \u0111\u1ec3 t\u00ecm c\u00e1c file template trong th\u01b0 m\u1ee5c <code>src\/main\/resources\/templates<\/code>.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Trong project c\u1ee7a b\u1ea1n, \u0111i\u1ec1u h\u01b0\u1edbng \u0111\u1ebfn th\u01b0 m\u1ee5c <code>src\/main\/resources<\/code>.<\/li>\n\n\n\n<li>T\u1ea1o m\u1ed9t file HTML m\u1edbi v\u00e0 \u0111\u1eb7t t\u00ean l\u00e0 home.html (tr\u00f9ng v\u1edbi t\u00ean logic m\u00e0 Controller \u0111\u00e3 tr\u1ea3 v\u1ec1).<\/li>\n\n\n\n<li>Th\u00eam m\u1ed9t v\u00e0i th\u1ebb HTML c\u01a1 b\u1ea3n v\u00e0o file n\u00e0y.<\/li>\n<\/ul>\n\n\n\n<p><strong>V\u00ed d\u1ee5 code (<\/strong><strong>home.html<\/strong><strong>):<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!DOCTYPE html>\n&lt;html lang=\"en\">\n&lt;head>\n    &lt;meta charset=\"UTF-8\">\n    &lt;title>\u1ee8ng d\u1ee5ng To-Do&lt;\/title>\n&lt;\/head>\n&lt;body>\n    &lt;h1>Ch\u00e0o m\u1eebng \u0111\u1ebfn v\u1edbi \u1ee9ng d\u1ee5ng qu\u1ea3n l\u00fd c\u00f4ng vi\u1ec7c!&lt;\/h1>\n&lt;\/body>\n&lt;\/html><\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"292\" src=\"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-16.png\" alt=\"\" class=\"wp-image-89286\" srcset=\"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-16.png 800w, https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-16-300x109.png 300w, https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-16-640x233.png 640w, https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-16-200x73.png 200w, https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-16-768x280.png 768w, https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-16-1536x560.png 1536w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/figure>\n\n\n\n<p><strong>Gi\u1ea3i th\u00edch:<\/strong> Khi Controller tr\u1ea3 v\u1ec1 t\u00ean view l\u00e0 &#8220;home&#8221;, ViewResolver c\u1ee7a Spring s\u1ebd t\u1ef1 \u0111\u1ed9ng t\u00ecm ki\u1ebfm file home.html trong th\u01b0 m\u1ee5c templates. Sau \u0111\u00f3, n\u00f3 s\u1ebd render file HTML n\u00e0y v\u00e0 g\u1eedi v\u1ec1 cho tr\u00ecnh duy\u1ec7t c\u1ee7a ng\u01b0\u1eddi d\u00f9ng.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-b\u01b0\u1edbc-3-truy\u1ec1n-d\u1eef-li\u1ec7u-t\u1eeb-controller-sang-view\"><strong>B\u01b0\u1edbc 3: Truy\u1ec1n d\u1eef li\u1ec7u t\u1eeb Controller sang View<\/strong><\/h4>\n\n\n\n<p><strong>M\u1ee5c \u0111\u00edch:<\/strong> L\u00e0m cho trang web tr\u1edf n\u00ean \u0111\u1ed9ng b\u1eb1ng c\u00e1ch g\u1eedi d\u1eef li\u1ec7u t\u1eeb backend v\u00e0 hi\u1ec3n th\u1ecb n\u00f3 tr\u00ean giao di\u1ec7n. \u0110\u00e2y l\u00e0 b\u01b0\u1edbc k\u1ebft n\u1ed1i Controller v\u1edbi View th\u00f4ng qua Model.<\/p>\n\n\n\n<p><strong>C\u00e1ch l\u00e0m:<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>S\u1eeda l\u1ea1i ph\u01b0\u01a1ng th\u1ee9c <code>showHomePage()<\/code> trong HomeController. Th\u00eam m\u1ed9t tham s\u1ed1 c\u00f3 ki\u1ec3u Model v\u00e0o ph\u01b0\u01a1ng th\u1ee9c. Spring s\u1ebd t\u1ef1 \u0111\u1ed9ng cung c\u1ea5p m\u1ed9t \u0111\u1ed1i t\u01b0\u1ee3ng Model cho ch\u00fang ta.<\/li>\n\n\n\n<li>S\u1eed d\u1ee5ng ph\u01b0\u01a1ng th\u1ee9c <code>model.addAttribute(\"key\", \"value\")<\/code> \u0111\u1ec3 th\u00eam m\u1ed9t thu\u1ed9c t\u00ednh v\u00e0o model. &#8220;key&#8221; l\u00e0 t\u00ean \u0111\u1ec3 ch\u00fang ta g\u1ecdi \u1edf View, &#8220;value&#8221; l\u00e0 gi\u00e1 tr\u1ecb ch\u00fang ta mu\u1ed1n truy\u1ec1n \u0111i.<\/li>\n\n\n\n<li>M\u1edf file home.html v\u00e0 s\u1eed d\u1ee5ng c\u00fa ph\u00e1p c\u1ee7a Thymeleaf \u0111\u1ec3 truy c\u1eadp v\u00e0 hi\u1ec3n th\u1ecb gi\u00e1 tr\u1ecb \u0111\u00e3 \u0111\u01b0\u1ee3c truy\u1ec1n qua.<\/li>\n<\/ol>\n\n\n\n<p><strong>Code:\u00a0HomeController.java<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.example.todomvc.controller;\n\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model; \/\/ Th\u00eam import\nimport org.springframework.web.bind.annotation.GetMapping;\n\n@Controller\npublic class HomeController {\n\n    @GetMapping(\"\/\")\n    public String showHomePage(Model model) { \/\/ Th\u00eam tham s\u1ed1 Model\n        \/\/ Th\u00eam m\u1ed9t thu\u1ed9c t\u00ednh v\u00e0o model \u0111\u1ec3 g\u1eedi sang View\n        model.addAttribute(\"welcomeMessage\", \"\u0110\u00e2y l\u00e0 th\u00f4ng \u0111i\u1ec7p t\u1eeb Controller!\");\n        return \"home\";\n    }\n}<\/code><\/pre>\n\n\n\n<p><strong>Home.html<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!DOCTYPE html>\n&lt;html lang=\"en\" xmlns:th=\"http:\/\/www.thymeleaf.org\">\n&lt;head>\n    &lt;meta charset=\"UTF-8\">\n    &lt;title>\u1ee8ng d\u1ee5ng To-Do&lt;\/title>\n&lt;\/head>\n&lt;body>\n    &lt;h1>Ch\u00e0o m\u1eebng \u0111\u1ebfn v\u1edbi \u1ee9ng d\u1ee5ng qu\u1ea3n l\u00fd c\u00f4ng vi\u1ec7c!&lt;\/h1>\n    &lt;p th:text=\"${welcomeMessage}\">&lt;\/p>\n&lt;\/body>\n&lt;\/html><\/code><\/pre>\n\n\n\n<p><strong>Output v\u00e0 gi\u1ea3i th\u00edch:<\/strong>&nbsp;<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Khi b\u1ea1n ch\u1ea1y l\u1ea1i \u1ee9ng d\u1ee5ng, trang ch\u1ee7 b\u00e2y gi\u1edd s\u1ebd hi\u1ec3n th\u1ecb th\u00eam d\u00f2ng ch\u1eef: &#8220;\u0110\u00e2y l\u00e0 th\u00f4ng \u0111i\u1ec7p t\u1eeb Controller!&#8221;.&nbsp;<\/li>\n\n\n\n<li>Thymeleaf nh\u00ecn th\u1ea5y <code>th:text=\"${welcomeMessage}\"<\/code> v\u00e0 hi\u1ec3u r\u1eb1ng n\u00f3 c\u1ea7n t\u00ecm m\u1ed9t thu\u1ed9c t\u00ednh t\u00ean l\u00e0 <code>welcomeMessage<\/code> trong \u0111\u1ed1i t\u01b0\u1ee3ng Model m\u00e0 Controller \u0111\u00e3 g\u1eedi. N\u00f3 s\u1ebd l\u1ea5y gi\u00e1 tr\u1ecb c\u1ee7a thu\u1ed9c t\u00ednh \u0111\u00f3 v\u00e0 \u0111\u1eb7t v\u00e0o b\u00ean trong th\u1ebb <code>&lt;p><\/code>.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-b\u01b0\u1edbc-4-ch\u1ea1y-\u1ee9ng-d\u1ee5ng-va-xem-k\u1ebft-qu\u1ea3\"><strong>B\u01b0\u1edbc 4: Ch\u1ea1y \u1ee9ng d\u1ee5ng v\u00e0 xem k\u1ebft qu\u1ea3<\/strong><\/h4>\n\n\n\n<p><strong>M\u1ee5c \u0111\u00edch:<\/strong> Ki\u1ec3m tra th\u00e0nh qu\u1ea3 c\u1ee7a c\u00e1c b\u01b0\u1edbc tr\u00ean v\u00e0 \u0111\u1ea3m b\u1ea3o \u1ee9ng d\u1ee5ng ch\u1ea1y \u0111\u00fang nh\u01b0 mong \u0111\u1ee3i.<\/p>\n\n\n\n<p><strong>C\u00e1ch l\u00e0m:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Trong IDE c\u1ee7a b\u1ea1n (IntelliJ, Eclipse, VSCode), t\u00ecm \u0111\u1ebfn class ch\u00ednh c\u1ee7a \u1ee9ng d\u1ee5ng (class c\u00f3 annotation <code>@SpringBootApplication<\/code>).<\/li>\n\n\n\n<li>Nh\u1ea5n chu\u1ed9t ph\u1ea3i v\u00e0o class \u0111\u00f3 v\u00e0 ch\u1ecdn &#8220;Run&#8221; ho\u1eb7c &#8220;Debug&#8221;.<\/li>\n\n\n\n<li>IDE s\u1ebd build v\u00e0 kh\u1edfi ch\u1ea1y server Tomcat nh\u00fang. Ch\u1edd \u0111\u1ebfn khi console log b\u00e1o &#8220;Tomcat started on port(s): 8080&#8221;.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"793\" src=\"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-14.png\" alt=\"\" class=\"wp-image-89279\" srcset=\"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-14.png 800w, https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-14-300x297.png 300w, https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-14-640x634.png 640w, https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-14-200x198.png 200w, https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-14-768x761.png 768w, https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-14-1536x1523.png 1536w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/figure>\n\n\n\n<p><strong>Output v\u00e0 gi\u1ea3i th\u00edch:<\/strong> M\u1edf tr\u00ecnh duy\u1ec7t web (Chrome, Firefox,&#8230;) v\u00e0 truy c\u1eadp v\u00e0o \u0111\u1ecba ch\u1ec9: http:\/\/localhost:8080. B\u1ea1n s\u1ebd th\u1ea5y trang web c\u1ee7a m\u00ecnh hi\u1ec7n ra v\u1edbi \u0111\u1ea7y \u0111\u1ee7 ti\u00eau \u0111\u1ec1 v\u00e0 d\u00f2ng th\u00f4ng \u0111i\u1ec7p \u0111\u01b0\u1ee3c truy\u1ec1n t\u1eeb Controller.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-ph\u1ea7n-2-x\u1eed-ly-form-them-cong-vi\u1ec7c-m\u1edbi\"><span class=\"ez-toc-section\" id=\"Phan_2_Xu_ly_Form_%E2%80%93_Them_cong_viec_moi\"><\/span><strong>Ph\u1ea7n 2: X\u1eed l\u00fd Form &#8211; Th\u00eam c\u00f4ng vi\u1ec7c m\u1edbi<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>B\u00e2y gi\u1edd, ch\u00fang ta s\u1ebd n\u00e2ng c\u1ea5p \u1ee9ng d\u1ee5ng \u0111\u1ec3 c\u00f3 th\u1ec3 th\u00eam c\u00e1c c\u00f4ng vi\u1ec7c m\u1edbi v\u00e0o danh s\u00e1ch th\u00f4ng qua m\u1ed9t form HTML.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-b\u01b0\u1edbc-1-t\u1ea1o-model-object-todo-java\"><strong>B\u01b0\u1edbc 1: T\u1ea1o Model Object (<\/strong><strong>Todo.java<\/strong><strong>)<\/strong><\/h4>\n\n\n\n<p><strong>M\u1ee5c \u0111\u00edch:<\/strong> \u0110\u1ecbnh ngh\u0129a c\u1ea5u tr\u00fac d\u1eef li\u1ec7u cho m\u1ed9t &#8220;c\u00f4ng vi\u1ec7c&#8221; (Todo). Thay v\u00ec d\u00f9ng c\u00e1c chu\u1ed7i (String) r\u1eddi r\u1ea1c, ch\u00fang ta t\u1ea1o m\u1ed9t \u0111\u1ed1i t\u01b0\u1ee3ng c\u1ee5 th\u1ec3 \u0111\u1ec3 \u0111\u00f3ng g\u00f3i th\u00f4ng tin. \u0110\u00e2y l\u00e0 th\u00e0nh ph\u1ea7n Model th\u1ef1c s\u1ef1 trong m\u00f4 h\u00ecnh MVC.<\/p>\n\n\n\n<p><strong>C\u00e1ch l\u00e0m:<\/strong> T\u1ea1o m\u1ed9t class Java POJO (Plain Old Java Object) v\u1edbi c\u00e1c tr\u01b0\u1eddng d\u1eef li\u1ec7u c\u1ea7n thi\u1ebft, c\u00f9ng v\u1edbi constructor, getter v\u00e0 setter.<\/p>\n\n\n\n<p><strong>V\u00ed d\u1ee5 code (<\/strong><strong>Todo.java<\/strong><strong>):<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.example.todomvc.model;\n\npublic class Todo {\n    private long id;\n    private String title;\n    private boolean completed;\n\n    \/\/ Constructors\n    public Todo() {}\n\n    public Todo(long id, String title, boolean completed) {\n        this.id = id;\n        this.title = title;\n        this.completed = completed;\n    }\n\n    \/\/ Getters and Setters\n    public long getId() { return id; }\n    public void setId(long id) { this.id = id; }\n    public String getTitle() { return title; }\n    public void setTitle(String title) { this.title = title; }\n    public boolean isCompleted() { return completed; }\n    public void setCompleted(boolean completed) { this.completed = completed; }\n}<\/code><\/pre>\n\n\n\n<p><strong>Gi\u1ea3i th\u00edch:<\/strong> Class Todo n\u00e0y l\u00e0 m\u1ed9t b\u1ea3n thi\u1ebft k\u1ebf cho d\u1eef li\u1ec7u c\u00f4ng vi\u1ec7c. M\u1ed7i \u0111\u1ed1i t\u01b0\u1ee3ng Todo s\u1ebd \u0111\u1ea1i di\u1ec7n cho m\u1ed9t c\u00f4ng vi\u1ec7c trong danh s\u00e1ch c\u1ee7a ch\u00fang ta. Spring s\u1ebd s\u1eed d\u1ee5ng class n\u00e0y \u0111\u1ec3 t\u1ef1 \u0111\u1ed9ng t\u1ea1o \u0111\u1ed1i t\u01b0\u1ee3ng t\u1eeb d\u1eef li\u1ec7u c\u1ee7a form.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-b\u01b0\u1edbc-2-hi\u1ec3n-th\u1ecb-danh-sach-cong-vi\u1ec7c-va-form-them-m\u1edbi-0\"><strong>B\u01b0\u1edbc 2: Hi\u1ec3n th\u1ecb danh s\u00e1ch c\u00f4ng vi\u1ec7c v\u00e0 Form th\u00eam m\u1edbi<\/strong><\/h4>\n\n\n\n<p><strong>M\u1ee5c \u0111\u00edch:<\/strong> C\u1eadp nh\u1eadt Controller \u0111\u1ec3 qu\u1ea3n l\u00fd m\u1ed9t danh s\u00e1ch c\u00f4ng vi\u1ec7c v\u00e0 truy\u1ec1n danh s\u00e1ch \u0111\u00f3 ra View. \u0110\u1ed3ng th\u1eddi, c\u1eadp nh\u1eadt View \u0111\u1ec3 hi\u1ec3n th\u1ecb danh s\u00e1ch n\u00e0y v\u00e0 m\u1ed9t form cho ph\u00e9p ng\u01b0\u1eddi d\u00f9ng nh\u1eadp c\u00f4ng vi\u1ec7c m\u1edbi.<\/p>\n\n\n\n<p><strong>C\u00e1ch l\u00e0m:<\/strong><\/p>\n\n\n\n<p><strong>Trong <\/strong><strong>HomeController<\/strong><strong>:<\/strong> T\u1ea1o m\u1ed9t List&lt;Todo&gt; \u0111\u1ec3 l\u01b0u tr\u1eef c\u00e1c c\u00f4ng vi\u1ec7c (ch\u00fang ta s\u1ebd d\u00f9ng m\u1ed9t danh s\u00e1ch trong b\u1ed9 nh\u1edb \u0111\u1ec3 \u0111\u01a1n gi\u1ea3n h\u00f3a, thay v\u00ec d\u00f9ng database). Truy\u1ec1n danh s\u00e1ch n\u00e0y v\u00e0 m\u1ed9t \u0111\u1ed1i t\u01b0\u1ee3ng Todo r\u1ed7ng (d\u00f9ng cho form) v\u00e0o model.<\/p>\n\n\n\n<p><strong>Trong <\/strong><strong>home.html<\/strong><strong>:<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>S\u1eed d\u1ee5ng v\u00f2ng l\u1eb7p th:each c\u1ee7a Thymeleaf \u0111\u1ec3 duy\u1ec7t qua danh s\u00e1ch c\u00f4ng vi\u1ec7c v\u00e0 hi\u1ec3n th\u1ecb ch\u00fang.<\/li>\n\n\n\n<li>T\u1ea1o m\u1ed9t th\u1ebb &lt;form> v\u1edbi c\u00e1c thu\u1ed9c t\u00ednh c\u1ee7a Thymeleaf (<code>th:action<\/code>, <code>th:object<\/code>) \u0111\u1ec3 li\u00ean k\u1ebft form v\u1edbi \u0111\u1ed1i t\u01b0\u1ee3ng v\u00e0 action trong Controller.<\/li>\n\n\n\n<li>S\u1eed d\u1ee5ng <code>th:field<\/code> cho th\u1ebb <code>&lt;input><\/code> \u0111\u1ec3 li\u00ean k\u1ebft n\u00f3 v\u1edbi m\u1ed9t thu\u1ed9c t\u00ednh c\u1ee5 th\u1ec3 c\u1ee7a \u0111\u1ed1i t\u01b0\u1ee3ng.<\/li>\n<\/ol>\n\n\n\n<p><strong>V\u00ed d\u1ee5 code:<\/strong> <strong>HomeController.java:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.example.todomvc.controller;\n\nimport com.example.todomvc.model.Todo; \/\/ Th\u00eam import\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.GetMapping;\n\nimport java.util.ArrayList; \/\/ Th\u00eam import\nimport java.util.List;      \/\/ Th\u00eam import\n\n@Controller\npublic class HomeController {\n\n    \/\/ D\u00f9ng m\u1ed9t danh s\u00e1ch \u0111\u01a1n gi\u1ea3n trong b\u1ed9 nh\u1edb \u0111\u1ec3 l\u00e0m CSDL gi\u1ea3\n    private final List&lt;Todo> todoList = new ArrayList&lt;>();\n\n    public HomeController() {\n        \/\/ Th\u00eam m\u1ed9t v\u00e0i d\u1eef li\u1ec7u m\u1eabu\n        todoList.add(new Todo(1, \"H\u1ecdc Spring MVC\", true));\n        todoList.add(new Todo(2, \"X\u00e2y d\u1ef1ng \u1ee9ng d\u1ee5ng To-Do\", false));\n    }\n\n    @GetMapping(\"\/\")\n    public String showHomePage(Model model) {\n        \/\/ Truy\u1ec1n danh s\u00e1ch c\u00f4ng vi\u1ec7c v\u00e0 m\u1ed9t \u0111\u1ed1i t\u01b0\u1ee3ng r\u1ed7ng cho form\n        model.addAttribute(\"todos\", todoList);\n        model.addAttribute(\"newTodo\", new Todo()); \/\/ \u0110\u1ed1i t\u01b0\u1ee3ng \u0111\u1ec3 binding v\u1edbi form\n        return \"home\";\n    }\n}<\/code><\/pre>\n\n\n\n<p><strong>Home.html<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!DOCTYPE html>\n&lt;html lang=\"en\" xmlns:th=\"http:\/\/www.thymeleaf.org\">\n&lt;head>\n    &lt;meta charset=\"UTF-8\">\n    &lt;title>\u1ee8ng d\u1ee5ng To-Do&lt;\/title>\n&lt;\/head>\n&lt;body>\n    &lt;h1>Danh s\u00e1ch c\u00f4ng vi\u1ec7c&lt;\/h1>\n\n    &lt;ul>\n        &lt;li th:each=\"todo : ${todos}\" th:text=\"${todo.title}\">\n            N\u1ed9i dung c\u00f4ng vi\u1ec7c\n        &lt;\/li>\n    &lt;\/ul>\n\n    &lt;hr\/>\n\n    &lt;h2>Th\u00eam c\u00f4ng vi\u1ec7c m\u1edbi&lt;\/h2>\n    &lt;form action=\"#\" th:action=\"@{\/add-todo}\" th:object=\"${newTodo}\" method=\"post\">\n        &lt;input type=\"text\" th:field=\"*{title}\" placeholder=\"Nh\u1eadp ti\u00eau \u0111\u1ec1 c\u00f4ng vi\u1ec7c\"\/>\n        &lt;button type=\"submit\">Th\u00eam&lt;\/button>\n    &lt;\/form>\n\n&lt;\/body>\n&lt;\/html><\/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>th:each=\"todo : ${todos}\"<\/code>: Thymeleaf s\u1ebd l\u1eb7p qua t\u1eebng \u0111\u1ed1i t\u01b0\u1ee3ng todo trong danh s\u00e1ch todos \u0111\u01b0\u1ee3c truy\u1ec1n t\u1eeb Controller. V\u1edbi m\u1ed7i todo, n\u00f3 s\u1ebd t\u1ea1o ra m\u1ed9t th\u1ebb <code>&lt;li><\/code>.<\/li>\n\n\n\n<li><code>th:text=\"${todo.title}\"<\/code>: Hi\u1ec3n th\u1ecb gi\u00e1 tr\u1ecb c\u1ee7a thu\u1ed9c t\u00ednh title c\u1ee7a \u0111\u1ed1i t\u01b0\u1ee3ng todo hi\u1ec7n t\u1ea1i.<\/li>\n\n\n\n<li><code>th:action=\"@{\/add-todo}\"<\/code>: Ch\u1ec9 \u0111\u1ecbnh r\u1eb1ng khi form \u0111\u01b0\u1ee3c submit, n\u00f3 s\u1ebd g\u1eedi y\u00eau c\u1ea7u POST \u0111\u1ebfn URL \/add-todo.<\/li>\n\n\n\n<li><code>th:object=\"${newTodo}\"<\/code>: Li\u00ean k\u1ebft (binding) to\u00e0n b\u1ed9 form n\u00e0y v\u1edbi \u0111\u1ed1i t\u01b0\u1ee3ng newTodo trong model.<\/li>\n\n\n\n<li><code>th:field=\"*{title}\"<\/code>: Li\u00ean k\u1ebft th\u1ebb <code>&lt;input><\/code> n\u00e0y v\u1edbi thu\u1ed9c t\u00ednh title c\u1ee7a \u0111\u1ed1i t\u01b0\u1ee3ng \u0111ang \u0111\u01b0\u1ee3c li\u00ean k\u1ebft (newTodo). D\u1ea5u <code>*<\/code> l\u00e0 c\u00fa ph\u00e1p t\u1eaft cho newTodo.title.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"190\" src=\"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-15.png\" alt=\"\" class=\"wp-image-89280\" srcset=\"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-15.png 800w, https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-15-300x71.png 300w, https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-15-640x152.png 640w, https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-15-200x48.png 200w, https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-15-768x182.png 768w, https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/image-15-1536x365.png 1536w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-b\u01b0\u1edbc-3-x\u1eed-ly-vi\u1ec7c-g\u1eedi-form-submit\"><strong>B\u01b0\u1edbc 3: X\u1eed l\u00fd vi\u1ec7c g\u1eedi Form (Submit)<\/strong><\/h4>\n\n\n\n<p><strong>M\u1ee5c \u0111\u00edch:<\/strong> T\u1ea1o m\u1ed9t ph\u01b0\u01a1ng th\u1ee9c trong Controller \u0111\u1ec3 nh\u1eadn d\u1eef li\u1ec7u khi ng\u01b0\u1eddi d\u00f9ng nh\u1ea5n n\u00fat &#8220;Th\u00eam&#8221; tr\u00ean form, x\u1eed l\u00fd d\u1eef li\u1ec7u \u0111\u00f3 (th\u00eam v\u00e0o danh s\u00e1ch) v\u00e0 c\u1eadp nh\u1eadt l\u1ea1i giao di\u1ec7n.<\/p>\n\n\n\n<p><strong>C\u00e1ch l\u00e0m:<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>T\u1ea1o m\u1ed9t ph\u01b0\u01a1ng th\u1ee9c m\u1edbi trong HomeController.<\/li>\n\n\n\n<li>S\u1eed d\u1ee5ng <code>@PostMapping(\"\/add-todo\")<\/code> \u0111\u1ec3 \u00e1nh x\u1ea1 ph\u01b0\u01a1ng th\u1ee9c n\u00e0y v\u1edbi action c\u1ee7a form.<\/li>\n\n\n\n<li>S\u1eed d\u1ee5ng <code>@ModelAttribute<\/code> tr\u00ean tham s\u1ed1 c\u1ee7a ph\u01b0\u01a1ng th\u1ee9c. Spring s\u1ebd t\u1ef1 \u0111\u1ed9ng l\u1ea5y d\u1eef li\u1ec7u t\u1eeb form v\u00e0 t\u1ea1o ra m\u1ed9t \u0111\u1ed1i t\u01b0\u1ee3ng Todo cho ch\u00fang ta.<\/li>\n\n\n\n<li>Th\u00eam \u0111\u1ed1i t\u01b0\u1ee3ng Todo m\u1edbi v\u00e0o todoList.<\/li>\n\n\n\n<li>Tr\u1ea3 v\u1ec1 <code>redirect:\/<\/code>. \u0110\u00e2y l\u00e0 m\u1ed9t k\u1ef9 thu\u1eadt quan tr\u1ecdng, y\u00eau c\u1ea7u tr\u00ecnh duy\u1ec7t th\u1ef1c hi\u1ec7n m\u1ed9t request GET m\u1edbi \u0111\u1ebfn trang ch\u1ee7, gi\u00fap t\u1ea3i l\u1ea1i danh s\u00e1ch \u0111\u00e3 \u0111\u01b0\u1ee3c c\u1eadp nh\u1eadt v\u00e0 tr\u00e1nh l\u1ed7i g\u1eedi l\u1ea1i form khi ng\u01b0\u1eddi d\u00f9ng nh\u1ea5n F5.<\/li>\n<\/ol>\n\n\n\n<p>V\u00ed d\u1ee5 code (HomeController.java &#8211; th\u00eam ph\u01b0\u01a1ng th\u1ee9c m\u1edbi):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ ... (b\u00ean trong class HomeController)\n\nimport org.springframework.web.bind.annotation.ModelAttribute; \/\/ Th\u00eam import\nimport org.springframework.web.bind.annotation.PostMapping;    \/\/ Th\u00eam import\n\n\/\/ ... (ph\u01b0\u01a1ng th\u1ee9c showHomePage v\u00e0 constructor v\u1eabn gi\u1eef nguy\u00ean)\n\n@PostMapping(\"\/add-todo\")\npublic String addTodo(@ModelAttribute Todo newTodo) {\n    \/\/ G\u00e1n ID t\u1ea1m th\u1eddi (trong \u1ee9ng d\u1ee5ng th\u1ef1c t\u1ebf s\u1ebd do CSDL qu\u1ea3n l\u00fd)\n    newTodo.setId(System.currentTimeMillis());\n    newTodo.setCompleted(false);\n\n    \/\/ Th\u00eam c\u00f4ng vi\u1ec7c m\u1edbi v\u00e0o danh s\u00e1ch\n    this.todoList.add(newTodo);\n\n    \/\/ Chuy\u1ec3n h\u01b0\u1edbng v\u1ec1 trang ch\u1ee7 \u0111\u1ec3 hi\u1ec3n th\u1ecb danh s\u00e1ch \u0111\u00e3 c\u1eadp nh\u1eadt\n    return \"redirect:\/\";\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>@PostMapping(\"\/add-todo\")<\/code>: Ch\u1ec9 l\u1eafng nghe c\u00e1c request d\u00f9ng ph\u01b0\u01a1ng th\u1ee9c <code>POST<\/code> \u0111\u1ebfn URL \/add-todo.<\/li>\n\n\n\n<li><code>@ModelAttribute Todo newTodo<\/code>: \u0110\u00e2y l\u00e0 &#8220;ph\u00e9p m\u00e0u&#8221; c\u1ee7a Spring. N\u00f3 nh\u00ecn v\u00e0o c\u00e1c name c\u1ee7a input trong form, so kh\u1edbp ch\u00fang v\u1edbi c\u00e1c thu\u1ed9c t\u00ednh c\u1ee7a class <code>Todo<\/code>, v\u00e0 t\u1ef1 \u0111\u1ed9ng t\u1ea1o m\u1ed9t \u0111\u1ed1i t\u01b0\u1ee3ng <code>newTodo<\/code> v\u1edbi c\u00e1c gi\u00e1 tr\u1ecb t\u01b0\u01a1ng \u1ee9ng.<\/li>\n\n\n\n<li><code>return \"redirect:\/\"<\/code>: Thay v\u00ec tr\u1ea3 v\u1ec1 m\u1ed9t t\u00ean view, ch\u00fang ta tr\u1ea3 v\u1ec1 m\u1ed9t l\u1ec7nh chuy\u1ec3n h\u01b0\u1edbng. Tr\u00ecnh duy\u1ec7t s\u1ebd nh\u1eadn l\u1ec7nh n\u00e0y v\u00e0 t\u1ef1 \u0111\u1ed9ng g\u1eedi m\u1ed9t request m\u1edbi \u0111\u1ebfn \/. Request n\u00e0y s\u1ebd \u0111\u01b0\u1ee3c <code>showHomePage()<\/code> x\u1eed l\u00fd, l\u1ea5y ra danh s\u00e1ch todoList (l\u00fac n\u00e0y \u0111\u00e3 c\u00f3 ph\u1ea7n t\u1eed m\u1edbi) v\u00e0 hi\u1ec3n th\u1ecb l\u1ea1i trang ch\u1ee7.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-b\u01b0\u1edbc-4-ki\u1ec3m-tra-l\u1ea1i\"><strong>B\u01b0\u1edbc 4: Ki\u1ec3m tra l\u1ea1i<\/strong><\/h4>\n\n\n\n<p><strong>M\u1ee5c \u0111\u00edch:<\/strong> Ch\u1ea1y l\u1ea1i \u1ee9ng d\u1ee5ng v\u00e0 ki\u1ec3m tra to\u00e0n b\u1ed9 lu\u1ed3ng ch\u1ee9c n\u0103ng th\u00eam m\u1edbi c\u00f3 ho\u1ea1t \u0111\u1ed9ng \u0111\u00fang kh\u00f4ng.<\/p>\n\n\n\n<p><strong>C\u00e1ch l\u00e0m:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ch\u1ea1y l\u1ea1i \u1ee9ng d\u1ee5ng c\u1ee7a b\u1ea1n t\u1eeb IDE.<\/li>\n\n\n\n<li>M\u1edf tr\u00ecnh duy\u1ec7t t\u1ea1i http:\/\/localhost:8080.<\/li>\n<\/ul>\n\n\n\n<p><strong>Output v\u00e0 gi\u1ea3i th\u00edch:<\/strong>&nbsp;<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>B\u1ea1n s\u1ebd th\u1ea5y trang ch\u1ee7 v\u1edbi danh s\u00e1ch 2 c\u00f4ng vi\u1ec7c m\u1eabu. H\u00e3y th\u1eed nh\u1eadp m\u1ed9t ti\u00eau \u0111\u1ec1 c\u00f4ng vi\u1ec7c m\u1edbi v\u00e0o \u00f4 input (v\u00ed d\u1ee5: &#8220;Ho\u00e0n th\u00e0nh b\u00e0i h\u01b0\u1edbng d\u1eabn&#8221;) v\u00e0 nh\u1ea5n n\u00fat &#8220;Th\u00eam&#8221;.&nbsp;<\/li>\n\n\n\n<li>Ngay l\u1eadp t\u1ee9c, trang s\u1ebd \u0111\u01b0\u1ee3c t\u1ea3i l\u1ea1i, v\u00e0 c\u00f4ng vi\u1ec7c b\u1ea1n v\u1eeba th\u00eam s\u1ebd xu\u1ea5t hi\u1ec7n \u1edf cu\u1ed1i danh s\u00e1ch.&nbsp;<\/li>\n\n\n\n<li>\u0110i\u1ec1u n\u00e0y x\u00e1c nh\u1eadn r\u1eb1ng to\u00e0n b\u1ed9 lu\u1ed3ng: Hi\u1ec3n th\u1ecb Form -&gt; Ng\u01b0\u1eddi d\u00f9ng nh\u1eadp li\u1ec7u -&gt; Submit -&gt; Controller x\u1eed l\u00fd -&gt; Th\u00eam v\u00e0o danh s\u00e1ch -&gt; Redirect -&gt; Hi\u1ec3n th\u1ecb l\u1ea1i danh s\u00e1ch m\u1edbi \u0111\u00e3 th\u00e0nh c\u00f4ng!<\/li>\n<\/ul>\n\n\n\n<p>\u1ee8ng d\u1ee5ng To-Do List v\u1eeba l\u00e0m ch\u1ec9 l\u00e0 b\u01b0\u1edbc kh\u1edfi \u0111\u1ea7u. Trong m\u1ed9t d\u1ef1 \u00e1n th\u1ef1c t\u1ebf, n\u00f3 c\u1ea7n \u0111\u01b0\u1ee3c ho\u00e0n thi\u1ec7n h\u01a1n. Gi\u1edd l\u00e0 l\u00fac kh\u00e1m ph\u00e1 xem ch\u00fang ta c\u00f3 th\u1ec3 n\u00e2ng c\u1ea5p \u1ee9ng d\u1ee5ng n\u00e0y l\u00ean nh\u1eefng t\u1ea7m cao m\u1edbi n\u00e0o.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-h\u01b0\u1edbng-nang-c\u1ea5p-\u1ee9ng-d\u1ee5ng\"><span class=\"ez-toc-section\" id=\"Huong_%E2%80%9Cnang_cap%E2%80%9D_ung_dung\"><\/span><strong>H\u01b0\u1edbng<\/strong> &#8220;n\u00e2ng c\u1ea5p&#8221; \u1ee9ng d\u1ee5ng<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>D\u01b0\u1edbi \u0111\u00e2y l\u00e0 nh\u1eefng b\u01b0\u1edbc ph\u00e1t tri\u1ec3n quan tr\u1ecdng m\u00e0 b\u1ea1n n\u00ean t\u00ecm hi\u1ec3u ti\u1ebfp theo:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-validation-ki\u1ec3m-tra-d\u1eef-li\u1ec7u-d\u1ea7u-vao\"><strong>Validation &#8211; Ki\u1ec3m tra d\u1eef li\u1ec7u \u0111\u1ea7u v\u00e0o<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>V\u1ea5n \u0111\u1ec1:<\/strong> Hi\u1ec7n t\u1ea1i, ng\u01b0\u1eddi d\u00f9ng c\u00f3 th\u1ec3 submit m\u1ed9t form v\u1edbi ti\u00eau \u0111\u1ec1 c\u00f4ng vi\u1ec7c tr\u1ed1ng r\u1ed7ng. \u0110i\u1ec1u n\u00e0y s\u1ebd t\u1ea1o ra d\u1eef li\u1ec7u kh\u00f4ng mong mu\u1ed1n trong h\u1ec7 th\u1ed1ng.<\/li>\n\n\n\n<li><strong>Gi\u1ea3i ph\u00e1p:<\/strong> S\u1eed d\u1ee5ng <strong>Spring Boot Validation<\/strong>. B\u1eb1ng c\u00e1ch th\u00eam c\u00e1c annotation nh\u01b0 <code>@NotEmpty<\/code> hay <code>@Size<\/code> v\u00e0o c\u00e1c tr\u01b0\u1eddng c\u1ee7a Model class (<code>Todo.java<\/code>) v\u00e0 d\u00f9ng <code>@Valid<\/code> trong Controller, b\u1ea1n c\u00f3 th\u1ec3 t\u1ef1 \u0111\u1ed9ng ki\u1ec3m tra d\u1eef li\u1ec7u tr\u01b0\u1edbc khi x\u1eed l\u00fd. N\u1ebfu d\u1eef li\u1ec7u kh\u00f4ng h\u1ee3p l\u1ec7, b\u1ea1n c\u00f3 th\u1ec3 hi\u1ec3n th\u1ecb th\u00f4ng b\u00e1o l\u1ed7i th\u00e2n thi\u1ec7n cho ng\u01b0\u1eddi d\u00f9ng ngay tr\u00ean form.<\/li>\n<\/ul>\n\n\n\n<p><strong>T\u1eeb kh\u00f3a \u0111\u1ec3 t\u00ecm hi\u1ec3u:<\/strong> Spring Boot Validation, Hibernate Validator, @Valid, @NotEmpty, BindingResult.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-k\u1ebft-n\u1ed1i-c\u01a1-s\u1edf-d\u1eef-li\u1ec7u-v\u1edbi-spring-data-jpa\"><strong>K\u1ebft n\u1ed1i C\u01a1 s\u1edf d\u1eef li\u1ec7u v\u1edbi Spring Data JPA<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>V\u1ea5n \u0111\u1ec1:<\/strong> Danh s\u00e1ch c\u00f4ng vi\u1ec7c c\u1ee7a ch\u00fang ta \u0111ang \u0111\u01b0\u1ee3c l\u01b0u trong m\u1ed9t ArrayList trong b\u1ed9 nh\u1edb. M\u1ed7i khi b\u1ea1n kh\u1edfi \u0111\u1ed9ng l\u1ea1i \u1ee9ng d\u1ee5ng, to\u00e0n b\u1ed9 d\u1eef li\u1ec7u s\u1ebd b\u1ecb m\u1ea5t.<\/li>\n\n\n\n<li><strong>Gi\u1ea3i ph\u00e1p:<\/strong> S\u1eed d\u1ee5ng <strong>Spring Data JPA<\/strong> v\u00e0 <strong>Hibernate<\/strong> \u0111\u1ec3 k\u1ebft n\u1ed1i \u1ee9ng d\u1ee5ng v\u1edbi m\u1ed9t c\u01a1 s\u1edf d\u1eef li\u1ec7u th\u1ef1c s\u1ef1 (nh\u01b0 H2, MySQL, PostgreSQL). \u0110i\u1ec1u n\u00e0y gi\u00fap d\u1eef li\u1ec7u \u0111\u01b0\u1ee3c l\u01b0u tr\u1eef l\u00e2u d\u00e0i. Spring Data JPA cung c\u1ea5p c\u00e1c interface nh\u01b0 JpaRepository gi\u00fap b\u1ea1n th\u1ef1c hi\u1ec7n c\u00e1c thao t\u00e1c CRUD (Create, Read, Update, Delete) v\u1edbi CSDL m\u00e0 kh\u00f4ng c\u1ea7n vi\u1ebft c\u00e1c <a href=\"https:\/\/itviec.com\/blog\/tong-hop-cau-lenh-sql\/\" target=\"_blank\" rel=\"noreferrer noopener\">c\u00e2u l\u1ec7nh SQL<\/a> ph\u1ee9c t\u1ea1p.<\/li>\n<\/ul>\n\n\n\n<p><strong>T\u1eeb kh\u00f3a \u0111\u1ec3 t\u00ecm hi\u1ec3u:<\/strong> Spring Data JPA, @Entity, JpaRepository, Hibernate, JDBC DataSource configuration.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-xay-d\u1ef1ng-rest-api\"><strong>X\u00e2y d\u1ef1ng REST API<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>V\u1ea5n \u0111\u1ec1:<\/strong> \u1ee8ng d\u1ee5ng c\u1ee7a ch\u00fang ta hi\u1ec7n t\u1ea1i ch\u1ec9 ph\u1ee5c v\u1ee5 giao di\u1ec7n web (server-rendered HTML). N\u1ebfu b\u1ea1n mu\u1ed1n m\u1ed9t \u1ee9ng d\u1ee5ng di \u0111\u1ed9ng (mobile app) ho\u1eb7c m\u1ed9t trang web d\u00f9ng JavaScript (React, Angular) c\u00f3 th\u1ec3 t\u01b0\u01a1ng t\u00e1c v\u1edbi d\u1eef li\u1ec7u c\u00f4ng vi\u1ec7c th\u00ec sao?<\/li>\n\n\n\n<li><strong>Gi\u1ea3i ph\u00e1p:<\/strong> X\u00e2y d\u1ef1ng c\u00e1c <strong>REST API<\/strong>. Thay v\u00ec tr\u1ea3 v\u1ec1 t\u00ean c\u1ee7a m\u1ed9t View, Controller s\u1ebd tr\u1ea3 v\u1ec1 d\u1eef li\u1ec7u d\u01b0\u1edbi d\u1ea1ng JSON. B\u1ea1n s\u1ebd s\u1eed d\u1ee5ng annotation <code>@RestController<\/code> thay cho <code>@Controller<\/code> \u0111\u1ec3 Spring t\u1ef1 \u0111\u1ed9ng chuy\u1ec3n \u0111\u1ed5i c\u00e1c \u0111\u1ed1i t\u01b0\u1ee3ng Java th\u00e0nh JSON.<\/li>\n<\/ul>\n\n\n\n<p><strong>T\u1eeb kh\u00f3a \u0111\u1ec3 t\u00ecm hi\u1ec3u:<\/strong> @RestController, @ResponseBody, ResponseEntity, JSON, Spring Boot REST API.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-b\u1ea3o-m\u1eadt-v\u1edbi-spring-security\"><strong>B\u1ea3o m\u1eadt v\u1edbi Spring Security<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>V\u1ea5n \u0111\u1ec1:<\/strong> B\u1ea5t k\u1ef3 ai c\u0169ng c\u00f3 th\u1ec3 truy c\u1eadp v\u00e0 th\u00eam c\u00f4ng vi\u1ec7c v\u00e0o danh s\u00e1ch. Trong th\u1ef1c t\u1ebf, b\u1ea1n s\u1ebd mu\u1ed1n m\u1ed7i ng\u01b0\u1eddi d\u00f9ng ch\u1ec9 c\u00f3 th\u1ec3 xem v\u00e0 qu\u1ea3n l\u00fd danh s\u00e1ch c\u00f4ng vi\u1ec7c c\u1ee7a ri\u00eang m\u00ecnh.<\/li>\n\n\n\n<li><strong>Gi\u1ea3i ph\u00e1p:<\/strong> T\u00edch h\u1ee3p <strong>Spring Security<\/strong> v\u00e0o d\u1ef1 \u00e1n. \u0110\u00e2y l\u00e0 m\u1ed9t framework c\u1ef1c k\u1ef3 m\u1ea1nh m\u1ebd cho ph\u00e9p b\u1ea1n th\u00eam c\u00e1c t\u00ednh n\u0103ng nh\u01b0 \u0111\u0103ng nh\u1eadp, \u0111\u0103ng k\u00fd, ph\u00e2n quy\u1ec1n ng\u01b0\u1eddi d\u00f9ng. B\u1ea1n c\u00f3 th\u1ec3 c\u1ea5u h\u00ecnh \u0111\u1ec3 ch\u1ec9 nh\u1eefng ng\u01b0\u1eddi d\u00f9ng \u0111\u00e3 \u0111\u0103ng nh\u1eadp (authenticated) m\u1edbi c\u00f3 th\u1ec3 truy c\u1eadp c\u00e1c trang nh\u1ea5t \u0111\u1ecbnh, v\u00e0 ch\u1ec9 nh\u1eefng ng\u01b0\u1eddi c\u00f3 quy\u1ec1n (authorized) m\u1edbi \u0111\u01b0\u1ee3c th\u1ef1c hi\u1ec7n m\u1ed9t s\u1ed1 h\u00e0nh \u0111\u1ed9ng.<\/li>\n<\/ul>\n\n\n\n<p><strong>T\u1eeb kh\u00f3a \u0111\u1ec3 t\u00ecm hi\u1ec3u:<\/strong> <a href=\"https:\/\/spring.io\/projects\/spring-security\" target=\"_blank\" rel=\"noreferrer noopener\">Spring Security<\/a>, <a href=\"https:\/\/docs.spring.io\/spring-security\/reference\/features\/authentication\/index.html\" target=\"_blank\" rel=\"noreferrer noopener\">Authentication<\/a>, <a href=\"https:\/\/docs.spring.io\/spring-security\/reference\/servlet\/authorization\/index.html\" target=\"_blank\" rel=\"noreferrer noopener\">Authorization<\/a>, <a href=\"https:\/\/docs.spring.io\/spring-security\/reference\/servlet\/architecture.html\" target=\"_blank\" rel=\"noreferrer noopener\">SecurityFilterChain<\/a>, <a href=\"http:\/\/docs.spring.io\/spring-security\/reference\/servlet\/authentication\/passwords\/password-encoder.html\" target=\"_blank\" rel=\"noreferrer noopener\">PasswordEncoder<\/a>.<\/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-tutorial\"><span class=\"ez-toc-section\" id=\"Cac_cau_hoi_thuong_gap_ve_Spring_MVC_tutorial\"><\/span><strong>C\u00e1c c\u00e2u h\u1ecfi th\u01b0\u1eddng g\u1eb7p v\u1ec1 Spring MVC tutorial<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-s\u1ef1-khac-bi\u1ec7t-gi\u1eefa-th\u01b0-m\u1ee5c-templates-va-static-la-gi\"><strong>S\u1ef1 kh\u00e1c bi\u1ec7t gi\u1eefa th\u01b0 m\u1ee5c <\/strong><strong>templates<\/strong><strong> v\u00e0 <\/strong><strong>static<\/strong><strong> l\u00e0 g\u00ec?<\/strong><\/h3>\n\n\n\n<p>C\u1ea3 hai \u0111\u1ec1u n\u1eb1m trong <code>src\/main\/resources<\/code>, nh\u01b0ng c\u00f3 m\u1ee5c \u0111\u00edch ho\u00e0n to\u00e0n kh\u00e1c nhau:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>src\/main\/resources\/templates<\/code>: D\u00e0nh cho c\u00e1c file <strong>\u0111\u1ed9ng<\/strong>. C\u00e1c file trong n\u00e0y (nh\u01b0 home.html c\u1ee7a ch\u00fang ta) s\u1ebd \u0111\u01b0\u1ee3c m\u1ed9t template engine (Thymeleaf) x\u1eed l\u00fd \u1edf ph\u00eda server tr\u01b0\u1edbc khi g\u1eedi v\u1ec1 cho tr\u00ecnh duy\u1ec7t. Server c\u00f3 th\u1ec3 ch\u00e8n d\u1eef li\u1ec7u v\u00e0o c\u00e1c file n\u00e0y.<\/li>\n\n\n\n<li><code>src\/main\/resources\/static<\/code>: D\u00e0nh cho c\u00e1c t\u00e0i nguy\u00ean <strong>t\u0129nh<\/strong>. C\u00e1c file trong n\u00e0y nh\u01b0 CSS, JavaScript, h\u00ecnh \u1ea3nh, fonts&#8230; s\u1ebd \u0111\u01b0\u1ee3c server g\u1eedi tr\u1ef1c ti\u1ebfp v\u1ec1 cho tr\u00ecnh duy\u1ec7t m\u00e0 kh\u00f4ng qua b\u1ea5t k\u1ef3 x\u1eed l\u00fd n\u00e0o. V\u00ed d\u1ee5, n\u1ebfu b\u1ea1n t\u1ea1o file style.css trong n\u00e0y, b\u1ea1n c\u00f3 th\u1ec3 link n\u00f3 trong HTML b\u1eb1ng th\u1ebb <code>&lt;link rel=\"stylesheet\" href=\"\/style.css\"><\/code>.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-s\u1ef1-khac-bi\u1ec7t-gi\u1eefa-controller-va-restcontroller-la-gi\"><strong>S\u1ef1 kh\u00e1c bi\u1ec7t gi\u1eefa <\/strong><strong>@Controller<\/strong><strong> v\u00e0 <\/strong><strong>@RestController<\/strong><strong> l\u00e0 g\u00ec?<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>@Controller<\/code><\/strong>: \u0110\u01b0\u1ee3c s\u1eed d\u1ee5ng \u0111\u1ec3 t\u1ea1o c\u00e1c web controller truy\u1ec1n th\u1ed1ng trong Spring MVC. C\u00e1c ph\u01b0\u01a1ng th\u1ee9c trong <code>@Controller<\/code> th\u01b0\u1eddng tr\u1ea3 v\u1ec1 m\u1ed9t String l\u00e0 t\u00ean c\u1ee7a m\u1ed9t <strong>View<\/strong> (template) \u0111\u1ec3 hi\u1ec3n th\u1ecb giao di\u1ec7n ng\u01b0\u1eddi d\u00f9ng (HTML).<\/li>\n\n\n\n<li><strong><code>@RestController<\/code><\/strong>: L\u00e0 m\u1ed9t annotation k\u1ebft h\u1ee3p gi\u1eefa <code>@Controller<\/code> v\u00e0 <code>@ResponseBody<\/code>. N\u00f3 \u0111\u01b0\u1ee3c s\u1eed d\u1ee5ng chuy\u00ean \u0111\u1ec3 x\u00e2y d\u1ef1ng <strong>RESTful API<\/strong>. C\u00e1c ph\u01b0\u01a1ng th\u1ee9c trong <code>@RestController<\/code> th\u01b0\u1eddng tr\u1ea3 v\u1ec1 tr\u1ef1c ti\u1ebfp d\u1eef li\u1ec7u (v\u00ed d\u1ee5: \u0111\u1ed1i t\u01b0\u1ee3ng Java), v\u00e0 Spring s\u1ebd t\u1ef1 \u0111\u1ed9ng chuy\u1ec3n \u0111\u1ed5i n\u00f3 th\u00e0nh \u0111\u1ecbnh d\u1ea1ng <a href=\"https:\/\/itviec.com\/blog\/json-la-gi\/\" target=\"_blank\" rel=\"noreferrer noopener\">JSON<\/a> \u0111\u1ec3 c\u00e1c \u1ee9ng d\u1ee5ng kh\u00e1c (nh\u01b0 mobile app, trang web React\/Angular) c\u00f3 th\u1ec3 s\u1eed d\u1ee5ng.<\/li>\n<\/ul>\n\n\n\n<p>Trong b\u00e0i h\u01b0\u1edbng d\u1eabn n\u00e0y, ch\u00fang ta x\u00e2y d\u1ef1ng \u1ee9ng d\u1ee5ng web tr\u1ea3 v\u1ec1 HTML n\u00ean \u0111\u00e3 d\u00f9ng <code>@Controller<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-modelattribute-ho\u1ea1t-d\u1ed9ng-nh\u01b0-th\u1ebf-nao-ma-co-th\u1ec3-t\u1ef1-t\u1ea1o-d\u1ed1i-t\u01b0\u1ee3ng-todo\"><strong>@ModelAttribute<\/strong><strong> ho\u1ea1t \u0111\u1ed9ng nh\u01b0 th\u1ebf n\u00e0o m\u00e0 c\u00f3 th\u1ec3 t\u1ef1 t\u1ea1o \u0111\u1ed1i t\u01b0\u1ee3ng <\/strong><strong>Todo<\/strong><strong>?<\/strong><\/h3>\n\n\n\n<p><code>@ModelAttribute<\/code> l\u00e0 m\u1ed9t annotation c\u1ef1c k\u1ef3 m\u1ea1nh m\u1ebd gi\u00fap \u0111\u01a1n gi\u1ea3n h\u00f3a vi\u1ec7c li\u00ean k\u1ebft d\u1eef li\u1ec7u (data binding). Khi m\u1ed9t form \u0111\u01b0\u1ee3c submit, c\u00e1c d\u1eef li\u1ec7u c\u1ee7a n\u00f3 \u0111\u01b0\u1ee3c g\u1eedi \u0111i d\u01b0\u1edbi d\u1ea1ng c\u00e1c c\u1eb7p key-value (v\u00ed d\u1ee5: title=Mua s\u1eefa).<\/p>\n\n\n\n<p><code>@ModelAttribute<\/code> s\u1ebd:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>T\u1ea1o m\u1ed9t instance m\u1edbi c\u1ee7a \u0111\u1ed1i t\u01b0\u1ee3ng \u0111\u01b0\u1ee3c ch\u1ec9 \u0111\u1ecbnh (v\u00ed d\u1ee5: <code>new Todo()<\/code>).<\/li>\n\n\n\n<li>Nh\u00ecn v\u00e0o c\u00e1c key trong d\u1eef li\u1ec7u request (title).<\/li>\n\n\n\n<li>T\u00ecm ph\u01b0\u01a1ng th\u1ee9c setter t\u01b0\u01a1ng \u1ee9ng trong \u0111\u1ed1i t\u01b0\u1ee3ng (<code>setTitle(...)<\/code>).<\/li>\n\n\n\n<li>G\u1ecdi ph\u01b0\u01a1ng th\u1ee9c setter \u0111\u00f3 v\u1edbi value t\u01b0\u01a1ng \u1ee9ng (<code>\"Mua s\u1eefa\"<\/code>).<\/li>\n<\/ol>\n\n\n\n<p>N\u00f3 gi\u00fap ch\u00fang ta kh\u00f4ng ph\u1ea3i l\u00e0m c\u00e1c c\u00f4ng vi\u1ec7c th\u1ee7 c\u00f4ng v\u00e0 nh\u00e0m ch\u00e1n nh\u01b0:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>String title = request.getParameter(\"title\"); todo.setTitle(title);<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-t\u1ed5ng-k\u1ebft-spring-mvc-tutorial\"><span class=\"ez-toc-section\" id=\"Tong_ket_Spring_MVC_tutorial\"><\/span><strong>T\u1ed5ng k\u1ebft Spring MVC tutorial<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>V\u1edbi Spring MVC tutorial tr\u00ean, b\u1ea1n kh\u00f4ng ch\u1ec9 bi\u1ebfn nh\u1eefng kh\u00e1i ni\u1ec7m l\u00fd thuy\u1ebft th\u00e0nh m\u1ed9t s\u1ea3n ph\u1ea9m ch\u1ea1y \u0111\u01b0\u1ee3c, m\u00e0 c\u00f2n n\u1eafm \u0111\u01b0\u1ee3c nh\u1eefng nguy\u00ean t\u1eafc ho\u1ea1t \u0111\u1ed9ng c\u1ed1t l\u00f5i nh\u1ea5t c\u1ee7a Spring MVC. \u0110\u00e2y l\u00e0 m\u1ed9t n\u1ec1n t\u1ea3ng c\u1ef1c k\u1ef3 v\u1eefng ch\u1eafc \u0111\u1ec3 b\u1ea1n ti\u1ebfp t\u1ee5c chinh ph\u1ee5c nh\u1eefng c\u00f4ng ngh\u1ec7 ph\u1ee9c t\u1ea1p h\u01a1n trong h\u1ec7 sinh th\u00e1i Spring.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Khi nh\u1eafc \u0111\u1ebfn h\u1ec7 sinh th\u00e1i Java, Spring MVC lu\u00f4n l\u00e0 l\u1ef1a ch\u1ecdn h\u00e0ng \u0111\u1ea7u. Nh\u01b0ng l\u00e0m th\u1ebf n\u00e0o \u0111\u1ec3 \u00e1p d\u1ee5ng n\u00f3 m\u1ed9t c\u00e1ch hi\u1ec7u qu\u1ea3 v\u00e0o c\u00f4ng vi\u1ec7c? B\u00e0i vi\u1ebft Spring MVC tutorial sau kh\u00f4ng ch\u1ec9 l\u00e0 m\u1ed9t b\u00e0i h\u01b0\u1edbng d\u1eabn th\u00f4ng th\u01b0\u1eddng m\u00e0 n\u00f3 l\u00e0 m\u1ed9t h\u00e0nh tr\u00ecnh th\u1ef1c chi\u1ebfn, n\u01a1i b\u1ea1n [&hellip;]<\/p>\n","protected":false},"author":203,"featured_media":89287,"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-89206","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 tutorial: H\u01b0\u1edbng d\u1eabn x\u00e2y \u1ee9ng d\u1ee5ng web v\u1edbi Spring MVC - ITviec Blog<\/title>\n<meta name=\"description\" content=\"H\u01b0\u1edbng d\u1eabn Spring MVC tutorial th\u1ef1c chi\u1ebfn chi ti\u1ebft, t\u1eeb l\u00fd thuy\u1ebft, c\u00e1ch t\u01b0 duy \u0111\u1ebfn th\u1ef1c h\u00e0nh t\u1eebng b\u01b0\u1edbc x\u00e2y d\u1ef1ng \u1ee9ng d\u1ee5ng web ho\u00e0n ch\u1ec9nh.\" \/>\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-tutorial\/\" \/>\n<meta property=\"og:locale\" content=\"vi_VN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Spring MVC tutorial: H\u01b0\u1edbng d\u1eabn x\u00e2y \u1ee9ng d\u1ee5ng web v\u1edbi Spring MVC\" \/>\n<meta property=\"og:description\" content=\"Khi nh\u1eafc \u0111\u1ebfn h\u1ec7 sinh th\u00e1i Java, Spring MVC lu\u00f4n l\u00e0 l\u1ef1a ch\u1ecdn h\u00e0ng \u0111\u1ea7u. Nh\u01b0ng l\u00e0m th\u1ebf n\u00e0o \u0111\u1ec3 \u00e1p d\u1ee5ng n\u00f3 m\u1ed9t c\u00e1ch hi\u1ec7u qu\u1ea3 v\u00e0o c\u00f4ng vi\u1ec7c? B\u00e0i vi\u1ebft Spring MVC\" \/>\n<meta property=\"og:url\" content=\"https:\/\/itviec.com\/blog\/spring-mvc-tutorial\/\" \/>\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-10T08:49:44+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-07-10T08:49:47+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/spring-mvc-tutorial-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=\"19 ph\u00fat\" \/>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Spring MVC tutorial: H\u01b0\u1edbng d\u1eabn x\u00e2y \u1ee9ng d\u1ee5ng web v\u1edbi Spring MVC - ITviec Blog","description":"H\u01b0\u1edbng d\u1eabn Spring MVC tutorial th\u1ef1c chi\u1ebfn chi ti\u1ebft, t\u1eeb l\u00fd thuy\u1ebft, c\u00e1ch t\u01b0 duy \u0111\u1ebfn th\u1ef1c h\u00e0nh t\u1eebng b\u01b0\u1edbc x\u00e2y d\u1ef1ng \u1ee9ng d\u1ee5ng web ho\u00e0n ch\u1ec9nh.","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-tutorial\/","og_locale":"vi_VN","og_type":"article","og_title":"Spring MVC tutorial: H\u01b0\u1edbng d\u1eabn x\u00e2y \u1ee9ng d\u1ee5ng web v\u1edbi Spring MVC","og_description":"Khi nh\u1eafc \u0111\u1ebfn h\u1ec7 sinh th\u00e1i Java, Spring MVC lu\u00f4n l\u00e0 l\u1ef1a ch\u1ecdn h\u00e0ng \u0111\u1ea7u. Nh\u01b0ng l\u00e0m th\u1ebf n\u00e0o \u0111\u1ec3 \u00e1p d\u1ee5ng n\u00f3 m\u1ed9t c\u00e1ch hi\u1ec7u qu\u1ea3 v\u00e0o c\u00f4ng vi\u1ec7c? B\u00e0i vi\u1ebft Spring MVC","og_url":"https:\/\/itviec.com\/blog\/spring-mvc-tutorial\/","og_site_name":"ITviec Blog","article_publisher":"https:\/\/www.facebook.com\/ITviec","article_published_time":"2025-07-10T08:49:44+00:00","article_modified_time":"2025-07-10T08:49:47+00:00","og_image":[{"width":2560,"height":1347,"url":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/spring-mvc-tutorial-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":"19 ph\u00fat"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/itviec.com\/blog\/spring-mvc-tutorial\/#article","isPartOf":{"@id":"https:\/\/itviec.com\/blog\/spring-mvc-tutorial\/"},"author":{"name":"Tien Tran","@id":"https:\/\/itviec.com\/blog\/#\/schema\/person\/1595d671c49cfa2a48cd3c0a047a1298"},"headline":"Spring MVC tutorial: H\u01b0\u1edbng d\u1eabn x\u00e2y \u1ee9ng d\u1ee5ng web v\u1edbi Spring MVC","datePublished":"2025-07-10T08:49:44+00:00","dateModified":"2025-07-10T08:49:47+00:00","mainEntityOfPage":{"@id":"https:\/\/itviec.com\/blog\/spring-mvc-tutorial\/"},"wordCount":4778,"publisher":{"@id":"https:\/\/itviec.com\/blog\/#organization"},"image":{"@id":"https:\/\/itviec.com\/blog\/spring-mvc-tutorial\/#primaryimage"},"thumbnailUrl":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/spring-mvc-tutorial-scaled.png","articleSection":["Chuy\u00ean m\u00f4n IT"],"inLanguage":"vi"},{"@type":"WebPage","@id":"https:\/\/itviec.com\/blog\/spring-mvc-tutorial\/","url":"https:\/\/itviec.com\/blog\/spring-mvc-tutorial\/","name":"Spring MVC tutorial: H\u01b0\u1edbng d\u1eabn x\u00e2y \u1ee9ng d\u1ee5ng web v\u1edbi Spring MVC - ITviec Blog","isPartOf":{"@id":"https:\/\/itviec.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/itviec.com\/blog\/spring-mvc-tutorial\/#primaryimage"},"image":{"@id":"https:\/\/itviec.com\/blog\/spring-mvc-tutorial\/#primaryimage"},"thumbnailUrl":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/spring-mvc-tutorial-scaled.png","datePublished":"2025-07-10T08:49:44+00:00","dateModified":"2025-07-10T08:49:47+00:00","description":"H\u01b0\u1edbng d\u1eabn Spring MVC tutorial th\u1ef1c chi\u1ebfn chi ti\u1ebft, t\u1eeb l\u00fd thuy\u1ebft, c\u00e1ch t\u01b0 duy \u0111\u1ebfn th\u1ef1c h\u00e0nh t\u1eebng b\u01b0\u1edbc x\u00e2y d\u1ef1ng \u1ee9ng d\u1ee5ng web ho\u00e0n ch\u1ec9nh.","breadcrumb":{"@id":"https:\/\/itviec.com\/blog\/spring-mvc-tutorial\/#breadcrumb"},"inLanguage":"vi","potentialAction":[{"@type":"ReadAction","target":["https:\/\/itviec.com\/blog\/spring-mvc-tutorial\/"]}]},{"@type":"ImageObject","inLanguage":"vi","@id":"https:\/\/itviec.com\/blog\/spring-mvc-tutorial\/#primaryimage","url":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/spring-mvc-tutorial-scaled.png","contentUrl":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/07\/spring-mvc-tutorial-scaled.png","width":800,"height":421,"caption":"Spring MVC tutorial - itviec blog"},{"@type":"BreadcrumbList","@id":"https:\/\/itviec.com\/blog\/spring-mvc-tutorial\/#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 tutorial: H\u01b0\u1edbng d\u1eabn x\u00e2y \u1ee9ng d\u1ee5ng web 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\/89206","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=89206"}],"version-history":[{"count":4,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/posts\/89206\/revisions"}],"predecessor-version":[{"id":89289,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/posts\/89206\/revisions\/89289"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/media\/89287"}],"wp:attachment":[{"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/media?parent=89206"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/categories?post=89206"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/tags?post=89206"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}