您好,登錄后才能下訂單哦!
先看MVC模式流程圖(其實MVC設(shè)計模式就是java中的model2。):
就像圖上所標識的C層主要是Servlet層控制頁面跳轉(zhuǎn),M層就是具體的業(yè)務(wù)處理邏輯,而JSP就是所謂的V層。MVC是有別于我們所說的三層,我們平常所說的三層是UI層、BLL層、DAL層,具體的區(qū)別如圖:
從圖上能看出來,JSP和Servlet構(gòu)成了UI層,而Model層分成了BLL層和DAL層(也就是業(yè)務(wù)邏輯和數(shù)據(jù)持久層)。
從理論上認清了MVC設(shè)計模式之后,下面開始動手敲一個MVC設(shè)計模式示例代碼:
JSP索引頁面index.jsp:
<%@ page language="java" contentType="text/html; charset=GB18030" pageEncoding="GB18030"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=GB18030"> <title>Insert title here</title> </head> <body> <form action="servlet/addUser.action" method="post"> 姓名:<input type="text" name="username" > <input type="submit" value="提交"> </form> </body> </html>
業(yè)務(wù)邏輯代碼UserManager:
package com.bjpowernode.servlet; import java.util.ArrayList; import java.util.List; public class UserManager { public void addUser(String username){ System.out.println("UserManager.addUsre()--->username:"+username); } public void delUser(String username){ System.out.println("UserManager.delUser()--->username:"+username); } public void modifyUser(String username){ System.out.println("UserManager.modifyUser()--->username"+username); } public List queryUser(String username){ System.out.println("UserManager.queryUser()--->username"+username); List userList=new ArrayList(); userList.add("a"); userList.add("b"); userList.add("c"); return userList; } }
Servlet控制代碼:
package com.bjpowernode.servlet; import java.io.IOException; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class TestServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String requestURI=request.getRequestURI(); System.out.println("request="+requestURI); String path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf(".")); System.out.println("path="+path); String username=request.getParameter("username"); UserManager userManager=new UserManager(); //userManager.addUser(username); String forward=""; if("/servlet/delUser".equals(path)){ userManager.delUser(username); forward="/del_success.jsp"; }else if("/servlet/addUser".equals(path)){ userManager.addUser(username); forward="/add_success.jsp"; }else if("/servlet/modifyUser".equals(path)){ userManager.modifyUser(username); forward="/modify_success.jsp"; }else if("/servlet/queryUser".equals(path)){ List userList=userManager.queryUser(username); request.setAttribute("userList", userList); forward="/query_success.jsp"; }else{ throw new RuntimeException("請求失敗"); } request.getRequestDispatcher(forward).forward(request, response); }
這個servlet代碼主要實現(xiàn)的功能判斷是那個頁面請求服務(wù)器做那些操作,之后調(diào)用業(yè)務(wù)邏輯實現(xiàn)相應(yīng)業(yè)務(wù)操作。
配置Servlet:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>test_Servlet</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>TestServlet</servlet-name> <servlet-class>com.cjq.servlet.TestServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>TestServlet</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping> </web-app>
輸出結(jié)果:
通過上面的示例已經(jīng)對MVC設(shè)計模式有了初步的認識,其實這個示例是對Struts框架學習的基礎(chǔ),只有弄清楚了這個實例才能弄清楚Struts框架的實現(xiàn)原理和Struts框架使用。
那么我們怎么才能通過這個示例引入Struts框架呢?這個問題從IF-Eles開始。
首先我們看到了TestServlet中出現(xiàn)了許多if-else語句,這樣是非常不穩(wěn)定的,這樣的程序是非常不靈活的,以后如果有變化,那么維護是非常差的;而且我們在if-else中出現(xiàn)了大量的字符串,這樣在coding的時候會出現(xiàn)寫錯,這樣無形中給調(diào)試帶來了麻煩。所以去掉if-else成了我們重構(gòu)的第一步,也是我們進行Struts框架學習的第一步。因為在TestServlet中出現(xiàn)了If-Else語句塊,所以讓程序變得不再靈活,讓應(yīng)付需求變化時變得笨拙。所以就承接上篇文章來重構(gòu)一下TestServlet代碼,主要是用繼承多態(tài)來進一步對TestServlet進行重構(gòu)。
下面進入重構(gòu)階段:
package com.bjpowernode.servlet; import java.io.IOException; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class TestServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String requestURI=request.getRequestURI(); System.out.println("request="+requestURI); String path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf(".")); System.out.println("path="+path); String username=request.getParameter("username"); UserManager userManager=new UserManager(); //userManager.addUser(username); String forward=""; if("/servlet/delUser".equals(path)){ userManager.delUser(username); forward="/del_success.jsp"; }else if("/servlet/addUser".equals(path)){ userManager.addUser(username); forward="/add_success.jsp"; }else if("/servlet/modifyUser".equals(path)){ userManager.modifyUser(username); forward="/modify_success.jsp"; }else if("/servlet/queryUser".equals(path)){ List userList=userManager.queryUser(username); request.setAttribute("userList", userList); forward="/query_success.jsp"; }else{ throw new RuntimeException("請求失敗"); } request.getRequestDispatcher(forward).forward(request, response); } }
首先我們看到了在每個語句塊中都出現(xiàn)了給forward賦值,其實也就是給頁面跳轉(zhuǎn)的路徑賦值,針對每個請求路徑判斷來賦值跳轉(zhuǎn)路徑。另外每個IF-Else語句塊中都有業(yè)務(wù)處理,我們要把這些業(yè)務(wù)處理分別放到類里面,讓職責更加單
一,這樣更加符合面向?qū)ο蟮乃悸贰?/p>
就從這里我們開始重構(gòu),我們可以將這個跳轉(zhuǎn)路徑和業(yè)務(wù)邏輯封裝起來。
既然封裝,那么我們就抽象出來一個借口,主要完成一個方法,這個方法主要的功能就是要完成業(yè)務(wù)邏輯封裝和路徑跳轉(zhuǎn)的返回。隨后建立四個類,主要實現(xiàn)相應(yīng)的增刪改查的業(yè)務(wù)處理和處理之后的跳轉(zhuǎn)路徑返回。
代碼如下:
接口Action:
package com.bjpowernode.servlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public interface Action { public String execute(HttpServletRequest request,HttpServletResponse response) throws Exception; }
增刪改查實現(xiàn)類:
添加用戶實現(xiàn)類:
package com.bjpowernode.servlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class AddUserAction implements Action { public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception { String username=request.getParameter("username"); UserManager userManager=new UserManager(); userManager.addUser(username); return "/add_success.jsp"; } }
刪除用戶實現(xiàn)類:
package com.bjpowernode.servlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class DelUserAction implements Action { public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception { String username=request.getParameter("username"); UserManager userManager=new UserManager(); userManager.delUser(username); return "/del_success.jsp"; } }
更新用戶實現(xiàn)類:
package com.bjpowernode.servlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ModifyUserAction implements Action { @Override public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception { String username=request.getParameter("username"); UserManager userManager=new UserManager(); userManager.modifyUser(username); return "/modify_success.jsp"; } }
查詢用戶實現(xiàn)類:
package com.bjpowernode.servlet; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class QueryUserAction implements Action { @Override public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception { String username=request.getParameter("username"); UserManager userManager=new UserManager(); List userList=userManager.queryUser(username); request.setAttribute("userList", userList); return "/query_success.jsp"; } }
TestServlet類重構(gòu)如下:
package com.bjpowernode.servlet; import java.io.IOException; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class TestServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String requestURI=request.getRequestURI(); System.out.println("request="+requestURI); String path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf(".")); System.out.println("path="+path); Action action=null; if("/servlet/delUser".equals(path)){ action=new DelUserAction(); }else if("/servlet/addUser".equals(path)){ action=new AddUserAction(); }else if("/servlet/modifyUser".equals(path)){ action=new ModifyUserAction(); }else if("/servlet/queryUser".equals(path)){ action=new QueryUserAction(); }else{ throw new RuntimeException("請求失敗"); } String forward=null; try{ forward=action.execute(request, response); }catch(Exception e){ e.printStackTrace(); } request.getRequestDispatcher(forward).forward(request, response); } }
運行結(jié)果:
這樣TestServlet類雖然沒有徹底去掉If-Else,但是這樣的代碼變得更加簡練,利用多肽實現(xiàn)業(yè)務(wù)邏輯處理和路徑跳轉(zhuǎn)返回。職責更加清晰,讓維護變得更加輕松。
package com.bjpowernode.servlet; import java.io.IOException; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class TestServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String requestURI=request.getRequestURI(); System.out.println("request="+requestURI); String path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf(".")); System.out.println("path="+path); Action action=null; if("/servlet/delUser".equals(path)){ action=new DelUserAction(); }else if("/servlet/addUser".equals(path)){ action=new AddUserAction(); }else if("/servlet/modifyUser".equals(path)){ action=new ModifyUserAction(); }else if("/servlet/queryUser".equals(path)){ action=new QueryUserAction(); }else{ throw new RuntimeException("請求失敗"); } String forward=null; try{ forward=action.execute(request, response); }catch(Exception e){ e.printStackTrace(); } request.getRequestDispatcher(forward).forward(request, response); } }
解決字符串問題,當然就要用到配置文件了,用到配置文件就要有用來讀取配置文件的相關(guān)的類和方法,這里就用dom4j中的類來讀取配置文件,這里的配置文件的書寫是有點邏輯上的難度的。
我們來看TestServlet中的代碼,我們要在這個testservlet中實現(xiàn)讀取配置文件和path比較,還有利用多肽實例化相應(yīng)的實現(xiàn)類,最后通過實例化的實現(xiàn)類的方法來返回跳轉(zhuǎn)路徑,最終跳轉(zhuǎn)到相應(yīng)的頁面。
所以我們的配置文件就要不僅配上testservlet中出現(xiàn)的字符串,還要配置相應(yīng)的Action接口的實現(xiàn)類(我們可以利用反射來實例化該類的對象,進而使用這個類的所有屬性和方法),另外還有跳轉(zhuǎn)路徑字符串。這樣我們的配置文件就變成了如下代碼所示:
<?xml version="1.0" encoding="UTF-8"?> <action-config> <action path="/servlet/delUser" type="com.cjq.servlet.DelUserAction"> <forward name="success">/del_success.jsp</forward> <forward name="error">/del_error.jsp</forward> </action> <action path="/servlet/addUser" type="com.cjq.servlet.AddUserAction"> <forward name="success">/add_success.jsp</forward> <forward name="error">/add_error.jsp</forward> </action> <action path="/servlet/modifyUser" type="com.cjq.servlet.ModifyUserAction"> <forward name="success">/modify_success.jsp</forward> <forward name="error">/modify_error.jsp</forward> </action> <action path="/servlet/queryUser" type="com.cjq.servlet.QueryUserAction"> <forward name="success">/query_success.jsp</forward> <forward name="error">/query_error.jsp</forward> </action> </action-config>
我們有了配置文件之后就要想法通過相關(guān)類讀取,并且實現(xiàn)相應(yīng)的功能。所以這里用dom4j來讀取完成。其實如果能把這個邏輯捋順之后就能發(fā)現(xiàn),其實懂我們利用dom4j讀取完配置文件的時候,我們是取得的是一個配套的匹配路徑字符串、相應(yīng)業(yè)務(wù)邏輯類還有處理業(yè)務(wù)邏輯之后跳轉(zhuǎn)頁面路徑字符串。這樣我們就能直截了當?shù)娜サ袅薸f-else。(這里可能邏輯上會出現(xiàn)一些困難,但是看到下面的重構(gòu)之后的testservlet中的代碼和讀取配置文件之后的代碼就會一目了然)。
現(xiàn)在等待解決的問題就是我們要把從配置文件取得的一整套內(nèi)容放到那里,當然這是毋庸置疑的要放到類中。所以我們就建立一個ActionMapping類來放我們的那一整套內(nèi)容。
ActionMapping中的代碼如下:
package com.bjpowernode.servlet; import java.util.Map; public class ActionMapping { private String path; private Object type; private Map forwardMap; public String getPath() { return path; } public void setPath(String path) { this.path = path; } public Object getType() { return type; } public void setType(Object type) { this.type = type; } public Map getForwardMap() { return forwardMap; } public void setForwardMap(Map forwardMap) { this.forwardMap = forwardMap; } }
現(xiàn)在ActionMapping類已經(jīng)有了,剩下的工作就是要利用dom4j來讀取配置文件類,具體代碼如下:
package com.bjpowernode.servlet; import java.io.InputStream; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; public class XmlConfigReader { private static XmlConfigReader instance=new XmlConfigReader(); ActionMapping actionMapping=new ActionMapping(); private Document doc; private Map actionMap=new HashMap(); private XmlConfigReader(){ try { SAXReader reader=new SAXReader(); InputStream in=Thread.currentThread().getContextClassLoader().getResourceAsStream("action_config.xml"); doc=reader.read(in); } catch (DocumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public ActionMapping getActionMapping(String path){ synchronized(this){ Object type=null; /*if(action.containsKey(path)){ type=action.get(path); }*/ Element eltAction = (Element)doc.selectObject("http://action[@path=\"" + path + "\"]"); try{ type=Class.forName(eltAction.attributeValue("type")).newInstance(); }catch(Exception e){ e.printStackTrace(); } Element eltForwards = eltAction.element("forward"); for (Iterator iter = eltForwards.elementIterator(); iter.hasNext();) { Element eltForward = (Element) iter.next(); actionMap.put( eltForward.attributeValue("name"),eltForward.getTextTrim()); } actionMapping.setPath(path); actionMapping.setType(type); actionMapping.setForwardMap(actionMap); return actionMapping; } } public static synchronized XmlConfigReader getInstance(){ return instance; } /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub ActionMapping actionMapping=XmlConfigReader.getInstance().getActionMapping("/servlet/delUser"); System.out.println(actionMapping.getPath()); System.out.println(actionMapping.getType()); System.out.println(actionMapping.getForwardMap().toString()); } }
我們通過返回ActionMapping來動態(tài)創(chuàng)建出action相應(yīng)的實現(xiàn)類,進而完成業(yè)務(wù)邏輯和頁面跳轉(zhuǎn),重構(gòu)之后的TestServlet代碼如下:
package com.bjpowernode.servlet; import java.io.IOException; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class TestServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String requestURI=request.getRequestURI(); System.out.println("request="+requestURI); String path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf(".")); System.out.println("path="+path); String forward=""; ActionMapping actionMapping=XmlConfigReader.getInstance().getActionMapping(path); Action action=(Action)actionMapping.getType(); try { forward=action.execute(request, response); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } request.getRequestDispatcher(forward).forward(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } }
我們可以清晰的看到if-else已經(jīng)沒有了,字符串也已經(jīng)沒有了。通過這篇文章對if-else還有字符串問題的解決,又一次重構(gòu)了testservlet代碼,程序相對靈活許多。通過這一次的重構(gòu),我們已經(jīng)看到了struts框架的雛形,
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。