Skip to content

1. مقدمه

PDF برای این سند در |ICI| موجود است.

مثال‌های این سند در |ICI| موجود است.

در این سند، هدف ما معرفی مفاهیم کلیدی Spring MVC، یک چارچوب وب جاوا، از طریق مثال‌ها است؛ این چارچوب، چارچوبی برای توسعه برنامه‌های وب بر اساس الگوی MVC (مدل–نما–کنترل‌کننده) فراهم می‌کند. اسپرینگ MVC شاخه‌ای از اکوسیستم اسپرینگ [http://projects.spring.io/spring-framework/] است. ما همچنین موتور نمای Thymeleaf [http://www.thymeleaf.org/] را معرفی می‌کنیم.

این دوره برای خوانندگانی با تسلط کامل بر زبان جاوا در نظر گرفته شده است. هیچ پیش‌زمینه‌ای در برنامه‌نویسی وب مورد نیاز نیست.

اگرچه این سند جامع است، اما احتمالاً ناقص خواهد بود. اسپرینگ یک چارچوب گسترده با شاخه‌های متعدد است. برای بررسی عمیق‌تر Spring MVC، می‌توان به مراجع زیر مراجعه کرد:

  • سند مرجع فریم‌ورک Spring [http://docs.spring.io/spring/docs/current/spring-framework-reference/pdf/spring-framework-reference.pdf
  • تعداد زیادی آموزش Spring را می‌توان در وب‌سایت‌های URL و [http://spring.io/guides] یافت.
  • وب‌سایت [developpez.com] که به اسپرینگ [http://spring.developpez.com/] اختصاص دارد.

این سند به گونه‌ای نوشته شده است که بتوان آن را بدون رایانه در دسترس خواند. در نتیجه، شامل تصاویر صفحه متعدد است.

1.1. Sources

این سند دو منبع اصلی دارد:

  • [مقدمه‌ای بر چارچوب ASP.NET MVC از طریق مثال‌ها (۲۰۱۳)]. Spring MVC و ASP.NET MVC دو چارچوب مشابه هستند که دومی به مراتب بعد از اولی توسعه یافته است. برای مقایسه این دو چارچوب، من از ساختار مشابهی که در سند مربوط به ASP.NET و MVC وجود دارد، پیروی کرده‌ام؛
  • سند مربوط به ASP.NET MVC در حال حاضر (دسامبر ۲۰۱۴) شامل مطالعه موردی با ارائه راه‌حل آن نیست. من راه‌حل موجود در سند [یک مثال کلاینت/سرور – AngularJS 1.x / Spring 4 (۲۰۱۴) را که به شرح زیر اصلاح کرده‌ام، در اینجا گنجانده‌ام:
    • مطالعه موردی در [یک مثال کلاینت/سرور – AngularJS 1.x / Spring 4 (۲۰۱۴) مربوط به یک برنامه کاربردی کلاینت/سرور است که در آن سرور یک سرویس وب / jSON است که با استفاده از Spring MVC ساخته شده و کلاینت یک برنامه کاربردی کلاینت AngularJS است؛
    • در این سند، ما از همان سرویس وب / jSON استفاده می‌کنیم، اما کلاینت یک برنامه وب دو لایه [client jQuery] / [service web / jSON] است؛

علاوه بر این منابع، برای یافتن پاسخ سؤالاتم در اینترنت جستجو کردم. وب‌سایت [http://stackoverflow.com/] به‌ویژه مفید بود.

1.2. ابزارهای مورد استفاده

مثال‌های زیر در محیط زیر آزمایش شده‌اند:

  • ماشین ویندوز 8.1 پرو 64 بیتی؛
  • JDK 1.8;
  • IDE Spring Tool Suite 3.6.3 (به بخش 9.3 مراجعه کنید);
  • مرورگر کروم (از سایر مرورگرها استفاده نشده است)؛
  • افزونه کروم [Advanced Rest Client] (به بخش 9.6 مراجعه کنید);

لطفاً توجه داشته باشید JDK 1.8. یکی از روش‌های مورد مطالعه از متدی در بسته [java.lang] در جاوا ۸ استفاده می‌کند.

تمام مثال‌ها پروژه‌های Maven هستند که می‌توان آن‌ها را در Eclipse (IDEIntellijIDEA یا NetBeans باز کرد. در ادامه، اسکرین‌شات‌ها از Spring Tool Suite (IDE)، یک نسخه از Eclipse، گرفته شده‌اند.

1.3. مثال‌ها

این مثال‌ها در URL [http://tahe.developpez.com/java/springmvc-thymeleaf] به صورت یک فایل قابل دانلود zip در دسترس هستند.

  

برای بارگذاری تمام پروژه‌ها در STS، مراحل زیر را دنبال کنید:

  • در [1-3]، پروژه‌های Maven را وارد کنید؛
  • در [4]، پوشهٔ examples را مشخص کنید؛
  • در [5]، تمام پروژه‌ها را در پوشه انتخاب کنید؛
  • در [6]، تأیید کنید؛
  • در [7]، پروژه‌های واردشده؛

1.4. نقش Spring MVC در یک برنامه وب

بیایید نقش Spring MVC را در توسعه یک برنامه وب در نظر بگیریم. اغلب این برنامه بر روی یک معماری چندلایه مانند زیر ساخته می‌شود:

  • لایه [Web] لایه‌ای است که با کاربر وب‌اپلیکیشن تعامل می‌کند. کاربر از طریق صفحات وبی که در یک مرورگر نمایش داده می‌شوند، با وب‌اپلیکیشن تعامل دارد. اسپرینگ MVC در این لایه قرار دارد، و تنها در همین لایه؛
  • لایه [métier] منطق کسب‌وکار برنامه را پیاده‌سازی می‌کند، مانند محاسبه حقوق یا فاکتور. این لایه داده‌ها را از کاربر از طریق لایه [Web] و از لایه SGBD از طریق لایه [DAO] استفاده می‌کند؛
  • لایه [DAO] (ابجکت‌های دسترسی به داده)، لایه [ORM] (نقشه‌بردار شیء-رابطه‌ای) و درایور JDBC دسترسی به داده‌ها در SGBD را مدیریت می‌کنند. لایه [ORM] به‌عنوان پلی میان اشیایی که توسط لایه [DAO] مدیریت می‌شوند و سطر و ستون‌های جدول‌ها در یک پایگاه داده رابطه‌ای عمل می‌کند. در اینجا، از Hibernate با شناسه ORM استفاده خواهیم کرد. یک مشخصه که با نام JPA (پایداری جاوا API) شناخته می‌شود، این امکان را می‌دهد که از ORM مورد استفاده انتزاع شود، به شرطی که آن مشخصات را پیاده‌سازی کند. این موضوع در مورد Hibernate و سایر پیاده‌سازی‌های ORM جاوا نیز صدق می‌کند. بنابراین از این پس، ما به لایه ORM به عنوان لایه JPA اشاره خواهیم کرد؛
  • ادغام لایه‌ها توسط فریم‌ورک Spring انجام می‌شود؛

اکثر مثال‌های ارائه‌شده در زیر تنها از یک لایه، لایه [Web]، استفاده خواهند کرد:

با این حال، این سند با ساخت یک برنامه وب چندلایه به پایان می‌رسد:

مرورگر به یک برنامه [Web1] که توسط Spring MVC پیاده‌سازی شده است، متصل خواهد شد / Thymeleaf که داده‌های خود را از یک سرویس وب [Web2] بازیابی می‌کند، همچنین با استفاده از Spring MVC پیاده‌سازی شده است. این اپلیکیشن وب دوم به یک پایگاه داده دسترسی خواهد داشت.

1.5. مدل توسعه Spring MVC

اسپرینگ MVC الگوی معماری موسوم به MVC (مدل–نما–کنترل‌کننده) را به شرح زیر پیاده‌سازی می‌کند:

پردازش یک درخواست مشتری به شرح زیر انجام می‌شود:

  1. درخواستURLهای درخواستی به شکل http://machine:port/contexte/Action/param1/param2/....?p1=v1&p2=v2&... هستند. [Front Controller] از یک فایل پیکربندی یا anotationهای جاوا برای «مسیردهی» درخواست به کنترل‌کننده صحیح و اکشن صحیح در آن کنترل‌کننده استفاده می‌کند. برای این کار، از فیلد [Action] در URL استفاده می‌کند. باقی‌مانده URL و [/param1/param2/...] شامل پارامترهای اختیاری است که به اکشن ارسال خواهند شد. C در MVC در این مورد، رشته [Front Controller, Contrôleur, Action] است. اگر هیچ کنترلری نتواند اقدام درخواستی را مدیریت کند، وب‌سرور پاسخ خواهد داد که URL درخواستی یافت نشد.
  1. پردازش
  • عمل انتخاب‌شده می‌تواند از پارامترهای parami که توسط [Front Controller] به آن ارسال شده‌اند، استفاده کند. این پارامترها ممکن است از چندین منبع منشأ بگیرند:
    • مسیر [/param1/param2/...] از URL،
    • پارامترهای [p1=v1&p2=v2] از URL,
    • از پارامترهای ارسال‌شده توسط مرورگر در درخواست آن؛
  • هنگام پردازش درخواست کاربر، ممکن است اقدام به لایه‌های [métier] و [2b] نیاز داشته باشد. پس از پردازش درخواست مشتری، ممکن است پاسخ‌های مختلفی ایجاد شود. یک مثال کلاسیک این است:
    • یک صفحهٔ خطا اگر درخواست نتوانست به‌درستی پردازش شود
    • در غیر این صورت، یک صفحه تأیید
  • اقدام دستور نمایش یک نمای خاص را صادر می‌کند: [3]. این نما داده‌هایی را که به عنوان مدل نما شناخته می‌شوند، نمایش می‌دهد. این همان M در MVC است. اقدام این مدل M [2c] را ایجاد می‌کند و به نمایش V دستور نمایش می‌دهد [3]؛
  1. پاسخ – نمای انتخاب‌شده V از مدل M که توسط اکشن ساخته شده است برای راه‌اندازی بخش‌های پویا از پاسخ HTML که باید به کلاینت ارسال کند، استفاده می‌کند و سپس این پاسخ را ارسال می‌کند.

اکنون، بیایید ارتباط بین معماری وب MVC و معماری لایه‌ای را روشن کنیم. بسته به نحوه تعریف مدل، این دو مفهوم ممکن است به هم مرتبط باشند یا نباشند. بیایید یک برنامه وب تک‌لایه اسپرینگ MVC را در نظر بگیریم:

اگر لایه [Web] را با Spring MVC پیاده‌سازی کنیم، در واقع یک معماری وب MVC خواهیم داشت، اما یک معماری چندلایه نخواهیم داشت. در اینجا لایه [web] همه چیز را مدیریت خواهد کرد: ارائه، منطق کسب‌وکار و دسترسی به داده‌ها. این اکشن‌ها هستند که این کار را انجام می‌دهند.

اکنون، بیایید یک معماری وب چندلایه را در نظر بگیریم:

لایه [Web] می‌تواند بدون فریم‌ورک و بدون پیروی از مدل MVC پیاده‌سازی شود. بنابراین ما در واقع یک معماری چندلایه داریم، اما لایه وب مدل MVC را پیاده‌سازی نمی‌کند.

برای مثال، در محیط .NET، لایه [Web]می‌تواند با استفاده از ASP.NET و MVC پیاده‌سازی شود که منجر به یک معماری لایه‌ای با یک لایه [Web] از نوع MVC می‌شود. پس از انجام این کار، این لایه ASP.NET و MVC را می‌توان با یک لایه استاندارد ASP.NET (WebForms) جایگزین کرد در حالی که بقیه حفظ می‌شوند (لایه کسب‌وکار، DAO، ORM) دقیقاً همان‌طور که هست. سپس ما یک معماری لایه‌ای داریم که در آن لایه [Web] دیگر از نوع MVC نیست.

در MVC بیان کردیم که مدل M همان نمای V است، c.a.d – مجموعه‌ای از داده‌هایی که توسط نمای V نمایش داده می‌شوند. تعریف دیگری از مدل M برای MVC ارائه شده است:

بسیاری از نویسندگان معتقدند آنچه در سمت راست لایه [Web] قرار دارد، مدل M از MVC را تشکیل می‌دهد. برای جلوگیری از ابهام، می‌توان به موارد زیر اشاره کرد:

  • مدل دامنه وقتی به همه چیز در سمت راست لایه [Web] اشاره می‌شود
  • مدل نما هنگام اشاره به داده‌های نمایش‌داده‌شده توسط یک نما V

از این پس، اصطلاح «مدل M» منحصراً به مدل یک نما V اشاره خواهد داشت.

1.6. یک پروژهٔ اولی Spring MVC

از این پس، ما با Spring Tool Suite (STS) کار خواهیم کرد که نسخه‌ای از اکلیپس (Eclipse) است که برای اسپرینگ (Spring) سفارشی شده است. وب‌سایت [http://spring.io/guides] آموزش‌های شروع کار را برای کمک به شما در کاوش در اکوسیستم اسپرینگ ارائه می‌دهد. ما یکی از این موارد را دنبال خواهیم کرد تا پیکربندی Maven مورد نیاز برای یک پروژه Spring MVC را کشف کنیم.

توجه: اکثر مبتدیان جزئیات پروژه را به طور کامل درک نخواهند کرد. این مهم نیست. این جزئیات بعداً در این سند توضیح داده می‌شوند. ما صرفاً مراحل را دنبال خواهیم کرد.

1.6.1. پروژهٔ نمایشی

  • در [1]، ما یکی از راهنماهای Spring را وارد می‌کنیم؛
  • در [2]، مثال [Serving Web Content] را انتخاب می‌کنیم؛
  • در [3]، پروژه Maven را انتخاب می‌کنیم؛
  • در [4]، نسخه نهایی راهنما را انتخاب می‌کنیم؛
  • در [5] تأیید می‌کنیم؛
  • در [6]، پروژهٔ واردشده؛

بیایید پروژه را بررسی کنیم، با پیکربندی Maven آن شروع می‌کنیم.

1.6.2. پیکربندی Maven

فایل [pom.xml] به شرح زیر است:


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.springframework</groupId>
    <artifactId>gs-serving-web-content</artifactId>
    <version>0.1.0</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.1.9.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
    </dependencies>

    <properties>
        <start-class>hello.Application</start-class>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-milestone</id>
            <url>https://repo.spring.io/libs-release</url>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>spring-milestone</id>
            <url>https://repo.spring.io/libs-release</url>
        </pluginRepository>
    </pluginRepositories>

</project>
  • خطوط ۶–۸: ویژگی‌های پروژه Maven. یک تگ [<packaging>] که نوع فایلی را که توسط ساخت Maven تولید می‌شود مشخص می‌کند، وجود ندارد. در غیاب این تگ، نوع [jar] استفاده می‌شود. بنابراین این برنامه یک برنامهٔ قابل اجرای مبتنی بر کنسول است، نه یک برنامهٔ وب، که در این صورت بسته‌بندی آن [war] خواهد بود؛
  • خطوط ۱۰–۱۴: پروژه Maven یک پروژه والد به نام [spring-boot-starter-parent] دارد. این پروژه بیشتر وابستگی‌های پروژه را تعریف می‌کند. این وابستگی‌ها ممکن است کافی باشند، که در این صورت هیچ وابستگی دیگری اضافه نمی‌شود، یا ممکن است کافی نباشند، که در این صورت وابستگی‌های missing اضافه می‌شوند؛
  • خطوط 17–20: آرتفکت [spring-boot-starter-thymeleaf] شامل کتابخانه‌های مورد نیاز برای یک پروژه Spring، MVC، است که در conjunction با یک موتور نما به نام [Thymeleaf] استفاده می‌شود. این آرتفکت شامل تعداد بسیار زیادی کتابخانه، از جمله کتابخانه‌های مربوط به یک سرور Tomcat تعبیه‌شده است. این اپلیکیشن بر روی همین سرور اجرا خواهد شد؛

کتابخانه‌های بسیار زیادی در این پیکربندی گنجانده شده‌اند:

در بالا آرشیوهای سرور Tomcat آمده است.

Spring Boot شاخه‌ای از اکوسیستم Spring ([http://projects.spring.io/spring-boot/]) است. هدف این پروژه این است که پیکربندی مورد نیاز برای پروژه‌های Spring را تا حد امکان به حداقل برساند. برای دستیابی به این هدف، Spring Boot بر اساس وابستگی‌های موجود در classpath پروژه، پیکربندی خودکار را انجام می‌دهد. Spring Boot وابستگی‌های آمادهٔ متعددی را فراهم می‌کند. بنابراین، وابستگی [spring-boot-starter-thymeleaf] که در پروژهٔ Maven قبلی یافت می‌شود، تمام وابستگی‌های مورد نیاز برای یک برنامهٔ Spring MVC را که از موتور نما [Thymeleaf] استفاده می‌کند، فراهم می‌آورد. با این دو ویژگی:

  • وابستگی‌های آماده به کار؛
  • پیکربندی خودکار بر اساس این وابستگی‌ها و مقادیر پیش‌فرض «منطقی»، امکان راه‌اندازی سریع یک برنامه Spring MVC را فراهم می‌کند. این موضوع در مورد پروژه‌ای که در اینجا بررسی شده نیز صدق می‌کند؛

1.6.3. معماری یک برنامه Spring MVC

اسپرینگ MVC الگوی معماری موسوم به MVC (مدل–نما–کنترل‌کننده) را پیاده‌سازی می‌کند:

پردازش یک درخواست مشتری به شرح زیر انجام می‌شود:

  1. درخواست URL درخواستی به شکل http://machine:port/contexte/Action/param1/param2/....?p1=v1&p2=v2&... است. [Dispatcher Servlet] کلاسی از Spring است که URL ورودی را پردازش می‌کند. این URL را به اکشنی که باید آن را پردازش کند، مسیریابی می‌کند. این اکشن‌ها متدهایی از کلاس‌های خاصی هستند که [Contrôleurs] نامیده می‌شوند. «C» در MVC در این مورد، رشته [Dispatcher Servlet, Contrôleur, Action] است. اگر هیچ عملی برای رسیدگی به URL ورودی پیکربندی نشده باشد، سرولت [Dispatcher Servlet] پاسخ خواهد داد که URL درخواستی یافت نشد (خطای ۴۰۴ NOT FOUND);
  2. پردازش
  • عملکرد انتخاب‌شده می‌تواند از پارامترهای parami که توسط سرولت [Dispatcher Servlet] به آن ارسال شده است، استفاده کند. این پارامترها ممکن است از چندین منبع منشأ بگیرند:
    • مسیر [/param1/param2/...] از URL،
    • پارامترهای [p1=v1&p2=v2] از URL,
    • پارامترهای ارسال‌شده توسط مرورگر در درخواست آن؛
  • هنگام پردازش درخواست کاربر، ممکن است اقدام به لایه [metier] [2b] نیاز داشته باشد. پس از پردازش درخواست مشتری، ممکن است پاسخ‌های مختلفی ایجاد شود. یک مثال معمول عبارت است از:
    • یک صفحهٔ خطا اگر درخواست نتوانست به درستی پردازش شود
    • در غیر این صورت، یک صفحه تأیید
  • اقدام دستور نمایش یک نمای خاص را صادر می‌کند: [3]. این نما داده‌هایی را که به عنوان مدل نما شناخته می‌شوند، نمایش می‌دهد. این همان M در MVC است. اقدام این مدل M [2c] را ایجاد کرده و دستور نمایش یک نما V [3] را صادر می‌کند؛
  1. پاسخ – نمای انتخاب‌شده V از مدل M ایجادشده توسط اقدام برای راه‌اندازی بخش‌های پویا از پاسخی که باید به کلاینت ارسال کند، استفاده می‌کند و سپس این پاسخ را ارسال می‌کند.

ما این عناصر مختلف را در پروژه مورد بررسی قرار خواهیم داد.

1.6.4. کنترل‌کننده C

  

برنامه واردشده دارای کنترلر زیر است:


package hello;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class GreetingController {

    @RequestMapping("/greeting")
    public String greeting(@RequestParam(value="name", required=false, defaultValue="World") String name, Model model) {
        model.addAttribute("name", name);
        return "greeting";
    }

}
  • خط ۸: تذکر [@Controller] کلاس [GreetingController] را به‌عنوان یک کنترلر Spring مشخص می‌کند، یعنی متدهای آن برای رسیدگی به URL ثبت شده‌اند. یک کنترلر Spring یک نمونهٔ واحد (singleton) است. تنها یک نمونه از آن ایجاد می‌شود؛
  • خط ۱۱: anotation [@RequestMapping] متدی را که این متد کنترل می‌کند مشخص می‌کند، در این مورد URL [/greeting] است. بعداً خواهیم دید که این URL را می‌توان پیکربندی کرد و بازیابی این پارامترها امکان‌پذیر است؛
  • خط ۱۲: متد دو پارامتر می‌گیرد:
    • [String name]: این پارامتر توسط پارامتری به نام [name] در درخواست پردازش‌شده مقداردهی اولیه می‌شود، برای مثال [/greeting?name=alfonse]. این پارامتر اختیاری است ([required=false]) و در صورت عدم وجود، پارامتر [name] مقدار 'World' ([defaultValue="World"]) را خواهد گرفت،
    • [Model model] یک مدل نما (view model) است. این مدل به صورت خالی ارسال می‌شود و وظیفه متد اکشن (greeting) است که آن را پر کند. این مدل است که به نما ارسال می‌شود و سپس اکشن آن را نمایش می‌دهد. بنابراین، این یک مدل نما است؛
  • خط ۱۳: مقدار [name] در مدل نما قرار می‌گیرد. کلاس [Model] مانند یک دیکشنری عمل می‌کند؛
  • خط ۱۴: متد نام ویوی نمایش‌دهندهٔ قالب ساخته‌شده را برمی‌گرداند. نام دقیق ویو به پیکربندی [Thymeleaf] بستگی دارد. در صورت عدم وجود چنین پیکربندی، نمای نمایش داده شده در اینجا نمای [/templates/greeting.html] خواهد بود، یا پوشه [templates] باید در ریشهٔ مسیر کلاس پروژه قرار داشته باشد؛

بیایید نگاهی به پروژه Eclipse خود بیندازیم:

پوشه‌های [src/main/java] و [src/main/resources] هر دو پوشه‌هایی هستند که محتویاتشان به کلاس‌پث پروژه اضافه خواهد شد. برای [src/main/java]، نسخه‌های کامپایل‌شده کد منبع جاوا به کلاس‌پث اضافه خواهند شد. از سوی دیگر، محتویات پوشه [src/main/resources] بدون تغییر به کلاس‌پث اضافه می‌شوند. بنابراین می‌توانیم ببینیم که پوشه [templates] در کلاس‌پث پروژه [1] قرار خواهد گرفت.

این موضوع را می‌توان با بررسی [2-3] در پنجره [Navigator] در Eclipse [Window / Show view / Other / General / Navigator] تأیید کرد. پوشه [target] توسط build پروژه (با نام build) ایجاد می‌شود. پوشه [classes] نمایانگر ریشه classpath است. می‌توان دید که پوشه [templates] در آنجا موجود است.

1.6.5. نما V

در MVC، ما به تازگی کنترل‌کننده C و مدل نمای M را دیدیم. نمای V در اینجا با فایل زیر، [greeting.html]، نشان داده شده است:


<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Getting Started: Serving Web Content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
    <p th:text="'Hello, ' + ${name} + '!'" />
</body>
</html>
  • خط ۲: فضای نام تگ Thymeleaf؛
  • خط ۸: یک تگ (پاراگراف) با یک ویژگی Thymeleaf. ویژگی [th:text] محتوای پاراگراف را تعیین می‌کند. در داخل این رشته، عبارت [${name}] را داریم. این بدان معناست که ما می‌خواهیم مقدار ویژگی [name] را از قالب نما دریافت کنیم. با این حال، به یاد داریم که این ویژگی توسط اکشن در قالب قرار داده شده است:

model.addAttribute("name", name);

پارامتر اول نام ویژگی و پارامتر دوم مقدار آن را مشخص می‌کند.

1.6.6. اجرا

  

کلاس [Application.java] کلاس اجرایی پروژه است. کد آن به شرح زیر است:


package hello;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan;

@ComponentScan
@EnableAutoConfiguration
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}
  • خط ۱۱: این کلاس از طریق یک متد [main] که مخصوص برنامه‌های کنسول است، قابل اجرا است. کلاس [SpringApplication] در خط ۱۲، سرور Tomcat را که در وابستگی‌ها فهرست شده است، راه‌اندازی کرده و سرویس وب را روی آن مستقر می‌کند؛
  • خط ۴: می‌بینیم که کلاس [SpringApplication] به پروژه [Spring Boot] تعلق دارد؛
  • خط ۱۲: پارامتر اول کلاسی است که پروژه را پیکربندی می‌کند؛ پارامتر دوم حاوی هرگونه پارامتر اضافی است؛
  • خط ۸: آناوتیشن [@EnableAutoConfiguration] به Spring Boot دستور می‌دهد تا پروژه را پیکربندی کند؛
  • خط ۷: anotation [@ComponentScan] باعث می‌شود پوشه‌ای که حاوی کلاس [Application] است برای اجزای Spring اسکن شود. یکی پیدا خواهد شد: کلاس [GreetingController] که دارای انوتیشن [@Controller] است و آن را به یک کامپوننت Spring تبدیل می‌کند؛

بیایید پروژه را اجرا کنیم:

 

لاگ‌های کنسول زیر تولید می‌شوند:

.   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.1.9.RELEASE)

2014-11-27 16:48:12.567  INFO 3908 --- [           main] hello.Application                        : Starting Application on Gportpers3 with PID 3908 (started by ST in D:\data\istia-1415\spring mvc\dvp\gs-serving-web-content-complete)
2014-11-27 16:48:12.723  INFO 3908 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@1a38c59b: startup date [Thu Nov 27 16:48:12 CET 2014]; root of context hierarchy
2014-11-27 16:48:13.813  INFO 3908 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'beanNameViewResolver': replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class]]
2014-11-27 16:48:15.247  INFO 3908 --- [           main] .t.TomcatEmbeddedServletContainerFactory : Server initialized with port: 8080
2014-11-27 16:48:15.574  INFO 3908 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2014-11-27 16:48:15.575  INFO 3908 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/7.0.56
2014-11-27 16:48:15.955  INFO 3908 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2014-11-27 16:48:15.955  INFO 3908 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 3236 ms
2014-11-27 16:48:16.918  INFO 3908 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2014-11-27 16:48:16.922  INFO 3908 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2014-11-27 16:48:17.354  INFO 3908 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2014-11-27 16:48:17.679  INFO 3908 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/greeting],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String hello.GreetingController.greeting(java.lang.String,org.springframework.ui.Model)
2014-11-27 16:48:17.681  INFO 3908 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2014-11-27 16:48:17.682  INFO 3908 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],methods=[],params=[],headers=[],consumes=[],produces=[text/html],custom=[]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest)
2014-11-27 16:48:17.696  INFO 3908 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2014-11-27 16:48:17.697  INFO 3908 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2014-11-27 16:48:18.159  INFO 3908 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2014-11-27 16:48:18.491  INFO 3908 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080/http
2014-11-27 16:48:18.493  INFO 3908 --- [           main] hello.Application                        : Started Application in 6.833 seconds (JVM running for 8.658)
  • خط ۱۳: سرور Tomcat روی پورت ۸۰۸۰ شروع به کار می‌کند (خط ۱۲);
  • خط ۱۷: سرولت [DispatcherServlet] موجود است؛
  • خط ۲۰: متد [hello.GreetingController.greeting] کشف شده است، و همچنین URL که مسئول [/greeting] است؛

برای آزمایش برنامه وب، ما URL و [http://localhost:8080/greeting] را درخواست می‌کنیم:

 

ممکن است ارزش داشته باشد که سربرگ‌های HTTP ارسال‌شده توسط سرور را بررسی کنیم. برای این کار، از افزونهٔ Chrome به نام [Advanced Rest Client] استفاده خواهیم کرد (بخش 9.6 را ببینید):

  • در [1]، URL درخواست‌شده؛
  • در [2]، از روش GET استفاده می‌شود؛
  • در [3]، سرور اعلام کرد که در حال ارسال پاسخی با فرمت HTML است؛
  • در [4]، پاسخ HTML است؛
  • در [5]، همان URL درخواست می‌شود، اما این بار با POST؛
  • در [7]، اطلاعات به شکل [urlencoded] به سرور ارسال می‌شود؛
  • در [6]، پارامتر 'name' به همراه مقدار آن؛
  • در [8]، مرورگر به سرور اطلاع می‌دهد که در حال ارسال اطلاعات به آن است [urlencoded];
  • در [9]، پاسخ سرور HTML;

برای متوقف کردن برنامه:

1.6.7. ایجاد یک آرشیو قابل اجرا

امکان ایجاد یک آرشیو اجرایی خارج از اکلیپس وجود دارد. پیکربندی لازم در فایل [pom.xml] قرار دارد:


    <properties>
        <start-class>hello.Application</start-class>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
</build>
  • خطوط ۷–۱۰ پلاگینی را که آرشیو اجرایی را ایجاد می‌کند، تعریف می‌کنند؛
  • خط ۲ کلاس اجرایی پروژه را تعریف می‌کند؛

طبق مراحل زیر عمل کنید:

  • در [1]: یک هدف Maven را اجرا کنید؛
  • در [2]: دو هدف وجود دارد: [clean] برای حذف پوشه [target] از پروژه Maven، و [package] برای بازتولید آن؛
  • در [3]: پوشه تولیدشده [target] در این پوشه ایجاد خواهد شد؛
  • در [4]: هدف تولید می‌شود؛

توجه: برای موفقیت در تولید، JVM که توسط STS استفاده می‌شود باید یک JDK [Window / Preferences / Java / Installed JREs] باشد:

 

در لاگ‌های نمایش‌داده‌شده در کنسول، مهم است که پلاگین [spring-boot-maven-plugin] را در فهرست ببینید. این پلاگین آرشیو قابل اجرا را تولید می‌کند.

[INFO] --- spring-boot-maven-plugin:1.1.9.RELEASE:repackage (default) @ gs-serving-web-content ---

با استفاده از کنسول، به پوشهٔ تولیدشده بروید:


gs-serving-web-content-complete\target>dir
 ...

 Répertoire de D:\data\istia-1415\spring mvc\dvp\gs-serving-web-content-complete
\target

27/11/2014  17:07    <DIR>          .
27/11/2014  17:07    <DIR>          ..
27/11/2014  17:07    <DIR>          classes
27/11/2014  17:07    <DIR>          generated-sources
27/11/2014  17:07        13 419 551 gs-serving-web-content-0.1.0.jar
27/11/2014  17:07             3 522 gs-serving-web-content-0.1.0.jar.original
27/11/2014  17:07    <DIR>          maven-archiver
27/11/2014  17:07    <DIR>          maven-status
  • خط ۱۲: آرشیو تولید شده؛

این آرشیو به صورت زیر اجرا می‌شود:


gs-serving-web-content-complete\target>java -jar gs-serving-web-content-0.1.0.jar

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.1.9.RELEASE)

2014-11-27 17:14:50.439  INFO 8172 --- [           main] hello.Application                        : Starting Application on Gportpers3 with PID 8172 (D:\data\istia-1415\spring mvc\dvp\gs-serving-web-content-complete\target\gs-serving-web-content-0.1.0.jar started by ST in D:\data\istia-1415\spring mvc\dvp\gs-serving-web-content-complete\target)
2014-11-27 17:14:50.491  INFO 8172 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@12f4ec3a: startup date [Thu Nov 27 17:14:50 CET 2014]; root of context hierarchy

توجه: شما باید ابتدا هر سرویس وبی را که ممکن است در اکلیپس راه‌اندازی شده باشد، متوقف کنید (به صفحه 17 مراجعه کنید).

اکنون که برنامه وب راه‌اندازی شده است، می‌توان از طریق یک مرورگر به آن دسترسی داشت:

 

1.6.8. استقرار برنامه روی سرور Tomcat

در حالی که Spring Boot در حالت توسعه بسیار کاربردی است، یک برنامه در محیط تولید روی یک سرور Tomcat واقعی مستقر خواهد شد. در اینجا نحوه انجام آن آمده است:

فایل [pom.xml] را به شرح زیر ویرایش کنید:


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.springframework</groupId>
    <artifactId>gs-serving-web-content</artifactId>
    <version>0.1.0</version>
    <packaging>war</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.1.9.RELEASE</version>
    </parent>

    <dependencies>
        <!-- محیط Thymeleaf -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!-- تولید WAR -->
<!--         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency> -->
    </dependencies>

    <properties>
        <start-class>hello.Application</start-class>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-milestone</id>
            <url>https://repo.spring.io/libs-release</url>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>spring-milestone</id>
            <url>https://repo.spring.io/libs-release</url>
        </pluginRepository>
    </pluginRepositories>

</project>

تغییراتی باید در دو مکان اعمال شود:

  • خط ۹: باید مشخص کنید که یک آرشیو WAR (وب ARchive) باید تولید شود؛
  • خطوط ۲۴–۲۸: وابستگی به آرتفکت [spring-boot-starter-tomcat] را اضافه کنید. این آرتفکت شامل تمام کلاس‌های Tomcat در وابستگی‌های پروژه است؛
  • خط ۲۷: این آرتفکت [provided] است، به این معنی که آرشیوهای متناظر در WAR تولید شده گنجانده نخواهند شد. این آرشیوها در عوض روی سرور Tomcat که برنامه روی آن اجرا می‌شود، قرار خواهند گرفت؛

در واقع، اگر به وابستگی‌های فعلی پروژه نگاه کنیم، می‌توانیم ببینیم که وابستگی [spring-boot-starter-tomcat] از قبل موجود است:

  

بنابراین نیازی به افزودن آن به فایل [pom.xml] نیست. ما آن را برای مرجع به صورت کامنت‌گذاری کرده‌ایم.

نیاز است که برنامه وب نیز پیکربندی شود. در صورت عدم وجود فایل [web.xml]، این کار با استفاده از کلاسی که از [SpringBootServletInitializer] ارث می‌برد، انجام می‌شود:

  

کلاس [ApplicationInitializer] به شرح زیر است:


package hello;

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;

public class ApplicationInitializer extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

}
  • خط ۶: کلاس [ApplicationInitializer] از کلاس [SpringBootServletInitializer] ارث می‌برد؛
  • خط ۹: متد [configure] (خط ۸) مجدداً تعریف شده است؛
  • خط ۱۰: کلاسی که پروژه را پیکربندی می‌کند مشخص شده است؛

برای اجرای پروژه، مراحل زیر را دنبال کنید:

  • در [1]، پروژه را روی یکی از سرورهای ثبت‌شده در Eclipse در IDE اجرا کنید؛
  • در [2]، [Tomcat v8.0] را از فهرست بالا انتخاب کنید؛

پس از انجام این کار، می‌توانید به URL [http://localhost:8080/gs-rest-service/greeting/?name=Mitchell] در یک مرورگر دسترسی پیدا کنید:

 

توجه: بسته به نسخه‌های [tomcat] و [tc Server Developer]، این عملیات ممکن است با شکست مواجه شود. برای مثال، این مورد در [Apache Tomcat 8.0.3 et 8.0.15] رخ داد. در مثال بالا، نسخه‌ای از Tomcat که استفاده شد [8.0.9] بود.

اکنون می‌دانیم چگونه یک آرشیو WAR تولید کنیم. در ادامه، کار با Spring Boot و آرشیو اجرایی JAR آن را ادامه خواهیم داد.

1.7. پروژه دوم Spring: MVC

1.7.1. پروژهٔ نمایشی

  • در [1]، یکی از راهنماهای Spring را وارد می‌کنیم؛
  • در [2]، مثال [Rest Service] را انتخاب می‌کنیم؛
  • در [3]، پروژه Maven را انتخاب می‌کنیم؛
  • در [4]، نسخه نهایی راهنما را انتخاب می‌کنیم؛
  • در [5] تأیید می‌کنیم؛
  • در [6]، پروژه واردشده؛

سرویس‌های وب که از طریق استاندارد URL قابل دسترسی هستند و متن jSON را بازمی‌گردانند، اغلب به عنوان سرویس‌های REST (انتقال وضعیت REpresentational) شناخته می‌شوند. در این سند، من به سادگی سرویسی را که قصد ساخت آن را داریم، به عنوان یک سرویس وب / jSON نام می‌برم. یک سرویس زمانی RESTful نامیده می‌شود که از قوانین خاصی پیروی کند. من در پی رعایت این قوانین نبوده‌ام.

حال بیایید پروژهٔ واردشده را بررسی کنیم، با پیکربندی Maven آن شروع می‌کنیم.

1.7.2. پیکربندی Maven

فایل [pom.xml] به شرح زیر است:


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.springframework</groupId>
    <artifactId>gs-rest-service</artifactId>
    <version>0.1.0</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.1.9.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <properties>
        <start-class>hello.Application</start-class>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-releases</id>
            <url>https://repo.spring.io/libs-release</url>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>spring-releases</id>
            <url>https://repo.spring.io/libs-release</url>
        </pluginRepository>
    </pluginRepositories>
</project>
  • خطوط ۶–۸: ویژگی‌های پروژه Maven. یک برچسب [<packaging>] که نوع فایلی را که توسط ساخت Maven تولید می‌شود مشخص می‌کند، وجود ندارد. در غیاب این برچسب، از نوع [jar] استفاده می‌شود. بنابراین این برنامه یک برنامهٔ قابل اجرای مبتنی بر کنسول است، نه یک برنامهٔ وب، که در این صورت بسته‌بندی آن [war] خواهد بود؛
  • خطوط ۱۰–۱۴: پروژه Maven یک پروژه والد به نام [spring-boot-starter-parent] دارد. این پروژه بیشتر وابستگی‌های پروژه را تعریف می‌کند. این وابستگی‌ها ممکن است کافی باشند، که در این صورت هیچ وابستگی دیگری اضافه نمی‌شود، یا ممکن است کافی نباشند، که در این صورت وابستگی‌های missing اضافه می‌شوند؛
  • خطوط 17–20: آرتیفکت [spring-boot-starter-web] شامل کتابخانه‌های مورد نیاز برای یک پروژه Spring (MVC) از نوع سرویس وب است که در آن هیچ ویوی (view) تولید نمی‌شود. این آرتفکت شامل تعداد بسیار زیادی کتابخانه، از جمله کتابخانه‌های مربوط به یک سرور Tomcat تعبیه‌شده است. این اپلیکیشن بر روی همین سرور اجرا خواهد شد؛

کتابخانه‌های گنجانده‌شده در این پیکربندی بسیار زیاد هستند:

در بالا سه آرشیو مربوط به سرور Tomcat آمده است.

1.7.3. معماری یک سرویس Spring [web / jSON]

بیایید به یاد بیاوریم که Spring چگونه مدل MVC را پیاده‌سازی می‌کند:

پردازش یک درخواست مشتری به شرح زیر انجام می‌شود:

  1. درخواست URLهای درخواستی به شکل http://machine:port/contexte/Action/param1/param2/....?p1=v1&p2=v2&... هستند. [Dispatcher Servlet] کلاسی از Spring است که URLهای ورودی را مدیریت می‌کند. این کلاس، URL را به اکشنی که باید آن را پردازش کند، مسیریابی می‌کند. این اکشن‌ها متدهایی از کلاس‌های خاصی به نام [Contrôleurs] هستند. «C» در MVC در این مورد، رشته [Dispatcher Servlet, Contrôleur, Action] است. اگر هیچ اقدامی برای رسیدگی به URL ورودی پیکربندی نشده باشد، سرولت [Dispatcher Servlet] پاسخ خواهد داد که URL درخواستی یافت نشد (خطای 404 NOT FOUND);
  2. پردازش
  • عملکرد انتخاب‌شده می‌تواند از پارامترهای parami که توسط سرولت [Dispatcher Servlet] به آن ارسال شده است، استفاده کند. این پارامترها ممکن است از چندین منبع منشأ بگیرند:
    • مسیر [/param1/param2/...] از URL،
    • پارامترهای [p1=v1&p2=v2] از URL,
    • پارامترهای ارسال‌شده توسط مرورگر در درخواست آن؛
  • هنگام پردازش درخواست کاربر، ممکن است اقدام به لایه‌های [metier] و [2b] نیاز داشته باشد. پس از پردازش درخواست مشتری، ممکن است پاسخ‌های مختلفی ایجاد شود. یک مثال کلاسیک این است:
    • یک صفحهٔ خطا اگر درخواست نتوانست به‌درستی پردازش شود
    • در غیر این صورت، یک صفحه تأیید
  • اقدام دستور نمایش یک نمای مشخص را صادر می‌کند [3]. این نما داده‌هایی را که به عنوان مدل نما شناخته می‌شوند، نمایش می‌دهد. این همان M در MVC است. اقدام این مدل M [2c] را ایجاد کرده و به نمایش یک نما V [3] دستور می‌دهد؛
  1. پاسخ – نمای انتخاب‌شده V از مدل M ساخته‌شده توسط اقدام برای راه‌اندازی بخش‌های پویا از پاسخی که باید به کلاینت ارسال کند، استفاده می‌کند و سپس این پاسخ را ارسال می‌کند.

برای یک سرویس وب / jSON، معماری قبلی کمی تغییر می‌کند:

  • در [4a]، مدل—که یک کلاس جاوا است—توسط یک کتابخانه jSON به رشته jSON تبدیل می‌شود؛
  • در [4b]، این رشته jSON به مرورگر ارسال می‌شود؛

1.7.4. C

  

برنامه واردشده دارای کنترلر زیر است:


package hello;

import java.util.concurrent.atomic.AtomicLong;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetingController {

    private static final String template = "Hello, %s!";
    private final AtomicLong counter = new AtomicLong();

    @RequestMapping("/greeting")
    public Greeting greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
        return new Greeting(counter.incrementAndGet(), String.format(template, name));
    }
}
  • خط ۹: حاشیه‌نویسی [@RestController] کلاس [GreetingController] را به یک کنترل‌کننده Spring تبدیل می‌کند، یعنی متدهای آن برای رسیدگی به URL ثبت شده‌اند. ما نشانه‌ی مشابه [@Controller] را دیده‌ایم. نوع بازگشتی متدهای این کنترلر [String] بود که نام ویوی نمایشی بود. در اینجا، متفاوت است. متدهای یک کنترل‌کننده از نوع [@RestController] اشیایی را بازمی‌گردانند که برای ارسال به مرورگر سریال‌سازی می‌شوند. نوع سریال‌سازی انجام‌شده به پیکربندی Spring برای MVC بستگی دارد. در اینجا، آن‌ها به صورت jSON سریالیزه خواهند شد. وجود یک کتابخانه jSON در میان وابستگی‌های پروژه باعث می‌شود که Spring Boot به طور خودکار پروژه را به این شکل پیکربندی کند؛
  • خط 14: آناوتیشن [@RequestMappingURL را که متد آن را پردازش می‌کند، مشخص می‌نماید؛ در این مورد URL [/greeting
  • خط 15: ما قبلاً توضیح دادیم که anotation [@RequestParam] چیست. نتیجه بازگردانده شده توسط متد یک شیء از نوع [Greeting] است.
  • خط ۱۲: یک عدد صحیح بلند از نوع اتمی. این بدان معناست که از دسترسی همزمان پشتیبانی می‌کند. چندین نخ ممکن است بخواهند همزمان مقدار متغیر [counter] را افزایش دهند. این موضوع به درستی مدیریت خواهد شد. یک نخ تنها پس از آنکه نخ در حال تغییر آن، عملیات خود را تکمیل کرد، می‌تواند مقدار شمارنده را بخواند.

1.7.5. مدل M

مدل M تولید شده توسط روش قبلی، شیء زیر [Greeting] است:

  

package hello;

public class Greeting {

    private final long id;
    private final String content;

    public Greeting(long id, String content) {
        this.id = id;
        this.content = content;
    }

    public long getId() {
        return id;
    }

    public String getContent() {
        return content;
    }
}

تبدیل jSON این شیء، رشته {"id":n,"content":"text"} را ایجاد خواهد کرد. در نهایت، رشته jSON تولید شده توسط متد کنترل‌کننده به شکل زیر خواهد بود:

{"id":2,"content":"Hello, World!"}

یا

{"id":2,"content":"سلام، جان!"}

1.7.6. اجرا

  

کلاس [Application.java] کلاس اجرایی پروژه است. کد آن به شرح زیر است:


package hello;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan;

@ComponentScan
@EnableAutoConfiguration
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

ما قبلاً این کد را در مثال قبلی دیده‌ایم و توضیح داده‌ایم.

1.7.7. اجرای پروژه

بیایید پروژه را اجرا کنیم:

 

خروجی‌های کنسول زیر تولید می‌شوند:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.1.9.RELEASE)

2014-11-28 15:22:55.005  INFO 3152 --- [           main] hello.Application                        : Starting Application on Gportpers3 with PID 3152 (started by ST in D:\data\istia-1415\spring mvc\dvp-final\gs-rest-service)
2014-11-28 15:22:55.046  INFO 3152 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@62e136d3: startup date [Fri Nov 28 15:22:55 CET 2014]; root of context hierarchy
2014-11-28 15:22:55.762  INFO 3152 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'beanNameViewResolver': replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class]]
2014-11-28 15:22:56.567  INFO 3152 --- [           main] .t.TomcatEmbeddedServletContainerFactory : Server initialized with port: 8080
2014-11-28 15:22:56.738  INFO 3152 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2014-11-28 15:22:56.740  INFO 3152 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/7.0.56
2014-11-28 15:22:56.869  INFO 3152 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2014-11-28 15:22:56.870  INFO 3152 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1827 ms
2014-11-28 15:22:57.478  INFO 3152 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2014-11-28 15:22:57.481  INFO 3152 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2014-11-28 15:22:57.685  INFO 3152 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2014-11-28 15:22:57.879  INFO 3152 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/greeting],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public hello.Greeting hello.GreetingController.greeting(java.lang.String)
2014-11-28 15:22:57.884  INFO 3152 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2014-11-28 15:22:57.885  INFO 3152 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],methods=[],params=[],headers=[],consumes=[],produces=[text/html],custom=[]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest)
2014-11-28 15:22:57.906  INFO 3152 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2014-11-28 15:22:57.907  INFO 3152 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2014-11-28 15:22:58.231  INFO 3152 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2014-11-28 15:22:58.318  INFO 3152 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080/http
2014-11-28 15:22:58.319  INFO 3152 --- [           main] hello.Application                        : Started Application in 3.788 seconds (JVM running for 4.424)
  • خط ۱۳: سرور Tomcat روی پورت ۸۰۸۰ شروع به کار می‌کند (خط ۱۲);
  • خط ۱۷: سرولت [DispatcherServlet] موجود است؛
  • خط ۲۰: متد [GreetingController.greeting] کشف شده است؛

برای آزمایش برنامه وب، ما URL و [http://localhost:8080/greeting] را درخواست می‌کنیم:

 

رشتهٔ مورد انتظار jSON به‌درستی دریافت شد.

توجه: این مثال با مرورگر داخلی اکلیپس کار نکرد.

ممکن است ارزش داشته باشد که سربرگ‌های HTTP ارسال‌شده توسط سرور را بررسی کنیم. برای این کار، از افزونه کروم به نام [Advanced Rest Client] استفاده خواهیم کرد (رجوع کنید به ضمیمه‌ها، بند 9.6):

  • در [1]، URL درخواست‌شده؛
  • در [2]، از روش GET استفاده می‌شود؛
  • در [3]، پاسخ jSON است؛
  • در [4]، سرور اعلام کرد که در حال ارسال پاسخی با فرمت jSON است؛
  • در [5]، همان URL درخواست می‌شود، اما این بار با POST؛
  • در [7]، اطلاعات به شکل [urlencoded] به سرور ارسال می‌شود؛
  • در [6]، پارامتر 'name' به همراه مقدار آن؛
  • در [8]، مرورگر به سرور اطلاع می‌دهد که در حال ارسال اطلاعات [urlencoded] برای آن است؛
  • در [9]، پاسخ سرور jSON؛

1.7.8. ایجاد یک آرشیو قابل اجرا

همان‌طور که برای پروژه قبلی انجام دادیم، یک آرشیو قابل اجرا ایجاد می‌کنیم:

  • در [1]: ما یک هدف Maven را اجرا می‌کنیم؛
  • در [2]: دو هدف وجود دارد: [clean] برای حذف پوشه [target] از پروژه Maven، و [package] برای بازتولید آن؛
  • در [3]: پوشه تولیدشده [target] در این پوشه ایجاد خواهد شد؛
  • در [4]: هدف تولید می‌شود؛

در لاگ‌های نمایش‌داده‌شده در کنسول، مهم است که پلاگین [spring-boot-maven-plugin] را ببینید. این پلاگین است که آرشیو قابل اجرا را تولید می‌کند.

[INFO] --- spring-boot-maven-plugin:1.1.0.RELEASE:repackage (default) @ gs-rest-service ---

با استفاده از کنسول، به پوشهٔ تولیدشده بروید:


D:\Temp\wksSTS\gs-rest-service\target>dir
 ...
11/06/2014  15:30    <DIR>          classes
11/06/2014  15:30    <DIR>          generated-sources
11/06/2014  15:30        11 073 572 gs-rest-service-0.1.0.jar
11/06/2014  15:30             3 690 gs-rest-service-0.1.0.jar.original
11/06/2014  15:30    <DIR>          maven-archiver
11/06/2014  15:30    <DIR>          maven-status
...
  • خط ۵: آرشیو تولید شده؛

این آرشیو به شرح زیر اجرا می‌شود:


D:\Temp\wksSTS\gs-rest-service-complete\target>java -jar gs-rest-service-0.1.0.jar

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.1.0.RELEASE)

2014-06-11 15:32:47.088  INFO 4972 --- [           main] hello.Application
                  : Starting Application on Gportpers3 with PID 4972 (D:\Temp\wk
sSTS\gs-rest-service-complete\target\gs-rest-service-0.1.0.jar started by ST in
D:\Temp\wksSTS\gs-rest-service-complete\target)
...

توجه: شما باید ابتدا هر سرویس وبی را که ممکن است در اکلیپس راه‌اندازی شده باشد، متوقف کنید (به بخش 1.6.6 مراجعه کنید).

اکنون که برنامه وب راه‌اندازی شده است، می‌توانید با استفاده از یک مرورگر به آن دسترسی پیدا کنید:

 

1.7.9. راه‌اندازی برنامه روی سرور Tomcat

همان‌طور که برای پروژه قبلی انجام دادیم، فایل [pom.xml] را به شرح زیر تغییر می‌دهیم:


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.springframework</groupId>
    <artifactId>gs-rest-service</artifactId>
    <version>0.1.0</version>
    <packaging>war</packaging>

    ...
</project>
  • خط ۹: باید مشخص کنیم که قصد داریم یک آرشیو WAR (وب ARchive) ایجاد کنیم؛

برنامهٔ وب نیز باید پیکربندی شود. در صورت عدم وجود فایل [web.xml]، این کار با استفاده از کلاسی که از [SpringBootServletInitializer] ارث می‌برد، انجام می‌شود:

  

کلاس [ApplicationInitializer] به شرح زیر است:


package hello;

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;

public class ApplicationInitializer extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

}
  • خط ۶: کلاس [ApplicationInitializer] از کلاس [SpringBootServletInitializer] ارث می‌برد؛
  • خط ۹: متد [configure] بازتعریف شده است (خط ۸);
  • خط ۱۰: کلاسی که پروژه را پیکربندی می‌کند مشخص شده است؛

برای اجرای پروژه، مراحل زیر را دنبال کنید:

  • در [1-2]، پروژه را روی یکی از سرورهای ثبت‌شده در Eclipse IDE اجرا کنید؛

پس از انجام این کار، می‌توانید URL [http://localhost:8080/gs-rest-service/greeting/?name=Mitchell] را در یک مرورگر درخواست کنید:

 

1.8. Conclusion

ما دو نوع پروژه Spring را معرفی کرده‌ایم:

  • یک پروژه که در آن برنامه وب یک جریان HTML را به مرورگر ارسال می‌کند. این جریان توسط موتور نما [Thymeleaf] تولید می‌شود؛
  • یک پروژه که در آن وب‌اپلیکیشن یک جریان jSON را به مرورگر ارسال می‌کند؛

در مورد اول، پروژه به دو وابستگی Maven نیاز دارد:


    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.1.9.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
</dependencies>

در مورد دوم، وابستگی‌های Maven به شرح زیر است:


    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.1.9.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
</dependencies>

وابستگی‌هایی که توسط این پیکربندی‌ها به‌صورت آبشاری ایجاد می‌شوند بسیار زیاد هستند و بسیاری از آن‌ها غیرضروری‌اند. هنگام استقرار برنامه، از یک پیکربندی دستی Maven استفاده خواهیم کرد که تنها شامل وابستگی‌های لازم برای پروژه است.

اکنون به مبانی برنامه‌نویسی وب بازمی‌گردیم و دو مفهوم اساسی را معرفی می‌کنیم:

  • گفتگوی HTTP (پروتکل انتقال HyperText) بین یک مرورگر و یک برنامه وب؛
  • HTML (HyperText زبان نشانه‌گذاری)، که مرورگر آن را برای نمایش صفحه‌ای که دریافت کرده است، تفسیر می‌کند؛