Biraz iyi bir web uygulaması tasarım desenlerinin bir karışımından oluşur. Sadece en önemlilerinden bahsedeceğim.
Kullanmak istediğiniz çekirdek (mimari) tasarım deseni Model-Görünüm-Denetleyici desenidir . Denetleyici (in) doğrudan oluşturan bir Servlet tarafından temsil edilecek / spesifik kullanır Modeli ve Görünüm isteğine dayanarak. Model Javabean sınıfları tarafından temsil edilmesi. Bu genellikle eylemleri (davranış) içeren İş Modeli ve verileri (bilgileri) içeren Veri Modeli'nde daha da bölünebilir . Görünüm (doğrudan erişime sahip JSP dosyaları tarafından temsil edilecek veriler ) Model EL (Expression Dil) tarafından.
Ardından, eylemlerin ve olayların nasıl ele alındığına bağlı olarak farklılıklar vardır. Popüler olanlar:
İstek (işlem) tabanlı MVC : uygulanması en basit olanıdır. ( İş ) Modeli doğrudan HttpServletRequest
ve HttpServletResponse
nesnelerle çalışır . İstek parametrelerini (çoğunlukla) kendiniz toplamanız, dönüştürmeniz ve doğrulamanız gerekir. Görünüm istekleri karşısında düz vanilya HTML / CSS / JS ve tutmaz devlet tarafından temsil edilebilir. Diğerleri arasında Bahar MVC , Struts ve Stripes çalışır.
Bileşen tabanlı MVC : uygulanması daha zordur. Ancak sonuçta daha basit bir model ve görünüm elde edersiniz; burada tüm "raw" Servlet API'si tamamen kaldırılır. İstek parametrelerini kendiniz toplamanız, dönüştürmeniz ve doğrulamanız gerekmez. Kontrolör bu görevi yapar ve toplanan, dönüştürülmüş ve valide istek parametreleri ayarlar Modeli . Tek yapmanız gereken, doğrudan model özellikleriyle çalışan eylem yöntemlerini tanımlamaktır. Görünüm JSP taglibs veya sırayla / JS HTML / CSS oluşturur XML öğelerinin lezzet "bileşenleri" ile temsil edilir. Devlet Görünüm sonraki isteği oturumda korunur. Bu, özellikle sunucu tarafı dönüştürme, doğrulama ve değer değiştirme olayları için yararlıdır. Diğerleri arasında JSF , Wicket ve Play! İşler.
Bir yan not olarak, ev yapımı bir MVC çerçevesiyle hobi yapmak çok güzel bir öğrenme egzersizidir ve kişisel / özel amaçlar için sakladığınız sürece bunu tavsiye ederim. Ancak profesyonelleştikten sonra, kendi çerçevenizi yeniden keşfetmek yerine mevcut bir çerçeveyi seçmeniz şiddetle tavsiye edilir. Mevcut ve iyi gelişmiş bir çerçeveyi öğrenmek, sağlam bir çerçeveyi kendiniz geliştirmekten ve sürdürmekten daha uzun zaman alır.
Aşağıdaki ayrıntılı açıklamada, uygulanması daha kolay olduğu için kendimi temelli MVC istemeyle sınırlayacağım.
İlk olarak, Kontrolör kısmı, Ön Kontrol modelini (özel bir tür Arabulucu modeli ) uygulamalıdır. Tüm isteklerin merkezi bir giriş noktasını sağlayan tek bir sunucu uygulamasından oluşmalıdır. OluşturmalıModeli , pathinfo veya servletpath, yöntem ve / veya belirli parametreler gibi istek tarafından sağlanan bilgilere dayanarak . İş Modeli olarak adlandırılan Action
aşağıda HttpServlet
örnek.
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);
}
}
Eylemin yürütülmesi, görünümü bulmak için bazı tanımlayıcılar döndürmelidir. En basit olanı, JSP'nin dosya adı olarak kullanmak olacaktır. Belli bir bölüme bu sunucu uygulamasını Harita url-pattern
içinde web.xml
örneğin /pages/*
,*.do
hatta sadece *.html
.
Örneğin önek kalıpları olması durumunda, http://example.com/pages/register , http://example.com/pages/login/pages/*
gibi URL'leri çağırabilirsiniz. , vb ve sağlamak /WEB-INF/register.jsp
, /WEB-INF/login.jsp
uygun GET ve POST eylemlerle . Parçalar register
, login
vb. Daha sonra request.getPathInfo()
yukarıdaki örnekte olduğu gibi kullanılabilir .
, Vb. Gibi ek kalıpları kullanırken *.do
, http://example.com/register.do , http://example.com/login.do , vb. *.html
Gibi URL'leri çağırabilirsiniz . kodları bu cevapta (ayrıca ) kodlamak yerine ve parçaları .ActionFactory
register
login
request.getServletPath()
Action
İzlemelidir Strateji deseni . Soyut yöntemin aktarılmış argümanlarına dayanarak işi yapması gereken bir soyut / arayüz tipi olarak tanımlanması gerekir (bu, komut model Anahtar / arabirimi göre işi, ki burada, uygulamanın oluşturulması sırasında aktarılan argümanlar ).
public interface Action {
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception;
}
Gibi Exception
özel bir istisna ile daha belirgin hale getirmek isteyebilirsinizActionException
. Bu sadece temel bir başlama örneği, gerisi tamamen size kalmış.
Aşağıda, LoginAction
(adından da anlaşılacağı gibi) kullanıcının oturum açtığı bir örnek bulunmaktadır . User
Kendisi sırayla bir olduğunu Veri Modeli . Görünüm varlığının farkındadır 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
İzlemelidir Fabrika yöntemi desen . Temel olarak, bir soyut / arayüz türünün somut bir uygulamasını döndüren yaratıcı bir yöntem sağlamalıdır. Bu durumda, Action
istek tarafından sağlanan bilgilere dayanarak arabirimin bir uygulamasını döndürmelidir . Örneğin, yöntem ve pathinfo (pathinfo, sorgu dizesi hariç istek URL'sindeki bağlam ve sunucu uygulaması yolundan sonraki bölümdür).
public static Action getAction(HttpServletRequest request) {
return actions.get(request.getMethod() + request.getPathInfo());
}
Buna actions
karşılık, Map<String, Action>
bilinen tüm eylemleri tutan bir statik / uygulama çapında olmalıdır . Bu haritayı nasıl dolduracağınız size kalmış. hardcoding:
actions.put("POST/register", new RegisterAction());
actions.put("POST/login", new LoginAction());
actions.put("GET/logout", new LogoutAction());
// ...
Veya sınıf yolundaki bir özellikler / XML yapılandırma dosyasına dayalı olarak yapılandırılabilir: (sözde)
for (Entry entry : configuration) {
actions.put(entry.getKey(), Class.forName(entry.getValue()).newInstance());
}
Veya belirli bir arabirimi ve / veya ek açıklamayı uygulayan sınıflar için sınıf yolundaki bir taramayı temel alarak: (sözde)
for (ClassFile classFile : classpath) {
if (classFile.isInstanceOf(Action.class)) {
actions.put(classFile.getAnnotation("mapping"), classFile.newInstance());
}
}
Action
Eşleme olmaması durumunda "hiçbir şey yapma" oluşturmayı unutmayın . Örneğin doğrudan o request.getPathInfo().substring(1)
zaman dönmesine izin verin .
Diğer desenler
Bunlar şimdiye kadarki önemli kalıplardı.
Bir adım daha ileri gitmek için , istek ve yanıt nesnelerini saran ve istek ve yanıt nesnelerine yetki veren ve bunun yerine yönteme argüman olarak ileten çeşitli kolaylık yöntemleri sunan bir sınıf oluşturmak için Cephe desenini kullanabilirsiniz . Bu, ham Servlet API'sını gizlemek için ekstra bir soyut katman ekler. Daha sonra temel olarak her uygulamada sıfır bildirim ile sonuçlanmalısınız . JSF açısından, ve sınıfları bunu yapıyor. Somut bir örnek bulabilirsinizContext
Action#execute()
import javax.servlet.*
Action
FacesContext
ExternalContext
Bu cevapta .
Ardından , istek parametrelerini toplama, dönüştürme, doğrulama, model değerlerini güncelleme ve eylemleri yürütme görevlerini bölmek için fazladan bir soyutlama katmanı eklemek istediğiniz durum için Devlet modeli vardır . JSF açısından, bu neLifeCycle
yapıyor.
Ardından , modele eklenebilen ve davranışı istek tabanlı yaşam döngüsünün durumuna bağlı olan bileşen tabanlı bir görünüm oluşturmak istediğiniz durum için Bileşik desen vardır . JSF açısından, bu neUIComponent
temsil budur.
Bu şekilde, bileşen tabanlı bir çerçeveye doğru yavaş yavaş gelişebilirsiniz.
Ayrıca bakınız: