4. اجرای برنامه
اکنون میخواهیم برنامه را خارج از IDE و STS (برای سرور) و WebStorm (برای کلاینت) اجرا کنیم.
4.1. راهاندازی سرویس وب روی سرور Tomcat
در بخش 2.11.9 دیدیم چگونه یک آرشیو WAR برای Tomcat ایجاد کنیم. در اینجا این فرایند را تکرار خواهیم کرد. ابتدا، برای حفظ پروژهٔ موجود، پروژهٔ Eclipse با نام [rdvmedecins-webapi-v3] را بهعنوان [rdvmedecins-webapi-v4] کپی میکنیم.
![]() |
فایل [pom.xml] به شرح زیر تغییر داده میشود:
<modelVersion>4.0.0</modelVersion>
<groupId>istia.st.spring4.mvc</groupId>
<artifactId>rdvmedecins-webapi-v4</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>rdvmedecins-webapi-v3</name>
<description>Gestion de RV Médecins</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.0.0.RELEASE</version>
</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-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>istia.st.spring4.rdvmedecins</groupId>
<artifactId>rdvmedecins-metier-dao-v2</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
تغییراتی باید در دو مکان اعمال شود:
- خط ۵: باید مشخص کنید که یک آرشیو WAR (وب ARchive) باید تولید شود؛
- خطوط ۲۳–۲۷: وابستگی به آرتیفکت [spring-boot-starter-tomcat] باید اضافه شود. این آرتیفکت شامل تمام کلاسهای Tomcat در وابستگیهای پروژه است؛
- خط ۲۶: این آرتفکت [provided] است، به این معنی که آرشیوهای متناظر در WAR تولید شده گنجانده نخواهند شد. این آرشیوها در عوض روی سرور Tomcat که برنامه روی آن اجرا میشود، قرار خواهند گرفت؛
برنامه وب نیز باید پیکربندی شود. در صورت عدم وجود فایل [web.xml]، این کار با استفاده از کلاسی که از [SpringBootServletInitializer] ارث میبرد، انجام میشود:
![]() |
کلاس [ApplicationInitializer] به شرح زیر است:
package rdvmedecins.web.config;
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(AppConfig.class);
}
}
- خط ۶: کلاس [ApplicationInitializer] از کلاس [SpringBootServletInitializer] ارث میبرد؛
- خط ۸: متد [configure] بازتعریف شده است (خط ۷);
- خط ۹: کلاس [AppConfig] که پروژه را پیکربندی میکند، ارائه شده است؛
پس از انجام این کار، ممکن است لازم باشد پروژه Maven را بهروزرسانی کنید (من مجبور شدم این کار را انجام دهم): [clic droit sur projet / Maven / Update project] یا [Alt-F5].
برای اجرای پروژه، مراحل زیر را دنبال کنید:
![]() |
- برای [1]، پروژه را روی یکی از سرورهای ثبتشده در پروژه Eclipse با شناسه IDE اجرا کنید؛
- در [2]، [tc Server Developer] را که گزینه پیشفرض است، انتخاب کنید. این یک نسخه از Tomcat است؛
نتیجهٔ زیر بهدست میآید:
![]() |
این امر قابل انتظار است. به یاد داشته باشید که سرویس وب، متدهای URL یا [/] را ندارد. وقتی URL یا [/getAllMedecins] را امتحان میکنید، پاسخ زیر را دریافت میکنید:
![]() |
این طبیعی است. سرویس وب محافظت شده است.
حالا بیایید کلاینت [rdvmedecins-angular-v2] را در WebStorm راهاندازی کنیم:
![]() |
در [1]، ما URL را برای سرویس وب جدید [http://localhost:8080/rdvmedecins-webapi-v4] تنظیم میکنیم. نتیجه زیر را دریافت میکنیم:

روشهای مختلفی برای اجرای برنامه خارج از محیط IDE STS وجود دارد. در اینجا یکی از این روشها آورده شده است.
نسخهای از Tomcat [http://tomcat.apache.org/download-80.cgi] (ژوئیه ۲۰۱۴) را دانلود کنید:
![]() |
نسخه فشردهشده را در [1] انتخاب کرده و آن را در [2] از حالت فشرده خارج کنید. به STS بازگردید:
![]() |
- در برگه [Servers]، روی برنامه [rdvmedecins-webapi-v4] کلیک راست کرده و گزینه [Browse Deployment Location] را انتخاب کنید؛
- در [4]: پوشه [rdvmedecins-webapi-v4] را کپی کنید؛
![]() |
- در [5]، پوشه [rdvmedecins-webapi-v4] را در پوشه [webapps] در Tomcat جایگذاری کنید؛
- در [6]، فایل اسکریپت [startup.bat] را اجرا کنید (ابتدا سرور Tomcat یکپارچه در STS باید متوقف شود). یک پنجره DOS باز میشود تا لاگهای Tomcat را نمایش دهد. این لاگها باید نشان دهند که برنامه [rdvmedecins-webapi-v4] راهاندازی شده است.
برای بررسی این موضوع، کلاینت Angular با نام [rdvmedecins-angular-v2] را دوباره در WebStorm اجرا کنید:
![]() |
در [1]، ما URL را برای سرویس وب جدید [http://localhost:8080/rdvmedecins-webapi-v4] تنظیم میکنیم. نتیجه زیر را به دست میآوریم:

4.2. راهاندازی کلاینت Angular روی سرور Tomcat
اکنون که سرویس وب روی تامکت مستقر شده است، کلاینت Angular را نیز روی یک سرور مستقر خواهیم کرد. این سرور میتواند همان سروری باشد که در حال حاضر میزبان سرویس وب است. ما این رویکرد را در پیش میگیریم.
ابتدا، کلاینت [rdvmedecins-angular-v2] را به عنوان [rdvmedecins-angular-v3] کپی کرده و تغییرات زیر را اعمال میکنیم:
![]() |
- به [1]؛ همه چیز به پوشهای به نام [app] منتقل شده است؛
- در [1]، پوشه [bower-components] را که شامل کتابخانههای مختلف CSS و JS مورد نیاز برای پروژه بود، حذف کردهایم. تمام این موارد به پوشه [lib] [2] کپی شدهاند؛
- در [1]، نام فایل [app.html] به [index.html] تغییر یافت؛
فایل [index.html] برای انعکاس تغییرات در مسیرهای منابع مورد استفاده اصلاح شده است:
<!DOCTYPE html>
<html ng-app="rdvmedecins">
<head>
<title>RdvMedecins</title>
...
<!-- CSS -->
...
<link href="lib/bootstrap-theme.min.css" rel="stylesheet"/>
<link href="lib/bootstrap-select.min.css" rel="stylesheet"/>
</head>
<!--کنترلکننده [appCtrl]، قالب [app] -->
<body ng-controller="appCtrl">
<div class="container">
...
</div>
<!--هسته Bootstrap JavaScript ================================================== -->
<script type="text/javascript" src="lib/jquery.min.js"></script>
<script type="text/javascript" src="lib/bootstrap.min.js"></script>
<script type="text/javascript" src="lib/bootstrap-select.min.js"></script>
<script type="text/javascript" src="lib/footable.js"></script>
<!-- AngularJS -->
<script type="text/javascript" src="lib/angular.min.js"></script>
<script type="text/javascript" src="lib/ui-bootstrap-tpls.min.js"></script>
<script type="text/javascript" src="lib/angular-route.min.js"></script>
<script type="text/javascript" src="lib/angular-translate.min.js"></script>
<script type="text/javascript" src="lib/angular-base64.min.js"></script>
<!-- ماژولها -->
...
<!-- خدمات -->
...
<!-- دستورالعملها -->
...
<!-- controllers -->
....
</body>
</html>
علاوه بر این، کنترلکننده [loginCtrl] اصلاح شده است تا به سرور صحیح اشاره کند، بنابراین کاربر نیازی به وارد کردن URL خود ندارد:
// اعتبارنامهها
app.serverUrl = "http://localhost:8080/rdvmedecins-webapi-v4";
app.username = "admin";
app.password = "admin";
اکنون که این کار انجام شد، بیایید فایل [index.html] را اجرا کنیم:
![]() | ![]() |
سپس بیایید به سرویس وب متصل شویم. باید کار کند. پس از تأیید این موضوع، بیایید سرور Tomcat را متوقف کنیم. ما قصد داریم از سرور داخلی موجود در STS مجدداً استفاده کنیم.
در STS، کل محتویات پوشه [rdvmedecins-angular-v3/app] را در پوشه [webapp] داخل پروژه [rdvmedecins-webapi-v4] کپی کنید (زبانهی Navigator) [1]:
![]() |
پس از انجام این کار، بیایید [2] را از STS راهاندازی کنیم، سپس سرور VMware را از STS راهاندازی کرده و سپس URL [http://localhost:8080/rdvmedecins-webapi-v4/app/index.html] را درخواست کنیم:
![]() |
ما با [3] مشکل مجوز داریم. این چندان تعجبآور نیست، چون سرویس وب را ایمن کردهایم. باید مشخص کنیم که دسترسی به فایل [/app/index.html] بدون محدودیت است. بیایید به اِکلِپس برگردیم:
![]() |
به یاد داشته باشید که حقوق دسترسی در کلاس [SecurityConfig] تعریف شدهاند. بیایید آن را به شرح زیر تغییر دهیم:
@Override
protected void configure(HttpSecurity http) throws Exception {
// CSRF
http.csrf().disable();
// رمز عبور از طریق هدر Authorisation: Basic xxxx ارسال میشود
http.httpBasic();
// روش HTTP OPTIONS باید برای همه مجاز باشد
http.authorizeRequests() //
.antMatchers(HttpMethod.OPTIONS, "/", "/**").permitAll();
//پوشه [app] برای همه قابل دسترسی است
http.authorizeRequests() //
.antMatchers(HttpMethod.GET, "/app", "/app/**").permitAll();
// فقط نقش ADMIN میتواند از برنامه استفاده کند
http.authorizeRequests() //
.antMatchers("/", "/**") // تمام URL
.hasRole("ADMIN");
}
- خطوط ۱۱–۱۲: ما به همه اجازه میدهیم پوشه [app] و محتویات آن را بخوانند. برای این کار، از مثال خطوط قبلی پیروی میکنیم.
اکنون، سرور Tomcat را برای STS مجدداً راهاندازی کنید، سپس دوباره URL و [http://localhost:8080/rdvmedecins-webapi-v4/app/index.html] را درخواست کنید:

این بار، کار میکند.
4.3. سربرگهای CORS
شاید به یاد داشته باشید که ما برای رسیدگی به سربرگهای CORS به سختی زیادی افتادیم. در مثال قبلی:
- سرویس وب در URL [http://localhost:8080/rdvmedecins-webapi-v4] قرار دارد؛
- کلاینت HTML در URL [http://localhost:8080/rdvmedecins-webapi-v4/app] قرار دارد؛
بنابراین کلاینت HTML و سرویس وب روی یک سرور واحد، [http://localhost:8080]، قرار دارند. بنابراین هیچ تداخلی با CORS وجود ندارد، زیرا این تداخلها تنها زمانی رخ میدهند که کلاینت و سرور در دامنه یکسان نباشند. ما باید بتوانیم این موضوع را تأیید کنیم. بیایید به STS بازگردیم:
![]() |
اینکه آیا سربرگهای CORS تولید شوند یا نه، توسط یک بولین تعریفشده در کلاس [ApplicationModel] کنترل میشود:
//دادههای پیکربندی
private boolean CORSneeded = true;
ما مقدار بولین بالا را روی false تنظیم کردیم، سرویس وب را مجدداً راهاندازی کردیم و دوباره URL [http://localhost:8080/rdvmedecins-webapi-v4/app/index.html] را درخواست کردیم. میتوانیم ببینیم که برنامه در حال کار است.
4.4. استقرار کلاینت Angular روی تبلت اندروید
ابزار [Phonegap] [http://phonegap.com/] به شما امکان میدهد یک فایل اجرایی برای دستگاههای موبایل (اندروید، IoS، ویندوز ۸، ...) از یک برنامه HTML / JS / CSS. روشهای مختلفی برای این کار وجود دارد. ما از سادهترین روش استفاده میکنیم: یک ابزار آنلاین موجود در وبسایت PhoneGap [http://build.phonegap.com/apps].
![]() |
- قبل از [1]، ممکن است لازم باشد یک حساب کاربری ایجاد کنید؛
- در [1]، کار را آغاز میکنیم؛
- در [2]، یک طرح رایگان را انتخاب کنید که فقط یک اپلیکیشن PhoneGap را مجاز میسازد؛
![]() |
- در [3]، برنامه فشردهشده [4] را دانلود کنید (پوشه [app] که در بخش 4.2 ایجاد شده، فشرده شده است)؛
![]() |
- در [5]، برای برنامه یک نام انتخاب کنید؛
- در [6]، برنامه را بسازید. این کار ممکن است تا ۱ دقیقه طول بکشد. لطفاً منتظر بمانید تا آیکونهای پلتفرمهای مختلف موبایل نشان دهند که ساخت برنامه کامل شده است؛
![]() |
- فقط باینری اندروید [7] و باینری ویندوز [8] تولید شدهاند؛
- برای دانلود باینری اندروید، روی [7] کلیک کنید؛
![]() |
- در [9]، باینری دانلود شده [apk]؛
یک شبیهساز [GenyMotion] برای یک تبلت اندروید را راهاندازی کنید (به بخش 6.4 مراجعه کنید):
![]() |
در بالا، ما یک شبیهساز تبلت با اندروید نسخه API 16 را راهاندازی میکنیم. پس از راهاندازی شبیهساز،
- با کشیدن اسلایدر (در صورت وجود) به کنار و سپس رها کردن آن، آن را باز کنید؛
- با استفاده از ماوس، فایل [PGBuildApp-debug.apk] را که دانلود کردهاید بکشید و در روی شبیهساز رها کنید. سپس نصب و اجرا خواهد شد؛
![]() |
شما باید URL را به [1] تغییر دهید. برای انجام این کار، در یک پنجرهٔ فرمان، دستور [ipconfig] (خط ۱ زیر) را تایپ کنید که آدرسهای مختلف IP را روی دستگاه شما نمایش خواهد داد:
C:\Users\Serge Tahé>ipconfig
Configuration IP de Windows
Carte réseau sans fil Connexion au réseau local* 15 :
Statut du média. . . . . . . . . . . . : Média déconnecté
Suffixe DNS propre à la connexion. . . :
Carte Ethernet Connexion au réseau local :
Suffixe DNS propre à la connexion. . . : ad.univ-angers.fr
Adresse IPv6 de liaison locale. . . . .: fe80::698b:455a:925:6b13%4
Adresse IPv4. . . . . . . . . . . . . .: 172.19.81.34
Masque de sous-réseau. . . . . . . . . : 255.255.0.0
Passerelle par défaut. . . . . . . . . : 172.19.0.254
Carte réseau sans fil Wi-Fi :
Statut du média. . . . . . . . . . . . : Média déconnecté
Suffixe DNS propre à la connexion. . . :
...
آدرس وایفای IP (خطوط ۶–۹) یا آدرس شبکه محلی IP (خطوط ۱۱–۱۷) را یادداشت کنید. سپس از این آدرس IP در بخش URL وبسرور استفاده کنید:
![]() |
پس از انجام این کار، به سرویس وب متصل شوید:
![]() |
برنامه را روی شبیهساز آزمایش کنید. باید کار کند. در سمت سرور، ممکن است سربرگهای CORS را در کلاس [ApplicationModel] مجاز کنید یا نکنید:
// دادههای پیکربندی
private boolean CORSneeded = false;
این موضوع برای اپلیکیشن اندروید اهمیتی ندارد. این اپلیکیشن در مرورگر اجرا نمیشود. با این حال، نیاز به هدرهای CORS از سمت مرورگر است، نه از سمت سرور.
4.5. راهاندازی کلاینت Angular روی شبیهساز گوشی هوشمند اندروید
ما مرحله قبلی را با استفاده از شبیهساز گوشی هوشمند تکرار میکنیم. میخواهیم بررسی کنیم که کلاینت ما در صفحههای کوچک چگونه رفتار میکند:
![]() |
- در [1]، یک شبیهساز گوشی هوشمند را راهاندازی میکنیم؛
- در [2] و [3]، نوار ناوبری به یک منو جمع شده است؛
![]() |
- در [4]، شما وارد میشوید؛
- در [5]، فهرست و تقویم به جای قرار گرفتن در کنار هم، یکی زیر دیگری قرار دارند؛
![]() |
- در [6]، دفترچه یادداشت درخواست میشود؛
- در [7]، از آنجا که صفحه نمایش خیلی کوچک است، بخشی از بازههای زمانی پنهان میشود. این مشکل توسط کتابخانه [footable] حل شد؛
![]() |
- در [8]، همان نمای قبلی، اما این بار با یک قرار ملاقات.
در مجموع، اپلیکیشن ما کاملاً با گوشی هوشمند سازگار است. قطعاً میتوانست بهتر باشد، اما همچنان قابل استفاده است.





























