در این مقاله، ما ابتدا قصد داریم به یک معرفی سریع از فریمورک Spark جاوا بپردازیم. Spark Framework یک فریمورک توسعه سریع وب (rapid development web) است که از فریمورک Sinatra برای زبان برنامهنویسی Ruby الهام گرفته و همچنین بر اساس فلسفهی Java 8 Lambda Expression ساخته شده است و نسبت به اکثر applicationهای نوشته شده در فریمورکهای جاوا چکیدهتر و مختصرتر است.
اگر که شما بخواهید تجربهای مانند Node.js در هنگام توسعه API وب و یا میکروسرویسهایی (microservices) در جاوا داشته باشید، انتخاب این فریمورک گزینهی خوبی است. با فریمورک Spark، شما میتوانید در کمتر از ده خط کد یک REST API آماده برای سرویس JSON داشته باشید.
ما در ادامهی این مقاله یک شروع سریع با مثال “Hello World” و به دنبال آن یک REST API ساده خواهیم داشت.
آن چه در این مقاله خواهید خواند:
Dependencyهای maven
-
Spark framework
Dependency Maven زیر را در pom.xml خود قرار دهید:
شما میتوانید آخرین نسخهی فریمورک Spark را در Maven Central پیدا کنید.
-
کتابخانهی (library) Gson
در قسمتهای مختلف مثال، ما از library Gson برای انجام عملیات JSON استفاده خواهیم کرد. برای گنجاندن Gson در پروژهی خود، این dependency را در pom.xml خود قرار دهید:
همچنین شما میتوانید آخرین نسخهی Gson را نیز در Maven Central پیدا کنید.
شروع کار با فریم ورک Spark
بیایید ابتدا نگاهی به بلوکهای اصلی سازندهی یک application Spark بیندازیم و یک web service سریع را شرح دهیم.
-
Routeها
سرویسهای وب (web service) مرتبط با فریمورکSpark جاوا، بر اساس routeها و گردانندههای آنها (handler) ساخته شدهاند. Routeها عناصر اصلی و ضروری در فریمورک Spark هستند. طبق documentها، هر route از سه قطعهی ساده تشکیل شده است: یک verb، یک path (مسیر) و یک callback.
- Verb یک روش مرتبط با یک متد HTTP است. روشهای verb عبارتند از: دریافت (get)، ارسال (post)، قرار دادن (put)، حذف (delete)، head، ردیابی (trace)، اتصال (connect) و optionها
- Path یا مسیر (که route path نیز نامیده میشود) تعیین میکند که route به کدام URI (ها) باید توجه کند و به آن پاسخ بدهد.
- Callback یک تابع گرداننده (handler) است که برای یک verb و یک path مشخص فراخوانده میشود تا پاسخی به درخواست HTTP مربوطه ایجاد کند و پاسخی نیز بازگرداند. یک callback، یک request object و response object را به عنوان آرگومان در نظر میگیرد.
در اینجا ما ساختار اصلی یک route را نشان میدهیم که از فعل (verb) get استفاده میکند:
Hello World API
یایید حال یک web service ساده ایجاد کنیم که دارای دو route برای درخواستهای GET است و پیامهای “Hello” را در پاسخ جواب میدهد. این routeها از متد get استفاده میکنند که یک import ثابت از کلاس spark.Spark است:
اولین آرگومان متد get، path برای route است. Route اول شامل یک path ثابت است که تنها یک URI را نشان میدهد (“/hello”).
دومین path route (“/hello/:name”) حاوی یک placeholder برای پارامتر “name” است، همانطور که با یک دو نقطه (“:”) به عنوان پیشوند پارامتر مشخص می شود. این route در پاسخ به درخواستهای GET به URLهایی مثل «hello/joe/ » و «hello/mary/» فراخوانی میشود.
دومین آرگومان برای متد get یک expression لامبدا (lambda expression) است که مزهی برنامهنویسی کاربردی را به این فریمورک میدهد.
Expression lambda دارای درخواست و پاسخ (request و response) به عنوان آرگومان است و به برگشت پاسخ کمک میکند. همانطور که بعداً در این آموزش خواهیم دید، ما کنترل گر منطقی (controller logic) خود را در expression lambda برای routeهای REST API قرار میدهیم.
-
تست Hello World API
پس از اجرای کلاس HelloWorldService به عنوان یک کلاس معمولی جاوا، شما می توانید با استفاده از routeهای تعریف شده با متد get که در بالاتر به آنها اشاره شد، به سرویس پورت پیش فرض 4567 آن دسترسی داشته باشید.
بیایید ابتدا به درخواست (request) و پاسخ (response) برای route اول نگاه کنیم:
درخواست (request):
پاسخ (response):
حال بیایید route دوم را با pass کردن پارامتر name در مسیر آن آزمایش کنیم:
درخواست (request):
پاسخ (response):
ببینید که چگونه قرار دادن متن “baeldung” در URI برای مطابقت با الگوی (pattern) route “/hello/:name” استفاده شده است. (که در واقع این کار باعث فراخوانی تابع callback handler route دوم میشود.)
طراحی یک سرویس RESTful
در این قسمت، ما یک وب سرویس (web service) ساده REST برای entity کاربر زیر طراحی می کنیم:
-
Routeها
بیایید ابتدا routeهایی که API ما را تشکیل میدهند، فهرست کنیم:
- GET /users – دریافت لیست همهی کاربران
- GET /users/:id – دریافت کاربر با شناسهی داده شده
- POST /users/:id – اضافه کردن یک کاربر
- PUT /users/:id – ویرایش یک کاربر خاص
- OPTIONS /users/:id – بررسی اینکه آیا کاربری با شناسهی داده شده وجود دارد یا خیر
- DELETE /users/:id – حذف یک کاربر خاص
-
User Service
در اینجا interface UserService ارائه شده است، که عملیات CRUD را برای entity کاربر معرفی میکند:
برای اهداف نمایشی، ما یک پیادهسازی (implementation) Map از این interface UserService را در کد GitHub برای شبیهسازی persistenceارائه میکنیم. شما همچنین می توانید پیاده سازی خود را با database و لایهی persistence مورد نظر خود انجام دهید.
-
ساختار پاسخ (response) JSON
در ادامه، ساختار JSON پاسخهای مورد استفاده در سرویس REST ما آمده است:
فیلد وضعیت (status field) میتواند یا SUCCESS و یا ERROR باشد. فیلد داده (data field) حاوی نمایش JSON از دادههای برگشتی است، از قبیل یک کاربر و یا مجموعهای از کاربران.
هنگامی که هیچ دادهای بازگردانده نمیشود، و یا اگر وضعیت (status)، ERROR است، ما field پیام (message field) را پر می کنیم تا دلیلی را برای خطا و یا عدم برگشت دادهها بیان کنیم.
حال بیایید ساختار JSON بالا را با استفاده از کلاس جاوا نشان دهیم:
که در آن StatusResponse یک enum است که به صورت زیر تعریف شده است:
پیاده سازی (Implementing) سرویس های RESTful
حال، اجازه دهید routeها و گردانندهها (handler) را برای REST API خود پیادهسازی (Implementing) کنیم.
-
ایجاد گردانندهها (handler)
کلاس جاوای زیر شامل routeهایی برای API ما، از جمله verbها و pathها و یک طرح کلی از handlerها برای هر route است:
ما در ادامه پیادهسازی کامل هر route handler را در زیر بخش های مرتبط نشان خواهیم داد.
-
افزودن کاربر
در زیر handler (گرداننده) post method responce وجود دارد که وظیفهی اضافه کردن کاربر را بر عهده دارد:
توجه: در این نمونه، نمایش (representation) JSON object کاربر به عنوان بدنه خام (raw body) درخواست POST، pass می شود.
بیایید حال route را آزمایش کنیم:
درخواست (request):
پاسخ (response):
-
دریافت (get) همهی کاربران
در دستور زیر، گرداننده (handler) پاسخ متد get است که همهی کاربران را از UserService بر میگرداند:
حال، بیایید route را آزمایش کنیم:
درخواست (request):
پاسخ (respond):
-
دریافت کاربر به وسیلهی شناسه
در دستور پایین، گرداننده (handler) پاسخ متد get است که یک کاربر را با شناسه (id) داده شده باز میگرداند:
حال بیایید route را تست کنیم:
درخواست (request):
پاسخ (response):
-
ویرایش کردن (edit) یک کاربر:
در کد زیر، گرداننده، پاسخ متد put است، که کاربر دارای شناسه (id) ارائه شده را در الگوی مسیر (route pattern) ویرایش (edit) می کند:
توجه: در این نمونه، دادهها در بدنهی خام (raw body) یک درخواست POST به عنوان یک object JSON، pass میشوند، که نام ویژگیهای آن با فیلدهای object کاربر برای ویرایش (edit) مطابقت دارد.
بیایید حال route را آزمایش کنیم:
درخواست (request):
پاسخ (response):
-
حذف (delete) یک کاربر
در کد زیر، گرداننده (handler) پاسخ متد “حذف کردن (delete)” است، که کاربر را با شناسهی داده شده حذف می کند:
حال، وقت آزمایش کردن route است:
درخواست (request):
پاسخ (response):
-
بررسی کردن اینکه آیا کاربر وجود دارد یا خیر
روش option، انتخاب خوبی برای بررسی conditional است. در ادامه، گرداننده (handler) پاسخ متد option وجود دارد که وظیفهی بررسی کردن وجود کاربری با شناسهی (id) داده شده را بر عهده دارد:
حالا باید route را تست کنیم:
درخواست (request):
پاسخ (response):
فریمورک spark، عمدتاً برای تولید میکروسرویسها (microservice) در زبان برنامهنویسی جاوا promote می شود. توسعه دهندگان Node.js با دانش جاوا، که می خواهند از libraryهای ساخته شده بر روی libraryهای JVM استفاده کنند، در استفاده از این فریمورک بسیار احساس راحتی میکنند.