خب ببین، Maven یه ابزار خیلی خفنه که کمک میکنه پروژههات رو تو جاوا راحتتر مدیریت کنی. مثلاً فرض کن یه پروژه داری و هر بار باید خودت دستی:
کدها رو کامپایل کنی،
وابستگیها (Dependencies) مثل کتابخونهها رو پیدا کنی و به پروژه اضافه کنی،
تست کنی ببینی کدت درست کار میکنه یا نه،
و در نهایت یه فایل اجرایی (Executable File) بسازی.
همه اینا رو اگه بخوای دستی انجام بدی، کلی وقتت گرفته میشه و اعصاب خوردکن هم هست، درسته؟
اینجاست که Maven وارد عمل میشه و همه این کارا رو برات خودکار انجام میده. یعنی فقط یه سری اطلاعات بهش میدی، خودش میره کارا رو انجام میده و پروژه رو آماده میکنه.
خب، Maven چه کمکی میکنه؟
مثال بزنم: فرض کن یه پروژه داری که نیاز داره از یه کتابخونه مثل JUnit برای تست کردن استفاده کنی. به جای اینکه بری دستی این کتابخونه رو پیدا کنی و اضافه کنی، فقط کافیه تو یه فایل به اسم pom.xml بگی این کتابخونه رو میخوای. Maven خودش میره از اینترنت دانلودش میکنه و به پروژهت اضافه میکنه.
دو نوع ابزار ساخت پروژه داریم
ابزارهای دستوری (Imperative)
ابزارهای اعلانی (Declarative)
ابزار دستوری چیه؟
مثلاً یه ابزار قدیمی به اسم Ant داریم که دستوری بود. این یعنی باید بهش میگفتی:
چی رو کامپایل کنه،
کجا فایلها رو ذخیره کنه،
و همه کارا رو دقیقاً چطور انجام بده.
اما ابزار اعلانی چطور؟
حالا Maven و Gradle اعلانی هستن. یعنی خودشون میدونن باید چیکار کنن. تو فقط میگی:
این پروژهم این وابستگیها (Dependencies) رو میخواد،
این فایلها رو نیاز دارم، و بقیهشو خودش انجام میده.
Maven چرا اینقدر خوبه؟
پروژهت رو به یه شکل استاندارد درست میکنه.
مدیریت وابستگیهاش عالیه، یعنی هرچی لازم داشته باشی خودش برات میاره.
اگه با یه پروژه Maven کار کنی، با هر پروژه Maven دیگهای هم راحت کار میکنی. چون همهشون ساختار مشابهی دارن.
بریم سراغ فایل pom.xml
این فایل مثل مغز Maven هست. هر اطلاعاتی که لازم داشته باشه، اینجا تو این فایل مینویسی. مثلاً:
اسم پروژه
نسخه پروژه
کتابخونههایی که نیاز داری
یه نکته: pom.xml مخفف Project Object Model هست.
ساختار پروژه تو Maven چطوریه؟
پروژه Maven چه شکلیه؟
وقتی یه پروژه رو با Maven میسازی، یه ساختار پیشفرض داره که به این شکله:
وقتی یه پروژه رو با Maven میسازی، یه ساختار پیشفرض داره که همیشه به این شکله:
src/main/java این پوشه جاییه که کد اصلی پروژهت رو مینویسی. مثلاً اگه داری یه اپلیکیشن درست میکنی، فایلهای مربوط به منطق برنامه (Logic) تو اینجا قرار میگیرن.
src/test/java اینجا کدهای مربوط به تستهات قرار میگیره. مثلاً اگه بخوای چک کنی که برنامهت درست کار میکنه یا نه، این تستها رو تو این پوشه مینویسی.
target folder وقتی پروژهت رو کامپایل میکنی، همه فایلهای خروجی مثل فایل اجرایی (مثلاً JAR) یا گزارش تستها، اینجا ذخیره میشن.
pom.xml این فایل هم توی ریشه پروژه قرار داره و تمام تنظیمات پروژهت اینجاست.
یه نکته خیلی مهم:
این ساختار باعث میشه پروژهها منظم و استاندارد باشن. یعنی هر کسی که پروژهت رو ببینه، میدونه کدها، تستها و خروجیها کجا هستن و لازم نیست دنبال فایلها بگرده.
بریم سراغ جزئیات فایل pom.xml
چی داخل pom.xml مینویسیم؟
سه تا چیز خیلی مهم تو این فایل هست که بدون اینا پروژه Maven درست کار نمیکنه:
Group ID: یه اسم یکتا برای پروژهته. معمولاً از اسم سایتت به صورت برعکس استفاده میکنی. مثلاً اگه سایتت fahmidani.com باشه، مینویسی: com.fahmidani.
Artifact ID: اسم فایل اجرایی پروژهت. مثلاً اگه پروژهت یه اپلیکیشن باشه، این اسم خروجی فایل JAR پروژهت میشه.
Version: نسخه پروژه. مثلاً اگه پروژه هنوز تو مرحله توسعه هست، از کلمه snapshot استفاده میکنی که یعنی این نسخه نهایی نیست و ممکنه آپدیت بشه.
وابستگیها (Dependencies) تو Maven
وابستگی چیه؟
خیلی ساده بگم، وابستگی یعنی پروژهت به یه چیز دیگه نیاز داره تا درست کار کنه. مثلاً:
شاید پروژهت بخواد از یه کتابخونه مثل JUnit برای تست استفاده کنه.
یا شاید به یه کتابخونه برای اتصال به دیتابیس نیاز داشته باشه.
تو Maven، این نیازها رو بهش میگی و خودش میره کتابخونههای لازم رو پیدا میکنه و برات اضافه میکنه.
وابستگیها کجا تعریف میشن؟
توی همون فایل pom.xml یه بخشی به اسم <dependencies> داری. تو این بخش، تمام کتابخونهها یا ابزارهایی که لازم داری رو تعریف میکنی. برای هر کتابخونه، باید اینا رو مشخص کنی:
Group ID
Artifact ID
Version
مثال بزنیم:
فرض کن میخوای از JUnit برای تست استفاده کنی. تو فایل pom.xml اینطوری تعریفش میکنی:
junitjunit4.13.2
حالا Maven خودش میره این کتابخونه رو دانلود میکنه و به پروژهت اضافه میکنه. چقدر راحت، نه؟ 😎
اسکوپها (Scopes) چیه؟
خب، یه وابستگی ممکنه تو مرحلههای مختلف پروژه لازم بشه. مثلاً:
شاید فقط موقع کامپایل بهش نیاز داشته باشی،
یا فقط موقع اجرا (runtime).
اینجاست که مفهوم اسکوپها (Scopes) میاد وسط. اسکوپ مشخص میکنه وابستگی تو کدوم مرحله از پروژه استفاده بشه.
انواع اسکوپها:
Compile (کامپایل)
پیشفرض همه وابستگیهاست.
یعنی این کتابخونه تو همه مراحل استفاده میشه (کامپایل، اجرا، و تست).
Provided (داده شده)
فقط برای کامپایل و تست استفاده میشه.
ولی تو فایل اجرایی (مثلاً JAR) نمیاد.
مثال: Lombok که فقط برای کامپایل لازمه.
Runtime (زمان اجرا)
تو اجرا و تست استفاده میشه.
ولی موقع کامپایل بهش نیازی نیست.
مثال: JDBC Drivers که فقط وقتی برنامه اجرا میشه لازمه.
Test (تست)
فقط برای تست استفاده میشه.
تو فایل اجرایی نمیاد.
مثال: JUnit که فقط برای تست کردن کد استفاده میشه.
وابستگیهای ترانزیتیو (Transitive Dependencies)
ترانزیتیو یعنی چی؟
یه وقتایی یه کتابخونه خودش به کتابخونههای دیگه نیاز داره. به اینا میگن وابستگیهای ترانزیتیو.
مثال بزنیم:
فرض کن از JUnit استفاده میکنی. این کتابخونه خودش به یه کتابخونه دیگه مثل Hamcrest نیاز داره. تو فایل pom.xml فقط JUnit رو تعریف میکنی و Maven خودش میره Hamcrest رو هم دانلود میکنه. یعنی لازم نیست نگران این چیزا باشی، Maven خودش اوضاع رو هندل میکنه.
پلاگینها (Plugins) و تنظیمات پیشرفته
پلاگین تو Maven چیه؟
پلاگینها تو Maven مثل ابزارای جانبی هستن که یه سری کارای خاص رو برای پروژهت انجام میدن. مثلاً:
کامپایل کردن کد با یه نسخه خاص از جاوا.
اجرای تستها.
ساختن فایل اجرایی (مثل JAR).
یه مثال ساده:
فرض کن میخوای پروژهت با نسخه 8 جاوا کامپایل بشه. باید از پلاگینی به اسم maven-compiler-plugin استفاده کنی. تو فایل pom.xml به این شکل تعریفش میکنی: