थोड़ा सभ्य वेब एप्लिकेशन में डिज़ाइन पैटर्न का मिश्रण होता है। मैं केवल सबसे महत्वपूर्ण लोगों का उल्लेख करूंगा।
जो कोर (आर्किटेक्चरल) डिज़ाइन पैटर्न आप उपयोग करना चाहते हैं, वह मॉडल-व्यू-कंट्रोलर पैटर्न है । नियंत्रक एक सर्वलेट जो (में) सीधे बनाता है द्वारा प्रतिनिधित्व किया जा रहा है / एक विशिष्ट का उपयोग करता है मॉडल और देखें अनुरोध के आधार पर। मॉडल JavaBean वर्गों द्वारा व्यक्त किया जा रहा है। यह अक्सर बिजनेस मॉडल में और अधिक विभक्त होता है जिसमें क्रिया (व्यवहार) और डेटा मॉडल होता है जिसमें डेटा (सूचना) होता है। देखें जो (करने के लिए सीधी पहुँच है JSP फ़ाइलों द्वारा प्रतिनिधित्व किया जा रहा है डाटा ) मॉडल से ईएल (अभिव्यक्ति भाषा)।
फिर, कार्यों और घटनाओं को कैसे नियंत्रित किया जाता है, इसके आधार पर भिन्नताएं हैं। लोकप्रिय हैं:
अनुरोध (कार्रवाई) आधारित MVC : यह लागू करने के लिए सबसे सरल है। ( व्यवसाय ) मॉडल सीधे HttpServletRequest
और HttpServletResponse
वस्तुओं के साथ काम करता है । आपको अनुरोध पैरामीटर को (ज्यादातर) स्वयं इकट्ठा करना, परिवर्तित करना और मान्य करना होगा। देखें सादे वेनिला HTML / CSS / जे एस और इसे बनाए रखने नहीं है अनुरोध भर में राज्य का प्रतिनिधित्व करती जा सकता है। यह दूसरों के बीच स्प्रिंग एमवीसी , स्ट्रट्स और स्ट्राइप्स काम करता है।
घटक आधारित MVC : इसे लागू करना कठिन है। लेकिन आप एक सरल मॉडल के साथ समाप्त होते हैं और देखते हैं कि सभी "कच्चे" सर्वलेट एपीआई पूरी तरह से दूर हो गए हैं। आपको अनुरोध पैरामीटर को स्वयं इकट्ठा करने, बदलने और मान्य करने की आवश्यकता नहीं होनी चाहिए। नियंत्रक इस कार्य को और सेट में एकत्र हुए, परिवर्तित और मान्य अनुरोध पैरामीटर करता है मॉडल । आपको बस उन क्रिया विधियों को परिभाषित करना है जो सीधे मॉडल के गुणों के साथ काम करती हैं। देखें JSP taglibs या XML तत्वों जो बारी में उत्पन्न HTML / CSS / जे एस के स्वाद में "घटक" का प्रतिनिधित्व करती है। दृश्य की स्थितिसत्र में बाद के अनुरोधों को बनाए रखा जाता है। यह सर्वर-साइड रूपांतरण, सत्यापन और मूल्य परिवर्तन की घटनाओं के लिए विशेष रूप से सहायक है। यह कैसे दूसरों JSF , विकेट और खेलने के बीच है! काम करता है।
एक साइड नोट के रूप में, एक होमग्रो एमवीसी फ्रेमवर्क के साथ हॉबीइंग एक बहुत अच्छा सीखने का व्यायाम है, और मैं इसे तब तक करने की सलाह देता हूं जब तक आप इसे निजी / निजी उद्देश्यों के लिए रखते हैं। लेकिन एक बार जब आप पेशेवर जाते हैं, तो यह दृढ़ता से अपने खुद को मजबूत करने के बजाय मौजूदा ढांचे को चुनने की सिफारिश की जाती है। एक मौजूदा और अच्छी तरह से विकसित ढांचे को सीखना अपने आप को एक मजबूत ढांचा विकसित करने और बनाए रखने की तुलना में लंबे समय तक कम समय लगता है।
नीचे दिए गए विस्तृत विवरण में मैं अपने आप को MVC आधारित अनुरोध करने के लिए प्रतिबंधित कर दूंगा क्योंकि इसे लागू करना आसान है।
सबसे पहले, नियंत्रक भाग को फ्रंट नियंत्रक पैटर्न (जो एक विशेष प्रकार का मध्यस्थ पैटर्न है ) को लागू करना चाहिए । इसमें केवल एक सर्वलेट शामिल होना चाहिए जो सभी अनुरोधों का एक केंद्रीकृत प्रवेश बिंदु प्रदान करता है। यह अनुरोध द्वारा उपलब्ध जानकारी के आधार पर मॉडल बनाना चाहिए , जैसे कि pathinfo या सर्वलेट, विधि और / या विशिष्ट पैरामीटर। बिजनेस मॉडल कहा जाता है Action
नीचे में HttpServlet
उदाहरण।
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
Action action = ActionFactory.getAction(request);
String view = action.execute(request, response);
if (view.equals(request.getPathInfo().substring(1)) {
request.getRequestDispatcher("/WEB-INF/" + view + ".jsp").forward(request, response);
}
else {
response.sendRedirect(view); // We'd like to fire redirect in case of a view change as result of the action (PRG pattern).
}
}
catch (Exception e) {
throw new ServletException("Executing action failed.", e);
}
}
कार्रवाई को निष्पादित करते हुए दृश्य का पता लगाने के लिए कुछ पहचानकर्ता को वापस करना चाहिए। सरलतम यह JSP के फ़ाइल नाम के रूप में उपयोग करना होगा। एक विशिष्ट पर इस सर्वलेट मानचित्र url-pattern
में web.xml
, उदाहरण के लिए /pages/*
, *.do
या बस *.html
।
उदाहरण के लिए के रूप में उपसर्ग पैटर्न के मामले में /pages/*
आप तो कर सकते थे आह्वान यूआरएल की तरह है http://example.com/pages/register , http://example.com/pages/login , आदि और प्रदान करते हैं /WEB-INF/register.jsp
, /WEB-INF/login.jsp
उचित प्राप्त और पोस्ट कार्यों के साथ । भागों register
, login
आदि तो request.getPathInfo()
उपरोक्त उदाहरण में उपलब्ध हैं ।
जब आप प्रत्यय-पैटर्न का उपयोग कर रहे हों *.do
, जैसे , *.html
आदि, तब आप URL को http://example.com/register.do , http://example.com/login.do , इत्यादि की तरह लागू कर सकते हैं और आपको बदलना चाहिए इस जवाब में कोड उदाहरण (भी ActionFactory
) के बजाय register
और login
भागों को निकालने के लिए request.getServletPath()
।
Action
का पालन करना चाहिए रणनीति पैटर्न । इसे एक अमूर्त / इंटरफ़ेस प्रकार के रूप में परिभाषित किया जाना चाहिए जो कि अमूर्त पद्धति के पारित-किए गए तर्कों के आधार पर कार्य करना चाहिए (यह कमांड पैटर्न के साथ अंतर है , जिसमें सार / इंटरफ़ेस प्रकार को कार्य के आधार पर करना चाहिए तर्क जो पारित किए गए हैं - कार्यान्वयन के निर्माण के दौरान )।
public interface Action {
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception;
}
आप Exception
जैसे कस्टम अपवाद के साथ अधिक विशिष्ट बनाना चाह सकते हैं ActionException
। यह सिर्फ एक बुनियादी किकऑफ उदाहरण है, बाकी सब आप पर निर्भर है।
यहाँ LoginAction
उपयोगकर्ता में लॉग (जैसा कि उसका नाम कहता है) का एक उदाहरण है । User
खुद बारी एक में है डेटा मॉडल । देखें की उपस्थिति के बारे में पता है User
।
public class LoginAction implements Action {
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
String username = request.getParameter("username");
String password = request.getParameter("password");
User user = userDAO.find(username, password);
if (user != null) {
request.getSession().setAttribute("user", user); // Login user.
return "home"; // Redirect to home page.
}
else {
request.setAttribute("error", "Unknown username/password. Please retry."); // Store error message in request scope.
return "login"; // Go back to redisplay login form with error.
}
}
}
ActionFactory
का पालन करना चाहिए फैक्टरी विधि पैटर्न । मूल रूप से, यह एक रचनात्मक तरीका प्रदान करना चाहिए जो एक अमूर्त / इंटरफ़ेस प्रकार का एक ठोस कार्यान्वयन लौटाता है। इस मामले में, इसे Action
अनुरोध द्वारा प्रदान की गई जानकारी के आधार पर इंटरफ़ेस का कार्यान्वयन वापस करना चाहिए । उदाहरण के लिए, विधि और pathinfo (pathinfo अनुरोध URL में संदर्भ और सर्वलेट पथ के बाद का हिस्सा है, क्वेरी स्ट्रिंग को छोड़कर)।
public static Action getAction(HttpServletRequest request) {
return actions.get(request.getMethod() + request.getPathInfo());
}
actions
बदले में कुछ स्थिर / applicationwide होना चाहिए Map<String, Action>
जो सभी ज्ञात कार्यों रखती है। यह आप पर निर्भर है कि इस नक्शे को कैसे भरें। कठिन कोडिंग:
actions.put("POST/register", new RegisterAction());
actions.put("POST/login", new LoginAction());
actions.put("GET/logout", new LogoutAction());
// ...
या क्लासपैथ में एक गुण / XML कॉन्फ़िगरेशन फ़ाइल के आधार पर विन्यास योग्य: (छद्म)
for (Entry entry : configuration) {
actions.put(entry.getKey(), Class.forName(entry.getValue()).newInstance());
}
या एक निश्चित इंटरफ़ेस और / या एनोटेशन को लागू करने वाली कक्षाओं के लिए क्लासपैथ में स्कैन के आधार पर गतिशील रूप से: (छद्म)
for (ClassFile classFile : classpath) {
if (classFile.isInstanceOf(Action.class)) {
actions.put(classFile.getAnnotation("mapping"), classFile.newInstance());
}
}
Action
कोई मैपिंग नहीं होने वाले मामले के लिए "कुछ भी नहीं" बनाने के लिए ध्यान रखें । उदाहरण के लिए इसे सीधे वापस आने दें request.getPathInfo().substring(1)
।
अन्य पैटर्न
वे अब तक के महत्वपूर्ण पैटर्न थे।
आगे एक कदम पाने के लिए, आप एक वर्ग बनाने के लिए मुखौटा पैटर्न का उपयोग कर सकते हैं, Context
जो बदले में अनुरोध और प्रतिक्रिया वस्तुओं को लपेटता है और अनुरोध और प्रतिक्रिया वस्तुओं को सौंपते हुए कई सुविधा विधियां प्रदान करता है और उस तर्क को Action#execute()
विधि के रूप में पारित करता है । यह कच्चे सर्वलेट एपीआई को दूर छिपाने के लिए एक अतिरिक्त सार परत जोड़ता है। फिर आपको मूल रूप से हर कार्यान्वयन में शून्य import javax.servlet.*
घोषणाओं को समाप्त करना चाहिए Action
। JSF के संदर्भ में, यह वही है जो FacesContext
और ExternalContext
वर्ग कर रहे हैं। आप इस जवाब में एक ठोस उदाहरण पा सकते हैं ।
फिर उस मामले के लिए राज्य पैटर्न है जिसे आप अनुरोध पैरामीटर को इकट्ठा करने, उन्हें परिवर्तित करने, उन्हें मान्य करने, मॉडल मूल्यों को अपडेट करने और कार्यों को निष्पादित करने के कार्यों को विभाजित करने के लिए एक अतिरिक्त अमूर्त परत जोड़ना चाहते हैं। जेएसएफ के संदर्भ में, यह वही है जो LifeCycle
कर रहा है।
फिर उस मामले के लिए समग्र पैटर्न है जिसे आप एक घटक आधारित दृश्य बनाना चाहते हैं जिसे मॉडल के साथ जोड़ा जा सकता है और जिसका व्यवहार अनुरोध आधारित जीवनचक्र की स्थिति पर निर्भर करता है। जेएसएफ के संदर्भ में, यह वही है जो UIComponent
प्रतिनिधित्व करता है।
इस तरह आप एक घटक आधारित ढांचे की ओर थोड़ा सा विकसित कर सकते हैं।
यह सभी देखें: