Spring MVC واقعا چگونه کار میکند؟
در این مطلب، ما نگاهی خواهیم داشت به این که چگونه ویژگیهای موجود در Spring MVC میتوانند اثر بزرگی در یک برنامه وب داشته باشند.
این یک نگاه عمیق به ویژگیهای قدرتمند و عملکرد داخلی از Spring MVC است که بخشی از چارچوب Spring میباشد.
کد این مطلب در GitHub موجود است.
راه اندازی پروژه
در طول این مقاله، از آخرین و بزرگترین چارچوب Spring 5 استفاده میکنیم.
ما بر روی وب استک کلاسیک Spring متمرکز هستیم، که از نسخههای ابتدایی این چارچوب در دسترس بوده و کماکان راه حل اولیه برای ساخت برنامههای کاربردی وب با استفاده از Spring است.
با در نظر گرفتن افراد مبتدی، برای شروع به کار، از Spring Boot و برخی از dependencyهای ابتدایی آن استفاده میکنیم؛ همچنین باید parent را به این شکل تعریف کنیم:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.0.M5</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> </dependencies>
توجه داشته باشید که برای استفاده از Spring 5 باید از Spring Boot 2.x استفاده کنید. در زمان نوشتن این مطلب، این نسخه یک milestone برای انتشار میباشد، که در Spring Milestone Repository در دسترس است. این انباره را به پروژه Maven اضافه میکنیم:
<repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
شما میتوانید نسخه فعلی Spring Boot را در Maven Central بررسی کنید.
پروژه نمونه
برای درک اینکه بدانید چگونه Spring Web MVC کار میکند، یک برنامه ساده با یک صفحه لاگین را اجرا خواهیم کرد. برای نمایش صفحه لاگین، کلاس InternalController با حاشیهنگاری Controller@ به همراه یک GET mapping برای ریشه ایجاد میکنیم.
متد hello بدون پارامتر است. یک رشته را باز میگرداند که توسط Spring MVC به عنوان نام view (در اینجا، تمپلت login.html) تفسیر میشود:
import org.springframework.web.bind.annotation.GetMapping; @GetMapping("/") public String hello() { return "login"; }
برای پردازش ورود یک کاربر، تابع دیگری ایجاد کنید که درخواستهای POST را با اطلاعات ورودی هندل کند. پس از آن، بسته به نتیجه، کاربر را به صفحه موفقیت یا شکست منتقل میکند.
توجه داشته باشید که متد login یک شی دامنه را به عنوان آرگومان دریافت میکند و یک شی ModelAndView باز میگرداند.
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.servlet.ModelAndView; @PostMapping("/login") public ModelAndView login(LoginData loginData) { if (LOGIN.equals(loginData.getLogin()) && PASSWORD.equals(loginData.getPassword())) { return new ModelAndView("success", Collections.singletonMap("login", loginData.getLogin())); } else { return new ModelAndView("failure", Collections.singletonMap("login", loginData.getLogin())); } }
ModelAndView دو شئ متمایز دارد:
– Model- یک نگاشت کلید-مقدار از دادههایی است که برای رندر صفحه استفاده میشوند.
– View – یک قالب از صفحه که با دادهای مدل پر شده است.
اینها برای راحتی در یک شئ تجمیع شدهاند به طوری که کنترلر میتواند هر دو را در یک زمان بازگرداند.
برای نمایش صفحه HTML خود، از Thymeleaf به عنوان موتور تمپلت view استفاده کنید، که از ابتدا با Spring یکپارچه شده است.
Servlet به عنوان اساس یک برنامه وب جاوا
وقتی آدرس http://localhost:8080 در مرورگر تایپ میکنید، چه اتفاقی میافتد، دکمه Enter را فشار دهید، درخواستی به وب سرور باز میشود؟ چگونه از این درخواست برای مشاهده یک فرم وب در مرورگر استفاده میکنید؟
با فرض این که برنامه Spring Boot یک برنامه ساده است، شما میتوانید آن را از طریق Spring5Application اجرا کنید.
Spring Boot از Apache Tomcat به طور پیش فرض استفاده میکند. از این رو با اجرای برنامه، احتمالا اطلاعات زیر را در ورود به سیستم مشاهده خواهید کرد:
2017-10-16 20:36:11.626 INFO 57414 --- [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http) 2017-10-16 20:36:11.634 INFO 57414 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2017-10-16 20:36:11.635 INFO 57414 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.23
از آنجا که Tomcat یک کانتینر Servlet است، به طور طبیعی هر درخواست HTTP ارسال شده به وب سرور Tomcat توسط یک servlet جاوا پردازش میشود. بنابراین نقطه ورود به وب اپلیکیشن Spring ، یک servlet است.
servlet ، یک مولفه اصلی هر برنامه وب جاوا است؛ سطح پایین است و الگوهای خاص برنامهنویسی را مانند MVC، تحمیل نمیکند.
Servlet HTTP تنها میتواند یک درخواست HTTP دریافت کند، آن را پردازش و یک پاسخ ارسال نماید. با استفاده از API Servlet 3.0 به عنوان شروع، شما هم اکنون میتوانید فراتر از پیکربندی XML حرکت کنید و از تنظیمات جاوا (با محدودیت های جزئی) استفاده کنید.
Servlet Dispatcher به عنوان قلب Spring MVC
آنچه که ما واقعا میخواهیم به عنوان توسعهدهندگان یک برنامه وب انجام دهیم این است که وظایف خستهکننده و تکراری زیر را کنار بگذاریم و روی business logic به درد بخور تمرکز کنیم:
- نگاشت یک درخواست HTTP به یک روش پردازش خاص
- تجزیه دادههای درخواست HTTP و هدرها به اشیاء انتقال دادهها (DTOها) یا اشیاء دامنه
- تعامل model-view-controller
- تولید پاسخ از DTOها، اشیاء دامنه و غیره
DispatcherServlet در Spring دقیقا همان چیز را فراهم میکند. این قلب چارچوب Spring Web MVC است. این مولفه اصلی تمام درخواستها را برای برنامه شما دریافت میکند.
همانطور که میبینید، Servlet Dispatcher بسیار قابل گسترش است. به عنوان مثال، به شما اجازه میدهد تا آداپتورهای مختلف موجود یا جدید را بر بسیاری از کارها متصل کنید:
- نگاشت یک درخواست به یک کلاس یا متد که باید آن را هندل کند (درخواست پیادهسازی واسط کاربری HandlerMapping )
- یک درخواست با استفاده از یک الگوی خاص مانند یک servlet معمولی، یک ورک فلو پیچیدهتر MVC و یا فقط یک تابع در یک POJO bean (پیاده سازی رابط HandlerAdapter)
- بازبینی نمایهها بر اساس نام، اجازه میدهد تا شما از موتورهای قالببندی مختلف، XML، XSLT یا هر نوع تکنولوژی view دیگر استفاده کنید (پیاده سازی رابط ViewResolver)
- تجزیه و تحلیل درخواستهای چندبخشی با استفاده از پیادهسازی پیشفرض Apache Commons file uploading یا پیادهسازی MultipartResolver دلخواه خود
- مشخص کردن موقعیت با هر گونه پیادهسازی LocaleResolver، که شامل کوکی، session، Accept Http header، و یا هر روش دیگر تعیین موقعیت مورد انتظار کاربر میشود.
در ادامه این مطلب، در بخش دوم، پردازش یک درخواست HTTP را بررسی میکنیم.
بقیش کو؟چرا ادامه نداره؟
لینک ادامه مطلب در انتهای مقاله اضافه شد.
با تشکر
سلام من سر این معماری طراحی یکم برام گنگه این الان واقعا MVC هست ؟ چون توی آموزش ها در بازه MVC ساختار تفاوت داره و View مستقیم به Model ارتباط داره در صورتی که توی کد هم این به نظر م درست نیست و شکل بالا صحیح تره
لطف میکنه کسی این رو توضیح بده ؟
بالاخره MVC به جاوا هم نفوذ کرد 🙂
سلام مقاله خوبی بود.ولی در مورد کانفیگ سرور و پروژه باید ساده تر از این حرف زده میشد.این مقاله یه خورد سریع و جنگ در کانفیگ صحبت کرد.
اگر ممکنه در این مورد ساده و سلیس تر صحبت بشه
ممنون
ببخشید منظور سریع و گنگ بود.
سلام
مرسی – مقاله خوبی بود ، Thymeleaf به نظرم عالی هستش و همینکه تمامی ویژگی های JSTL رو هم داره واقعا کار باهاش رو ساده تر هم میکنه