詳解Java的Struts框架和相干的MVC設計理念。本站提示廣大學習愛好者:(詳解Java的Struts框架和相干的MVC設計理念)文章只能為提供參考,不一定能成為您想要的結果。以下是詳解Java的Struts框架和相干的MVC設計理念正文
struts簡介
Struts是Apache軟件基金會(ASF)資助的一個開源項目。它最後是jakarta項目中的一個子項目,並在2004年3月成為ASF的頂級項目。它經由過程采取JavaServlet/JSP技巧,完成了基於JavaEEWeb運用的MVC設計形式的運用框架,是MVC經典設計形式中的一個經典產物。
Struts成長汗青
Struts是作為ApacheJakarta項目標構成部門,項目標創建者願望經由過程對該項目標研討,改良和進步JavaServerPages、servlet、標簽庫和面向對象的技巧水准。
Struts這個名字的起源於在修建和新式飛機中應用的支撐金屬架。之所以這個框架叫做“struts”,是為了提示我們記住那些支持我們衡宇,修建,橋梁,乃至我們踩高跷的基本支持。這也是說明struts在開辟web運用法式中所飾演的腳色的出色描寫。
Struts的寄義是”支柱,枝干”,它的目標是為了削減法式開辟的時光,項目標創立者以為JSP,servlet的存在固然可以贊助用戶處理年夜部門成績,然則因為它們的編碼對項目標開辟帶來了很多的不便利,可重用性也差,所以struts應運而生,贊助用戶在最短的時光內處理這些成績。Struts框架供給以下辦事:
(1)作為掌握器的Servlet。
(2)供給年夜量的標簽庫。
(3)供給了用於國際化的框架,應用分歧的設置裝備擺設文件,可以贊助用戶選擇適合本身的說話。
(4)供給了JDBC的完成,來界說數據源和數據庫銜接池。
(5)XML語法剖析對象。
(6)文件下載機制。
Struts道理
Struts是對JSPModel2設計尺度的一種完成,上面分離從模子(Model)、視圖(view)和掌握器3個部門引見Struts的系統構造和任務道理。挪用流程以下所示。
(1)視圖(view)
在Struts中,視圖層包括兩個部門,JSP頁面和ActionForm。
ActionForm封裝了用戶提交的表單信息,其實ActonForm實質上就是JavaBean,這些JavaBean中沒有營業邏輯,只供給了一切屬性的getter和setter辦法,這些屬性和用戶表單中的輸出項是逐個對應的。在Struts中就是經由過程ActionForm把用戶表單信息提交給掌握器。
JSP頁面是經典MVC中重要的視圖組件,重要是信息顯示和掌握器處置成果顯示的功效。
除以上,struts還供給了一個壯大的struts標簽庫,來贊助用戶處理顯示邏輯,而且應用ActonForm組件將信息傳遞到掌握層。
(2)掌握器(Controller)
在掌握層,struts供給了一個掌握器組件ActionServlet,它繼續自HttpServlet,偏重載了HttpServlet的doGet(),doPost()辦法,可以接收HTTP的呼應,並停止轉發,同時還供給了應用XML停止轉發Mapping(映照)的功效。
(3)模子(Model)
模子表現狀況和營業邏輯的處置,在普通的web運用法式中,用JavaBean或許EJB來完成體系的營業邏輯。在Struts中,struts供給Action對象,來治理營業邏輯的挪用,贊助用戶分別營業邏輯,也就是說struts自己不完成營業邏輯,但可以挪用已完成的營業邏輯。
Struts任務流程
Struts任務流程以下所示。
ActionServlet是struts中焦點的掌握器,一切的用戶要求都必需經由過程ActionServlet的處置,而struts-config.xml是struts中焦點的設置裝備擺設文件,在這個文件中設置裝備擺設了用戶要求URL和掌握器Action的映照關系,ActionServlet經由過程這個設置裝備擺設文件把用戶的要求發送到對應的掌握器中。
在struts web運用法式中,當web運用法式啟動的時刻,就會初始化ActionServlet在初始化ActionServlet的時刻會加載struts-config.xml設置裝備擺設文件,在加載勝利後會把這些URL和掌握器映照關系寄存在ActionMapping對象或許其他對象中。當ActionServlet吸收到用戶要求的時刻,就會依照上面的流程對用戶要求停止處置。
(1)ActionServlet吸收到用戶的要求後,會依據要求URL尋覓婚配的ActionMapping對象,假如婚配掉敗,解釋用戶要求的URL途徑信息有誤,所以前往要求途徑有效的信息,當找到婚配的ActionMapping的時刻,進入到下一步。
(2)當ActionServlet找到婚配的ActionMapping對象的時刻,會依據ActionMapping中的映照信息斷定對應的ActionForm對象能否存在,假如不存在對應的ActionForm對象就創立一個新的ActionForm對應,並把用戶提交的表單信息保留到這個ActionForm對象中。
(3)在struts-config.xml中這個設置裝備擺設文件,可以設置裝備擺設表單能否須要驗證,假如須要驗證,就挪用ActionForm中的validate()辦法對用戶輸出的表單停止驗證。
(4)假如ActionForm的validate()辦法前往了ActionErrors對象,則注解驗證掉敗,ActionServlet把這個頁面前往到用戶輸出的界面,提醒用戶從新輸出。假如辦法的前往值為null,就注解驗證曾經經由過程,可以進入下一步處置。
(5)ActionServlet可以依據ActionMapping對象查找用戶要求轉發給哪一個掌握器Action,假如對應的Action對象不存在,就創立這個對象,並挪用這個Action的excute()辦法。
(6)營業邏輯掌握器Action的execute()辦法就會前往一個ActionForward對象,ActionServlet把掌握器處置的成果轉發到ActionForward對象指定的JSP頁面。
(7)ActionForward對象指定的JSP頁面依據前往的處置成果,用適合情勢把辦事器處置的成果展現給用戶,到這裡為止,一個客戶要求的全部進程終了。
以上初步struts框架停止了引見,和對道理停止了簡略的剖析。至於struts是若何完成MVC的,ActionServlet屬於Controller部門,Action和ActionForm屬於Model層,照樣Action屬於Controller層,分歧的人對struts有分歧的懂得。接上去真實的應用到理論中,在理論中深入去領會,道理雖然主要,主要的是應用,是能駕御和應用這個框架。就像進修開車一樣,不是一揮而就的。
MVC向struts MVC框架演化進程
版本一 根本的MVC
起首是創立一個jsp索引頁面index.jsp,index.jsp創立一個表單。
假如我們完成添加用戶的模塊,我們提交表單的時刻要把這個表單提交給一個servlet,因而我們在src本身的包中樹立本身的servlet繼續HttpServlet,TestServlet同時籠罩父類的doGet和doPost辦法。
提交的的表單信息,我們可以在TestServlet中經由過程request.getParameter(“username”);掏出來。以後把從表單中的數據提交到數據庫,我們的servlet作為掌握器沒有添加到數據庫的職責,因而我們把拜訪數據庫的營業邏輯放到UserManager.java類中。在這個類中完成添加用戶的義務。
package com.bjpowernode.servlet; public class UserManager { public void add(String username) { System.out.println("UserManager.add()-->>"+ username); } }
在TestServlet中挪用UserManager中的辦法。同時讓頁面轉向到添加勝利的頁面add_success.jsp。
TestServlet代碼和在web.xml中設置裝備擺設TestServlet.
<servlet> <servlet-name>TestServlet</servlet-name> <servlet-class>com.bjpowernode.servlet.TestServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>TestServlet</servlet-name> <url-pattern>/servlet/TestServlet</url-pattern> </servlet-mapping>
Testservlet代碼以下所示:
package com.bjpowernode.servlet; import java.io.IOException; import java.util.List; import javax.servlet.ServletException; importjavax.servlet.http.HttpServlet; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; public class TestServlet extendsHttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter(“username”); UserManager userManager = new UserManager(); userManager.add(username); request.getRequestDispatcher(“/add_success.jsp”).forward(request,response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } }
索引頁面index.jsp代碼,經由過程servlet/TestServlet來轉到TestServlet。
<form action="servlet/queryUser.action" method="post"> 姓名:<input type="text" name="username"><br> <input type="submit" value="提交"><br> </form>
如許采取MVC完成了用戶的添加義務。
版本二 經由過程斷定標識變量
當我們不只要完成用戶的添加而是要完成用戶的增刪改查的時刻我們可以在servlet中停止斷定,是添加照樣刪除等。而且在傳遞字符串的時刻要加上一個標識表現響應的操作。如許在servlet中會有許多的if和else語句。
版本三 servlet形式婚配 截取字符串斷定
我們可以在設置裝備擺設servlet的時刻設置裝備擺設成為婚配形式<url-pattern>*.action</url-pattern>任何的*.action的都邑轉到到TestServlet,如許我們可以截取URL來斷定轉到哪一個頁面。但在TestServlet中依然有許多的ifelse語句停止斷定。如許我們的TestServlet代碼以下所示。
import java.io.IOException; import java.util.List; importjavax.servlet.ServletException; importjavax.servlet.http.HttpServlet; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; public class TestServlet extendsHttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //截取url. String requestURI = request.getRequestURI(); //System.out.println("requestURI="+ requestURI); //截取http://localhost:8080/test_servlet/servlet/addUser.action test_servlet前面的器械。 String path = requestURI.substring(requestURI.indexOf("/", 1),requestURI.indexOf(".")); //截獲得到虛目次。/servlet/addUser System.out.println("path="+ path); String username = request.getParameter("username"); UserManager userManager = new UserManager(); String forward = ""; //斷定截取的path和哪一個要加載的頁面相等. if("/servlet/delUser".equals(path)) { userManager.del(username); forward = "del_success.jsp"; //request.getRequestDispatcher("/del_success.jsp").forward(request,response); }else if("/servlet/addUser".equals(path)) { userManager.add(username); forward= "add_success.jsp"; //request.getRequestDispatcher("/add_success.jsp").forward(request,response); }else if("/servlet/modifyUser".equals(path)) { userManager.modify(username); forward= "modify_success.jsp"; //request.getRequestDispatcher("/modify_success.jsp").forward(request,response); }else if("/servlet/queryUser".equals(path)) { List userList = userManager.query(username); request.setAttribute("userList",userList); forward= "query_success.jsp"; //request.getRequestDispatcher("/query_success.jsp").forward(request,response); }else { throw new RuntimeException("要求掉敗!"); } request.getRequestDispatcher(forward).forward(request,response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException { doGet(request,response); } }
UserManager代碼以下所示:
package com.bjpowernode.servlet; import java.util.ArrayList; import java.util.List; public class UserManager { public void add(String username) { System.out.println("UserManager.add()-->>"+ username); } public void del(String username) { System.out.println("UserManager.del()-->>"+ username); } public void modify(String username) { System.out.println("UserManager.modify()-->>"+ username); } public List query(String username) { System.out.println("UserManager.query()-->>"+ username); List userList = new ArrayList(); userList.add("a"); userList.add("b"); userList.add("c"); return userList; } }
同時樹立查詢勝利,刪除勝利,修正勝利jsp頁面。
如許在index.jsp頁面中經由過程表單的action屬性來轉到響應的頁面。
<body> <form action="servlet/queryUser.action" method="post"> 姓名:<input type="text" name="username"><br> <input type="submit" value="提交"><br> </form> </body>
版本三的缺陷是if太多,不穩固,當我們添加或許刪除一個if的時刻還須要從新編譯源法式。如許沒法順應變更的需求。所以我們在此基本長進行改良就須要去失落if語句,可以把轉變的部門分別出來,釀成可設置裝備擺設的,如許就變得靈巧的,須要修改jsp的文件名,在設置裝備擺設文件中設置裝備擺設一下便可以了。
版本四 if else籠統出接口和類+設置裝備擺設文件
起首我們把轉到的地址字符串放到一個字符串變量中,如許TestServlet中的doGet辦法,代碼以下。
String username = request.getParameter("username"); UserManager userManager = new UserManager(); String forward = ""; //斷定截取的path和哪一個要加載的頁面相等. if("/servlet/delUser".equals(path)) { userManager.del(username); forward= "del_success.jsp"; }else if("/servlet/addUser".equals(path)) { userManager.add(username); forward= "add_success.jsp"; }elseif("/servlet/modifyUser".equals(path)) { userManager.modify(username); forward= "modify_success.jsp"; }else if("/servlet/queryUser".equals(path)) { List userList = userManager.query(username); request.setAttribute("userList",userList); forward= "query_success.jsp"; }else { thrownew RuntimeException("要求掉敗!"); } request.getRequestDispatcher(forward).forward(request,response);
同一完成了轉向。當if語句是知足某種前提,前提分歧的時刻轉到分歧的頁面,添加有添加的邏輯,修正有修正的邏輯,如許我們可以籠統出接口。對添加的action操作添加,對刪除的action做出刪除義務,對修正的action做出修正。把每個if語句中的釀成為類去完成,籠統出一個Action接口,接口中辦法execute()辦法,前往轉向途徑字符串。類圖以下所示。
配合的Action接口,分歧的完成。
Action接口代碼。
package com.bjpowernode.servlet; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; public interface Action { public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception; }
package com.bjpowernode.servlet; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; public class AddUserActionimplements Action { @Override public String execute(HttpServletRequest request,HttpServletResponse response) throws Exception { String username = request.getParameter("username"); //Stringsex = request.getParameter("sex"); //........... //挪用營業邏輯. UserManager userManager = new UserManager(); userManager.add(username); return"/add_success.jsp"; } }
DelUserAction代碼。
package com.bjpowernode.servlet; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; public class DelUserActionimplements Action { @Override public String execute(HttpServletRequest request,HttpServletResponse response) throws Exception { String username = request.getParameter("username"); //String sex = request.getParameter("sex"); //........... //挪用營業邏輯. UserManager userManager = new UserManager(); try { userManager.del(username); }catch(Exceptione) { return"del_error.jsp"; } return"/del_success.jsp"; } }
ModifyUserAction代碼。
package com.bjpowernode.servlet; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; public class ModifyUserActionimplements Action { @Override public String execute(HttpServletRequest request,HttpServletResponse response) throwsException { String username = request.getParameter("username"); //String sex = request.getParameter("userId"); //...........等其他... //挪用營業邏輯. UserManager userManager = new UserManager(); userManager.modify(username); return"/modify_success.jsp"; } }
QueryUserAction代碼。
package com.bjpowernode.servlet; import java.util.List; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; public class QueryUserActionimplements Action { @Override public String execute(HttpServletRequest request,HttpServletResponse response) throwsException { String username = request.getParameter("username"); //Stringsex = request.getParameter("userId"); //其他查詢前提. //...........等其他... //挪用營業邏輯. UserManager userManager = new UserManager(); List userList = userManager.query(username); request.setAttribute("userList",userList); return"/query_success.jsp";//轉向途徑都可以經由過程設置裝備擺設文件讀取。 } }
如許應用多態方法挪用分歧的Action,轉向代碼以下所示。
//用多態的方法. 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("要求掉敗!"); } //獲得action後傳遞曩昔。靜態挪用ACtion中的execute辦法。 String forward = null; try{ forward= action.execute(request,response); }catch (Exception e) { e.printStackTrace(); } //依據途徑完成轉向。 request.getRequestDispatcher(forward).forward(request, response);
上述挪用分歧的action,我們可以把分歧的要求和對應的action設置裝備擺設到本身的xml文件中。設置裝備擺設哪一個要求對應哪一個Action。
<action-config> <action path="/servlet/delUser" type="com.bjpowernode.servlet.DelUserAction"> <forward name="success">/del_success.jsp</forward> <forward name="error">/del_error.jsp</forward> </action> <action path="/servlet/addUser" type="com.bjpowernode.servlet.AddUserAction"> <forward name="success">/add_success.jsp</forward> <forward name="error">/add_error.jsp</forward> </action> <action path="/servlet/modifyUser" type="com.bjpowernode.servlet.ModifyUserAction"> <forward name="success">/modify_success.jsp</forward> <forward name="error">/modify_error.jsp</forward> </action> <action path="/servlet/queryUser" type="com.bjpowernode.servlet.QueryUserAction"> <forward name="success">/query_success.jsp</forward> <forward name="error">/query_error.jsp</forward> </action> </action-config>
如許我們便可以讀取設置裝備擺設文件來停止響應的操作。每一個action對應著一些信息,它的class,履行勝利和履行掉敗的設置裝備擺設。我們在讀取設置裝備擺設文件的時刻可以把這些放到Map對象中。代碼以下所示。
ActionMapping { private String path; private String type; Map forwardMap; } forwardMap { key="success"; value="/del_success.jsp" key="error"; value="/del_error.jsp"; } Map map = new HashMap(); map.put("/servlet/delUser",); map.put("/servlet/addUser",); map.put("/servlet/modifyUser",); map.put("/servlet/queryUser",); //假如是刪除的ActionMapping存儲以下: actionMapping { path="/servlet/delUser"; type="com.bjpowernode.servlet.DelUserAction"; forwardMap { key="success",value="/del_success.jsp"; key="error",value="/del_error.jsp"; } } String path ="/servlet/delUser"; //依據截取的URL要求,到Map中獲得本次要求對應的Action。 ActionMapping actionMapping =(ActionMappint)map.get(path); // 獲得本次要求對應的Action類的完成途徑。 String type =actionMappint.getType();//com.bjpowernode.servlet.DelUserAction //經由過程反射靜態實例化Action Aciton action =(Action)class.forName(type).newInstance(); //獲得action後傳遞曩昔。靜態挪用ACtion中的execute辦法。 String forward =action.execute(request,response); //依據途徑完成轉向。 request.getRequestDispatcher(forward).forward(request,response);
我們用時序圖來描寫上述挪用進程(如圖)。
Struts就是采取上述思緒。Struts框架是把上圖中前端掌握器servlet停止了封裝,我們只需繼續struts的Action去挪用營業邏輯和轉向。讀取設置裝備擺設文件的任務也是封裝到了struts框架中。前篇講授了struts框架的運用實例,我們可以停止比較。