Spring Boot Components हिंदी ट्यूटोरियल: Controller, Service, Repository, Entity
ये हमारा Spring Boot Tutorials का पाँचवा आर्टिकल है और इसमें हम Application-Level Components (जो Annotation से मार्क किये जाते है) के बारे में डिटेल में जानेंगे। ये प्रोजेक्ट के वो हिस्से होते है, जो मिलकर एक Spring Application को बनाते है। याने हम एक प्रोजेक्ट को अलग-अलग हिस्सों में बाँटते है। जैसे -

पिछले आर्टिकल में हमने Dependency क्या होती है? और उसके बारे में अच्छेसे जाना था। अब आगे बढ़ते है।
सब से पहले मैं अपने एक प्रोजेक्ट का स्ट्रक्चर दिखा देता हूँ। मैं चाहता हूँ की सबसे पहले आप ये देखे। ताकि आप क्लियर हो जाये की जब हम Spring Initializr से प्रोजेक्ट की zip फाइल डाउनलोड करते है। और जब हम उसे Extract करके अपने IDE पर ओपन करते और प्रोजेक्ट बनाने की शुरवात करते है। तो हम इसी Application-Level Components से करते है।
( यहाँ पर एक इमेज है जो प्रोजेक्ट के स्ट्रक्चर को दिखाती है)
इस इमेज में देखो, com.farmeradvice पैकेज के अन्दर Controller, Model, Repository, Service के फोल्डर बनाए है जिसमे कुछ फाइल्स बनी हुई है। जैसे Controller पैकेज में AdminController, FarmerController, HomeController।
आप यहाँ देख सकते है, जितनी भी Controller फाइल्स है, जिन्हें हमने एक Controller नाम के फोल्डर में रखा है और अन्य Components की फाइल्स उस Components के नाम वाले फोल्डर में रखी है।
जिस तरह से एक घर बनाने के लिए हमें ईंटे, सीमेंट, गिट्टी, वालू, लोहे के बार, छत इस तरह से कई चीजों की जरूरत होती है, जो घर बनाने के काम आती है, और हम एक-एक हिस्से जो जोड़ते है, और खास बात ये होती है की हर चीज अलग-अलग चीजों से जुडी होती है, जैसे घर के पिलर सीमेंट, गिट्टी, वालू, लोहे के बार से जुड़े होते है. ईंटे भी सीमेंट और वालू से जुडी होती है, उस से बनी दीवार पिलर से जुडी होती है, पिलर और दीवारों से छत जुडा होता है। इसी तरह से घर बनता है।
बिलकुल यही कांसेप्ट यहाँ स्प्रिंग बूट के प्रोजेक्ट को कम्पलीट करने के लिए यूज़ होता है। अलग-अलग एप्लीकेशन लेवल के Components हमें आपस में जोड़ने होते है। इसलिए इन कंपोनेंट्स को हम Spring के "बिल्डिंग बॉक्स" कह सकते है।
यहाँ स्प्रिंग ने हर Components को एक लेबल दिया है(लेबल, टैग्स, या मार्कर कुछ भी हम कह सकते है), जिसे हम Annotation कहते है। (इसे हमे आनेवाले आर्टिकल में डिटेल में पढ़ना ही है) ये Annotation ही बताता है की किसी क्लास या मेथड से कौनसा काम करवाना है।
Controller Spring Boot के Model-View-Controller (MVC) का हिस्सा है, जिसका काम है ब्राउज़र request (HTTP Request) को हैंडल करना और यूजर को रिस्पांस देना। बिलकुल वैसे ही जैसे कोई ग्राहक वेटर को आर्डर देता है, और वेटर ग्राहक की डिमांड को पूरा करता है। अब हम इसे थोडा टेक्निकली समझते है।
हमे अपने स्प्रिंग बूट प्रोजेक्ट में Controller बनाना होता है, जो ब्राउज़र रिक्वेस्ट को हैंडल कर सकें। यूजर डिमांड को देखते हुए यूजर को अलग अलग पेज रेंडर करने की जरूरत होती है। और ये ही जरूरत पूरी करने के लिए हर अलग-अलग काम (जैसे लॉगिन, रजिस्ट्रेशन, डैशबोर्ड, और भी अन्य) के लिए हम अलग-अलग Controller क्लास बनाते हैं, जो @Controller एनोटेशन से मार्क की जाती है।
याने जब कोई यूजर लॉग इन पेज के लिए रिक्वेस्ट भेजता है(ब्राउज़र से) तब DispatcherServlet ( ये स्प्रिंग कोर का हिस्सा है, जिसे हम स्प्रिंग का फ्रंट Controller भी कहते है) उस रिक्वेस्ट को डिटेक्ट करता है, और उसे सही Controller के पास भेजता है।
याने लॉग इन पेज के लिए रिक्वेस्ट को LoginController के पास भेजेगा क्यों की यहाँ @GetMapping("/login") एनोटेशन को होल्ड किया गया है। DispatcherServlet URL और उस पर लगे Mapping Annotation (जैसे @GetMapping("/login")) के आधार पर तय करता है कि यूज़र की रिक्वेस्ट किस Controller और किस मेथड को भेजी जाए।
LoginController में जिस मेथड में Getmapping एनोटेशन लगा है, वो मेथड अब view return करती है, जैसे login.html या login.jsp (जो भी हम फ्रंटएंड के लिए यूज़ कर रहे है वो लॉग इन पेज )
इस तरह से Controller काम करता है और यूज़र की रिक्वेस्ट के अनुसार रेस्पॉन्स देता है।
निचे एक Simple example दिया गया है। आप देख सकते है।
Controller क्लास एक और Annotation से रिप्रेजेंट की जाती है, जो है @RestController। अब ये हमें समझना जरुरी है की हम @Controller और @RestController का यूज़ कब करें? चलो समझते है।
सरल तरीके से बता देता हूँ जब हम स्प्रिंग बूट प्रोजेक्ट में ही HTML और JSP जैसे पेजेज बनाते है और Controller के जरिये यूजर को HTML और JSP में view return करते है, तब हम @Controller एनोटेशन का यूज़ करते है।
लेकिन कई बार हम प्रोजेक्ट के बैकएंड और फ्रंटएंड को अलग-अलग बनाते है, जैसे हमने बैकएंड तो स्प्रिंग बूट में बना रहे है लेकिन इसके फ्रंटएंड के लिए हम React.js , एंगुलर जैसे अन्य फ्रेमवर्क या लाइब्रेरीज का यूज़ करते है इस कंडीशन में हमें Rest APIs को बनाना होता है और हम Controller द्वारा यूजर को JSON या XML में view return करना होता है, तब हम @RestController एनोटेशन का यूज़ करते है।
निचे Simple example देख सकते है।
ये Application-Level Components है जो बिज़नेस लॉजिक को लागु करता है। अब ये बिज़नेस लॉजिक क्या है ये हम समझते है। हमने ऊपर Controller को समझा है, समझो अगर Controller यूजर को उसके रिक्वेस्ट के अनुसार लॉग इन पेज दिखता है लेकिन यहाँ Controller लॉग इन पेज पर मौजूद लॉजिक की जबाबदेही नहीं लेता। इसके लिए Controller अपने क्लास में Service क्लास को @Autowired कर लेता है, ताकि पेज पर मौजूद लॉजिक के लिए Service क्लास जिम्मेदार हो। जैसे की हम यहाँ Controller क्लास के कोड में देखते है। यहाँ @Autowired के जरिये LoginService क्लास को इंजेक्ट किया गया है।
@Autowired एक Annotation है जो एक क्लास में किसी दुसरे क्लास के ऑब्जेक्ट को ऑटोमेटिकली बनाकर इंजेक्ट कर देता है। ( इसे हम Annotation के आर्टिकल में विस्तार से समझेंगे)।
हम बात कर रहे है Service Component की, लॉग इन पेज पर जो भी मौजूद है उसका जिम्मा Controller नहीं लेता, वह सिर्फ यूजर को पेज दिखता है और लॉजिक का जिम्मा Service क्लास पर दे देता है।
याने जब यूजर लॉग इन पेज पर जायेगा तो उसे वहाँ यूजरनाम और पासवर्ड के आप्शन दिखेंगे, यहाँ पर यूजर को सही या गलत यूजरनाम और पासवर्ड डालने पर क्या होना चाहए? ये लॉजिक हैंडल करने की जिम्मेदारी अब Service क्लास की है।
हम Service नाम के फोल्डर में आवश्यकता नुसार अलग-अलग Service classes बनाते है। अगर LoginController इस Controller क्लास ने लॉजिक की जिम्मेदारी LoginService पेज पर दी है, तो हमारे Service पैकेज(फोल्डर) में ये मौजूद होनी चाहिए।
अब Service क्लास लॉजिक को कैसे हैंडल करती है, ये देखते है।
मैं इस क्लास को बिचौलिया क्लास कहता हूँ। क्यों की ये क्लास सिर्फ इधर का उधर उधर का इधर इतना ही काम करता है। जैसे कोई यूजर लॉग इन पेज पर यूजरनाम और पासवर्ड फील करता है, तब ये यूजरनाम और पासवर्ड को चेक करने के लिए Repository Component क्लास के पास भेजता है, याने @Autowired के जरिये Repository के इंटरफ़ेस को पहले ही इंजेक्ट कर लेता है, और जैसे ही यूजर यूजरनाम और पासवर्ड देता है उसे चेक करने के लिए भेज देता Repository इंटरफ़ेस के पास, अगर Repository इंटरफ़ेस ने बताया की ये गलत पासवर्ड है तो यूजर को एरर थ्रो कर देता है। अगर सही है तो Controller क्लास के पास भेज देता है ताकि Controller यूजर को अगला पेज दिखा सकें।
इस तरह से Service क्लास काम करता है, और स्प्रिंग बूट इसे @Service Annotation के जरिये पहचानता है।
अब ये समझना जरूरी है क्या Service क्लास (@Service Annotation मार्क के साथ) जरुरी है? क्या इसके बिना काम नहीं हो सकता? बिल्कुल हो सकता है, Service क्लास जो काम कर रहा है वो काम Controller क्लास से भी करवाया जा सकता है। लेकिन इस से हमारे कई Options सिमित हो सकते है या फिर जब हम किसी Problems को फेस करेंगे तो तो ज्याद complicated हो सकता है। आईये समझते है।
ऐसा नहीं है कापने Service क्लास नहीं बनाई तो आपका काम नहीं होगा, लेकिन जब Service क्लास नहीं होगी तो लोड आएगा आपके Controller पर। याने अब आपके लॉजिक हो हैंडल कर रहा है Controller। इसके कुछ नुकसान देखते है :
Service Layer को loosely coupled रखने से हम Code Reusability और Testing को आसान बना सकते है। इसलिए मुझे लगता है प्रोजेक्ट छोटा हो या बड़ा, हमें इंडस्ट्रियल लेवल पर अपनी प्रैक्टिस करनी चाहिए।
रिपॉजिटरी ये कॉम्पोनेन्ट जो है वो हमारे डेटाबेस ऑपरेशन को परफॉर्म करता है। जैसे डेटाबेस में वैल्यू चेक करना, सेव करना, डिलीट करना।
अब एक बात यहाँ समझे की जरूरत है। जैसे हम कंट्रोलर, सर्विस। एंटिटी के लिए क्लासेज बनाते है, लेकिन रिपॉजिटरी के लिए हम एक इंटरफ़ेस बनाते है। ऐसा क्यों?। ये समझना काफी अनिवार्य है।
स्प्रिंग बूट में डेटाबेस ऑपरेशन परफॉर्म करने के लिए हम Spring Data JPA की डिपेंडेंसी ऐड करते है। ताकि हमारे सभी डेटाबेस के काम इस डिपेंडेंसी के जरिये स्प्रिंग बूट पूरा कर दें। Spring Data JPA के पास कई सुविधाएँ होती है, जैसे -
इस तरह से Repository इंटरफ़ेस काम करता है।
तो फिर एंटिटी क्या करती है? और रिपॉजिटरी एंटिटी क्लास की क्यों मैपिंग करती है?
सब से पहले एंटिटी क्लास को समझते है। Entity क्लास ना ही डेटाबेस बनता है और ना ही डेटाबेस के टेबल्स बनता है, ये बस प्रोजेक्ट के आवश्यकता नुसार डेटाबेस में बनने वाले टेबल्स को स्ट्रक्चराईज्ड बनता है, टेबल्स के Row और Column को सुनियोजित तरीके से डिफाइन करता है।
तो अब आप सोचेंगे डेटाबेस और डेटाबेस टेबल्स तो ऑटोमेटिकली स्प्रिंग बूट प्रोजेक्ट में बन जाते है, जब प्रोजेक्ट रन होता है, तो उसे कौन बनाता होगा?
असल में Spring Data JPA ये डिपेंडेंसी इसे क्रिएट करती है, लेकिन ये आपके अनुमति के बगैरे नही करती। आपको अपने प्रोजेक्ट के application.properties में बताना होता है। यहाँ पर आप MYSQL में डेटाबेस क्रिएट करने के लिए JDBC driver को अपना यूआरएल और पासवर्ड देते हो। साथ ही डेटाबेस में टेबल्स क्रिएट करनी अनुमति भी देते हो।
यहाँ पर अनुमति मिलने के बाद रनटाइम पर Spring Data JPA Mysql में डेटाबेस बनता है और एंटिटी क्लास को ढूंडकर टेबल्स के स्ट्रक्चर को समजकर उसके हिसाब से डेटाबेस में स्ट्रक्चर बना देता है।
इसीलिए रिपॉजिटरी क्लास @Autowired Annotation के जरिये एंटिटी में वो स्ट्रक्चर चेक करता है, जो सर्विस क्लास द्वारा मंगाई गयी वैल्यू का होगा। और अगर एंटिटी में वो स्ट्रक्चर बना है तो कन्फर्म हो जाता है की डेटाबेस में इसका टेबल्स बनाया गया है। इस तरह से एंटिटी को पढ़कर ही रिपॉजिटरी वैल्यू रिटर्न करता है।
मैं जानना चाहता हूँ की, Spring Boot Tutorials के ये आर्टिकल्स आपको आसानी से स्प्रिंग बूट सिखा पा रहे है या नहीं। मुझे कमेंट में जरुर बताएं।
- Controller
- Service
- Entity
- Repository
- DAO
- DTO
- Model
- Configuration
- Exception Handler
- Interceptor
- Filter
- Event Listener
- Component

पिछले आर्टिकल में हमने Dependency क्या होती है? और उसके बारे में अच्छेसे जाना था। अब आगे बढ़ते है।
Components Structure को समझना जरुरी
( यहाँ पर एक इमेज है जो प्रोजेक्ट के स्ट्रक्चर को दिखाती है)
इस इमेज में देखो, com.farmeradvice पैकेज के अन्दर Controller, Model, Repository, Service के फोल्डर बनाए है जिसमे कुछ फाइल्स बनी हुई है। जैसे Controller पैकेज में AdminController, FarmerController, HomeController।
आप यहाँ देख सकते है, जितनी भी Controller फाइल्स है, जिन्हें हमने एक Controller नाम के फोल्डर में रखा है और अन्य Components की फाइल्स उस Components के नाम वाले फोल्डर में रखी है।
लेकिन मैं आपको बता देना चाहता हूँ, Controller फोल्डर या अन्य सभी Components के फोल्डर बनाना या फाइल्स को Controller या अन्य Components के नाम देना ये कोई लिखित नियम नहीं है। ये तो हम अपने प्रोजेक्ट को सुव्यवस्थित रखने के लिए, फाइल्स को आसानी से पहचानने के लिए और अन्य डेवलपर्स को प्रोजेक्ट की संरचना को समझाने के लिए स्ट्रक्चर में ऐसे फोल्डर और फाइल के नाम इस तरह से बनाते है। और हमे ऐसा ही बनाना भी चाहिए।
लेकिन ऐसा कोई नियम नहीं है। स्प्रिंग बूट Annotation (जो एक मार्कर है) के बेस पर फाइल्स को पहचानने का काम करता है। अगर आपने बिना फोल्डर के कोई Controller फाइल बनाई है, और उसमे मेन क्लास MyFirstFile है। जो आपके फाइल का भी नाम है। और उसपर @Controller Annotation लगाया है। फिर भी स्प्रिंग बूट पहचान जायेगा की ये एक Controller क्लास है और इसे HTTP requests को हैंडल करना है। या हम कहे की ब्राउज़र कॉल पर एक्शन करना है।
ये बताना इसलिए जरुरी था क्योंकि नये स्टूडेंट्स इसमें काफी कन्फ्यूज्ड रहते है। अब आगे बढ़ते है और Spring Boot के Application-Level Components को समझते है, उनके फंक्शनलिटी को जानते है।
लेकिन ऐसा कोई नियम नहीं है। स्प्रिंग बूट Annotation (जो एक मार्कर है) के बेस पर फाइल्स को पहचानने का काम करता है। अगर आपने बिना फोल्डर के कोई Controller फाइल बनाई है, और उसमे मेन क्लास MyFirstFile है। जो आपके फाइल का भी नाम है। और उसपर @Controller Annotation लगाया है। फिर भी स्प्रिंग बूट पहचान जायेगा की ये एक Controller क्लास है और इसे HTTP requests को हैंडल करना है। या हम कहे की ब्राउज़र कॉल पर एक्शन करना है।
ये बताना इसलिए जरुरी था क्योंकि नये स्टूडेंट्स इसमें काफी कन्फ्यूज्ड रहते है। अब आगे बढ़ते है और Spring Boot के Application-Level Components को समझते है, उनके फंक्शनलिटी को जानते है।
Spring Boot के Application-Level Components
बिलकुल यही कांसेप्ट यहाँ स्प्रिंग बूट के प्रोजेक्ट को कम्पलीट करने के लिए यूज़ होता है। अलग-अलग एप्लीकेशन लेवल के Components हमें आपस में जोड़ने होते है। इसलिए इन कंपोनेंट्स को हम Spring के "बिल्डिंग बॉक्स" कह सकते है।
यहाँ स्प्रिंग ने हर Components को एक लेबल दिया है(लेबल, टैग्स, या मार्कर कुछ भी हम कह सकते है), जिसे हम Annotation कहते है। (इसे हमे आनेवाले आर्टिकल में डिटेल में पढ़ना ही है) ये Annotation ही बताता है की किसी क्लास या मेथड से कौनसा काम करवाना है।
Annotation क्या है? ( संक्षिप्त में )
Annotation कैसे काम करता है, इसे थोडा समझाने के लिए मैं आपको एक Example देता हूँ, जैसे- किसी होटल में मैनेजर, कुक, वेटर होते है। सबका काम निर्धारित है। आर्डर लेना, आर्डर को कुक तक पहुचाना, कुक से बनी हुई डिश लेना और ग्राहक को सर्व करना, और ग्राहक को बिल देकर मेनेजर के पास भेजना वेटर का काम है।
वेटर ने दी हुई आर्डर के मुताबिक डिश बनाना और उसे वेटर को देना ये कुक का काम है, और वेटर द्वारा दिए गये बिल को चेक करना और ग्राहक से पैसे लेना मैनेजर का काम है।
आर्डर लेकर खाना परोसना और बिल बनाना ये काम जिस इन्सान का है उसे “वेटर” ये टैग दिया है, इसी टैग को हम Annotation कहते है। Annotation सिर्फ एक टैग या लेबल है, यहाँ पर जो भी काम हो रहा है Component क्लास या मेथड के जरिये ही हो रहा है। लेकिन उस क्लास और मेथड का काम Annotation निर्धारित कर रहा है।
याने होटल में जानेवाला ग्राहक कंफ्यूज नही है, जिसे ग्राहक ने वेटर कहके बुलाया, उसे वो सिर्फ आर्डर देगा, होटल का बिल वेटर के पास नही देगा, वेटर डिश नहीं बनाएगा या खाने के टेस्ट की जवाबदेही वेटर की नहीं है। इसी तरह से Annotation स्प्रिंग को कन्फ्यूज्ड होने से बचाते है।
यहाँ Annotation को संक्षिप्त में समझाया है, आगे आनेवाले आर्टिकल में हम इसे विस्तार से समझेंगे और जानेंगे कौन कौन से Annotation होते है?
यहाँ हम Application-Level Components की बात कर रहे है तो जाहिर है, तो वे किस लिए मार्क किये गये है? और कौनसा Component क्या काम करता है?, ये हम यहाँ जानेंगे।
आर्डर लेकर खाना परोसना और बिल बनाना ये काम जिस इन्सान का है उसे “वेटर” ये टैग दिया है, इसी टैग को हम Annotation कहते है। Annotation सिर्फ एक टैग या लेबल है, यहाँ पर जो भी काम हो रहा है Component क्लास या मेथड के जरिये ही हो रहा है। लेकिन उस क्लास और मेथड का काम Annotation निर्धारित कर रहा है।
याने होटल में जानेवाला ग्राहक कंफ्यूज नही है, जिसे ग्राहक ने वेटर कहके बुलाया, उसे वो सिर्फ आर्डर देगा, होटल का बिल वेटर के पास नही देगा, वेटर डिश नहीं बनाएगा या खाने के टेस्ट की जवाबदेही वेटर की नहीं है। इसी तरह से Annotation स्प्रिंग को कन्फ्यूज्ड होने से बचाते है।
यहाँ Annotation को संक्षिप्त में समझाया है, आगे आनेवाले आर्टिकल में हम इसे विस्तार से समझेंगे और जानेंगे कौन कौन से Annotation होते है?
यहाँ हम Application-Level Components की बात कर रहे है तो जाहिर है, तो वे किस लिए मार्क किये गये है? और कौनसा Component क्या काम करता है?, ये हम यहाँ जानेंगे।
आर्टिकल के शुरवात में ही हमने सभी कंपोनेंट्स की लिस्ट देखी थी, चलो इसे एक-एक करके विस्तार से समझते है।
Controller क्या है?
Controller Spring Boot के Model-View-Controller (MVC) का हिस्सा है, जिसका काम है ब्राउज़र request (HTTP Request) को हैंडल करना और यूजर को रिस्पांस देना। बिलकुल वैसे ही जैसे कोई ग्राहक वेटर को आर्डर देता है, और वेटर ग्राहक की डिमांड को पूरा करता है। अब हम इसे थोडा टेक्निकली समझते है।
हमे अपने स्प्रिंग बूट प्रोजेक्ट में Controller बनाना होता है, जो ब्राउज़र रिक्वेस्ट को हैंडल कर सकें। यूजर डिमांड को देखते हुए यूजर को अलग अलग पेज रेंडर करने की जरूरत होती है। और ये ही जरूरत पूरी करने के लिए हर अलग-अलग काम (जैसे लॉगिन, रजिस्ट्रेशन, डैशबोर्ड, और भी अन्य) के लिए हम अलग-अलग Controller क्लास बनाते हैं, जो @Controller एनोटेशन से मार्क की जाती है।
याने जब कोई यूजर लॉग इन पेज के लिए रिक्वेस्ट भेजता है(ब्राउज़र से) तब DispatcherServlet ( ये स्प्रिंग कोर का हिस्सा है, जिसे हम स्प्रिंग का फ्रंट Controller भी कहते है) उस रिक्वेस्ट को डिटेक्ट करता है, और उसे सही Controller के पास भेजता है।
याने लॉग इन पेज के लिए रिक्वेस्ट को LoginController के पास भेजेगा क्यों की यहाँ @GetMapping("/login") एनोटेशन को होल्ड किया गया है। DispatcherServlet URL और उस पर लगे Mapping Annotation (जैसे @GetMapping("/login")) के आधार पर तय करता है कि यूज़र की रिक्वेस्ट किस Controller और किस मेथड को भेजी जाए।
LoginController में जिस मेथड में Getmapping एनोटेशन लगा है, वो मेथड अब view return करती है, जैसे login.html या login.jsp (जो भी हम फ्रंटएंड के लिए यूज़ कर रहे है वो लॉग इन पेज )
इस तरह से Controller काम करता है और यूज़र की रिक्वेस्ट के अनुसार रेस्पॉन्स देता है।
निचे एक Simple example दिया गया है। आप देख सकते है।
@Controller public class LoginController { @Autowired private LoginService loginService;@GetMapping("/login") public String showLoginPage() { return "login"; } } |
Controller क्लास एक और Annotation से रिप्रेजेंट की जाती है, जो है @RestController। अब ये हमें समझना जरुरी है की हम @Controller और @RestController का यूज़ कब करें? चलो समझते है।
सरल तरीके से बता देता हूँ जब हम स्प्रिंग बूट प्रोजेक्ट में ही HTML और JSP जैसे पेजेज बनाते है और Controller के जरिये यूजर को HTML और JSP में view return करते है, तब हम @Controller एनोटेशन का यूज़ करते है।
लेकिन कई बार हम प्रोजेक्ट के बैकएंड और फ्रंटएंड को अलग-अलग बनाते है, जैसे हमने बैकएंड तो स्प्रिंग बूट में बना रहे है लेकिन इसके फ्रंटएंड के लिए हम React.js , एंगुलर जैसे अन्य फ्रेमवर्क या लाइब्रेरीज का यूज़ करते है इस कंडीशन में हमें Rest APIs को बनाना होता है और हम Controller द्वारा यूजर को JSON या XML में view return करना होता है, तब हम @RestController एनोटेशन का यूज़ करते है।
निचे Simple example देख सकते है।
@RestController public class ApiController { @Autowired private LoginService loginService; @GetMapping("/api/user") public User getUser() { return new User("John", "john@example.com"); } } |
Service क्या है?
@Autowired एक Annotation है जो एक क्लास में किसी दुसरे क्लास के ऑब्जेक्ट को ऑटोमेटिकली बनाकर इंजेक्ट कर देता है। ( इसे हम Annotation के आर्टिकल में विस्तार से समझेंगे)।
हम बात कर रहे है Service Component की, लॉग इन पेज पर जो भी मौजूद है उसका जिम्मा Controller नहीं लेता, वह सिर्फ यूजर को पेज दिखता है और लॉजिक का जिम्मा Service क्लास पर दे देता है।
याने जब यूजर लॉग इन पेज पर जायेगा तो उसे वहाँ यूजरनाम और पासवर्ड के आप्शन दिखेंगे, यहाँ पर यूजर को सही या गलत यूजरनाम और पासवर्ड डालने पर क्या होना चाहए? ये लॉजिक हैंडल करने की जिम्मेदारी अब Service क्लास की है।
हम Service नाम के फोल्डर में आवश्यकता नुसार अलग-अलग Service classes बनाते है। अगर LoginController इस Controller क्लास ने लॉजिक की जिम्मेदारी LoginService पेज पर दी है, तो हमारे Service पैकेज(फोल्डर) में ये मौजूद होनी चाहिए।
अब Service क्लास लॉजिक को कैसे हैंडल करती है, ये देखते है।
मैं इस क्लास को बिचौलिया क्लास कहता हूँ। क्यों की ये क्लास सिर्फ इधर का उधर उधर का इधर इतना ही काम करता है। जैसे कोई यूजर लॉग इन पेज पर यूजरनाम और पासवर्ड फील करता है, तब ये यूजरनाम और पासवर्ड को चेक करने के लिए Repository Component क्लास के पास भेजता है, याने @Autowired के जरिये Repository के इंटरफ़ेस को पहले ही इंजेक्ट कर लेता है, और जैसे ही यूजर यूजरनाम और पासवर्ड देता है उसे चेक करने के लिए भेज देता Repository इंटरफ़ेस के पास, अगर Repository इंटरफ़ेस ने बताया की ये गलत पासवर्ड है तो यूजर को एरर थ्रो कर देता है। अगर सही है तो Controller क्लास के पास भेज देता है ताकि Controller यूजर को अगला पेज दिखा सकें।
इस तरह से Service क्लास काम करता है, और स्प्रिंग बूट इसे @Service Annotation के जरिये पहचानता है।
@Service public class LoginService { @Autowired private LoginRepository loginRepository; public boolean validateLogin(String username, String password) { User user = loginRepository.findByUsername(username); return user != null && user.getPassword().equals(password); } } |
अब ये समझना जरूरी है क्या Service क्लास (@Service Annotation मार्क के साथ) जरुरी है? क्या इसके बिना काम नहीं हो सकता? बिल्कुल हो सकता है, Service क्लास जो काम कर रहा है वो काम Controller क्लास से भी करवाया जा सकता है। लेकिन इस से हमारे कई Options सिमित हो सकते है या फिर जब हम किसी Problems को फेस करेंगे तो तो ज्याद complicated हो सकता है। आईये समझते है।
ऐसा नहीं है कापने Service क्लास नहीं बनाई तो आपका काम नहीं होगा, लेकिन जब Service क्लास नहीं होगी तो लोड आएगा आपके Controller पर। याने अब आपके लॉजिक हो हैंडल कर रहा है Controller। इसके कुछ नुकसान देखते है :
- अब जब हमे ये ही लॉजिक किसी दुसरे पेज के लिए इस्तेमाल करना है तो हमे दूसरा Controller क्लास बनाना पड़ेगा, और यही कोड फिरसे लिखना पड़ेगा। याने हम एक ही कोड को reuse नहीं कर पाएंगे।
- अगर Controller में कोई प्रॉब्लम आये तो उसका असर लॉजिक पर नही पड़ेगा, या लॉजिक में कोई प्रॉब्लम आये तो बाकि Controller फाइल पर उसका असर पड़ेगा, जो एरर डिटेक्शन को complicated करेगा।
- Controller के साथ लॉजिक को टेस्ट करना मुश्किल हो जायेगा।
Service Layer को loosely coupled रखने से हम Code Reusability और Testing को आसान बना सकते है। इसलिए मुझे लगता है प्रोजेक्ट छोटा हो या बड़ा, हमें इंडस्ट्रियल लेवल पर अपनी प्रैक्टिस करनी चाहिए।
Repository क्या है?
Service क्लास Repository को @Autowired के जरिये इंजेक्ट करता है, और डेटाबेस में स्टोर वैल्यू को चेक करने के लिए रिपॉजिटरी के पास भेज देता है। ये हमने Service में जाना है। अब जानते है की Repository ये Application-Level Components करता क्या है?रिपॉजिटरी ये कॉम्पोनेन्ट जो है वो हमारे डेटाबेस ऑपरेशन को परफॉर्म करता है। जैसे डेटाबेस में वैल्यू चेक करना, सेव करना, डिलीट करना।
अब एक बात यहाँ समझे की जरूरत है। जैसे हम कंट्रोलर, सर्विस। एंटिटी के लिए क्लासेज बनाते है, लेकिन रिपॉजिटरी के लिए हम एक इंटरफ़ेस बनाते है। ऐसा क्यों?। ये समझना काफी अनिवार्य है।
स्प्रिंग बूट में डेटाबेस ऑपरेशन परफॉर्म करने के लिए हम Spring Data JPA की डिपेंडेंसी ऐड करते है। ताकि हमारे सभी डेटाबेस के काम इस डिपेंडेंसी के जरिये स्प्रिंग बूट पूरा कर दें। Spring Data JPA के पास कई सुविधाएँ होती है, जैसे -
- इसके पास रेडीमेड मेथड्स होते है - save(), findAll(), findById(), deleteById()
- यहाँ SQL/JPQL queries लिखने की जरूरत नहीं पड़ती, ये Automatic Query Derivation पर काम करता है।(इसे निचे एक्सप्लेन किया है)
- paging, sorting, derived queries के लिए ऑटो-कॉन्फ़िगरेशन
- डायनामिक तरीके से Proxy को रनटाइम इम्प्लेमेंट्स करता है।
- Boilerplate code को कम कर देता है।
अब हम जानते है की हम Repository को इंटरफ़ेस क्यों बनाते है? । क्यों की हम Spring Data JPA डिपेंडेंसी का यूज़ करते है। और Spring Data JPA ये डिपेंडेंसी JpaRepository<User, Long> को होल्ड करता है जो एक generic interface है।
इस generic interface के पास डेटाबेस ऑपरेशन के लिए कई मेथड्स होते है, जैसे -
ऐसे में अगर हम Repository को क्लास बनायेंगे तो स्प्रिंग बूट JpaRepository के मेथड्स को override या proxy नहीं कर पाएगा। इस जेनेरिक इंटरफ़ेस को हमे इम्प्लेमेंट्स करना पड़ेगा और इसके सभी मेथड्स को मैन्युअली ओवरराइड करना पड़ेगा। और बाकि सब काम भी मैन्युअली करना पड़ेगा, जो आपके लिए tedious और error-prone हो जायेगा।
क्यों की Spring Boot हमारे लिए कई तरह के काम ऑटोमेटिकली करता है, इसलिए रिपॉजिटरी को क्लास के रूप में प्रेजेंट करना हमारे लिए और हमारे प्रोजेक्ट के लिए एक सरदर्द बन जायेगा, इसीलिए हम रिपॉजिटरी को इंटरफ़ेस बनाते है।
जब Service क्लास से डेटाबेस ऑपरेशन परफॉर्म की कॉल आती है, तब Repository इंटरफ़ेस सब से पहले Spring Data JPA और Hibernate के साथ मिलकर Entity class से टेबल मैपिंग करते हैं। अगर Entity class ग़लत है, या टेबल मैपिंग ग़लत है, तो application context boot होने पर ही error मिल जाता है
और अगर सर्विस क्लास द्वारा रेकुमेंट किये हुए टेबल Entity क्लास में बने है तो फिर रिपॉजिटरी इंटरफ़ेस सर्विस क्लास द्वारा दिए गये निर्देशों के अनुसार ऑपरेशन परफॉर्म करके रिजल्ट सर्विस क्लास को दे देता है।
इस generic interface के पास डेटाबेस ऑपरेशन के लिए कई मेथड्स होते है, जैसे -
- CRUD methods के लिए - save(), findById(), delete(), और अन्य।
- Sorting methods के लिए - findAll(Sort sort)
- Paging methods के लिए -findAll(Pageable pageable)
ऐसे में अगर हम Repository को क्लास बनायेंगे तो स्प्रिंग बूट JpaRepository के मेथड्स को override या proxy नहीं कर पाएगा। इस जेनेरिक इंटरफ़ेस को हमे इम्प्लेमेंट्स करना पड़ेगा और इसके सभी मेथड्स को मैन्युअली ओवरराइड करना पड़ेगा। और बाकि सब काम भी मैन्युअली करना पड़ेगा, जो आपके लिए tedious और error-prone हो जायेगा।
क्यों की Spring Boot हमारे लिए कई तरह के काम ऑटोमेटिकली करता है, इसलिए रिपॉजिटरी को क्लास के रूप में प्रेजेंट करना हमारे लिए और हमारे प्रोजेक्ट के लिए एक सरदर्द बन जायेगा, इसीलिए हम रिपॉजिटरी को इंटरफ़ेस बनाते है।
जब Service क्लास से डेटाबेस ऑपरेशन परफॉर्म की कॉल आती है, तब Repository इंटरफ़ेस सब से पहले Spring Data JPA और Hibernate के साथ मिलकर Entity class से टेबल मैपिंग करते हैं। अगर Entity class ग़लत है, या टेबल मैपिंग ग़लत है, तो application context boot होने पर ही error मिल जाता है
और अगर सर्विस क्लास द्वारा रेकुमेंट किये हुए टेबल Entity क्लास में बने है तो फिर रिपॉजिटरी इंटरफ़ेस सर्विस क्लास द्वारा दिए गये निर्देशों के अनुसार ऑपरेशन परफॉर्म करके रिजल्ट सर्विस क्लास को दे देता है।
import com.example.entity.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import java.util.List; @Repository public interface LoginRepository extends JpaRepository<User, Long> { List<User> findByName(String name); } |
इस तरह से Repository इंटरफ़ेस काम करता है।
Entity क्या है? (@Entity)
अब Entity कंपोनेट को समझते है, हमने देखा रिपॉजिटरी Entity क्लास की मैपिंग करती है। कई स्टूडेंट्स पहली बार कंफ्यूज हो सकते है, जैसे मैं भी हुआ था और ये मानता था एंटिटी क्लास ही डेटाबेस में टेबल क्रिएट करती है। लेकिन ऐसा नहीं है, डेटाबेस से रिलेटेड डिपेंडेंसी (Spring Data JPA) इस काम को करती है।तो फिर एंटिटी क्या करती है? और रिपॉजिटरी एंटिटी क्लास की क्यों मैपिंग करती है?
सब से पहले एंटिटी क्लास को समझते है। Entity क्लास ना ही डेटाबेस बनता है और ना ही डेटाबेस के टेबल्स बनता है, ये बस प्रोजेक्ट के आवश्यकता नुसार डेटाबेस में बनने वाले टेबल्स को स्ट्रक्चराईज्ड बनता है, टेबल्स के Row और Column को सुनियोजित तरीके से डिफाइन करता है।
@Entity public class User { @Id private Long id; private String name; private String email; // Default Constructor // Parameterized Constructor // Getter and Setter } |
तो अब आप सोचेंगे डेटाबेस और डेटाबेस टेबल्स तो ऑटोमेटिकली स्प्रिंग बूट प्रोजेक्ट में बन जाते है, जब प्रोजेक्ट रन होता है, तो उसे कौन बनाता होगा?
असल में Spring Data JPA ये डिपेंडेंसी इसे क्रिएट करती है, लेकिन ये आपके अनुमति के बगैरे नही करती। आपको अपने प्रोजेक्ट के application.properties में बताना होता है। यहाँ पर आप MYSQL में डेटाबेस क्रिएट करने के लिए JDBC driver को अपना यूआरएल और पासवर्ड देते हो। साथ ही डेटाबेस में टेबल्स क्रिएट करनी अनुमति भी देते हो।
application.properties फाइल
spring.datasource.url=jdbc:mysql://localhost:3306/demo_db spring.datasource.username=root spring.datasource.password=your_password spring.jpa.hibernate.ddl-auto=update |
यहाँ पर अनुमति मिलने के बाद रनटाइम पर Spring Data JPA Mysql में डेटाबेस बनता है और एंटिटी क्लास को ढूंडकर टेबल्स के स्ट्रक्चर को समजकर उसके हिसाब से डेटाबेस में स्ट्रक्चर बना देता है।
इसीलिए रिपॉजिटरी क्लास @Autowired Annotation के जरिये एंटिटी में वो स्ट्रक्चर चेक करता है, जो सर्विस क्लास द्वारा मंगाई गयी वैल्यू का होगा। और अगर एंटिटी में वो स्ट्रक्चर बना है तो कन्फर्म हो जाता है की डेटाबेस में इसका टेबल्स बनाया गया है। इस तरह से एंटिटी को पढ़कर ही रिपॉजिटरी वैल्यू रिटर्न करता है।
संबोधन
यहाँ तक हमने स्प्रिंग बूट Application-Level Components को अच्छेसे समझा है। आवश्यक बातों को जाना है। इसलिए मुझे लगता है की यहाँ पर अब प्रैक्टिकल करने देखने की जरूरत है। इसलिए अगला आर्टिकल हम स्प्रिंग बूट “Hello World” का सिंपल प्रोजेक्ट बनायेंगे। और @Controller और @RestController के जरिये टेक्स्ट, html पेज और JSON फाइल के रूप में हम “Hello World” कैसे लौटते है , ये प्रैक्टिकली सीखेंगे।मैं जानना चाहता हूँ की, Spring Boot Tutorials के ये आर्टिकल्स आपको आसानी से स्प्रिंग बूट सिखा पा रहे है या नहीं। मुझे कमेंट में जरुर बताएं।
टिप्पणियाँ
एक टिप्पणी भेजें