本文實例為大家分享了struts2自定義MVC框架的方法,供大家參考,具體內(nèi)容如下
自定義MVC: (首先了解Model1和Model2的概念)
Model1與Model2:
Model1:就是一種純jsp開發(fā)技術(shù),將業(yè)務(wù)邏輯代碼和視圖渲染代碼雜糅在一起。
Model2:Model2是在Model1的基礎(chǔ)上,將業(yè)務(wù)邏輯的代碼分離開來,單獨形成一個Servlet,Model2也是基于MVC開發(fā)。
總結(jié)MVC特點如下:
(1)數(shù)據(jù)的獲取和顯示分離
(2)控制器將不同的模型和視圖組合在一起
(3)應(yīng)用分為三部分,三部分之間松耦合并協(xié)同工作,從而提高應(yīng)用的可擴(kuò)展性和可維護(hù)性
(4)各層負(fù)責(zé)不同的功能,各司其職,每一層的組件具有相同的特征,便于通過工程化和工具化產(chǎn)生程序代碼
MVC思想及其優(yōu)勢(很強(qiáng)勢)
MVC是一種架構(gòu)模式,目的是將模型(業(yè)務(wù)邏輯)、視圖(表示層)分離,使模型和視圖可以獨立修改互不影響。大多數(shù)軟件在設(shè)計架構(gòu)時都采用此模式。使用MVC模式有很多處,當(dāng)一個通過瀏覽器瀏覽的系統(tǒng)想要開發(fā)手機(jī)版本時,只需要重新開發(fā)視圖,模型部分的業(yè)務(wù)邏輯可以重用。許多軟件需要同時推出B/S和C/S版本,采用MVC模式,模型部分可以重用,只需要開發(fā)不同的視圖即可。MVC思想將一個應(yīng)用分成三個基本部分M(Model,模型)V(View,視圖)C(Controller,控制器)。其中M表示處理業(yè)務(wù)邏輯的部分,V表示顯示數(shù)據(jù)和獲取用戶輸入的部分,C類似中介,保證M和V不會直接交互。
基本步驟如下:
1.創(chuàng)建XML文檔Framework.xml
2.定義Action接口
3.定義一個actionMapping類,視為action節(jié)點
4.定義ActionMappingManage類來管理ActionMapping類(actions節(jié)點)
5.定義ActionManager類使用反射機(jī)制根據(jù)字符串類型的類名獲取到具體的類(web.xml標(biāo)簽的書寫)
6.編寫servlet進(jìn)行運行時機(jī)的控制
7.定義LoginAction類進(jìn)行測試
1.創(chuàng)建XML文檔Framework.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
<!--?xml version="1.0" encoding="UTF-8"?--> <!-- 定義約束文件 --> (標(biāo)注) <!-- ELEMENT 表示元素 --> <!-- ATTLIST 表示屬性 --> <!-- CDATA 表示字符串類型 --> <!-- REQUIRED 表示此屬性必須的寫 --> <!-- *代表多個 --> <!-- IMPLIED 表示此屬性可寫 --> <!-- redirect 重定向或轉(zhuǎn)發(fā) --> <!--ELEMENT actions (action)--> <!--ELEMENT action (result*)--> (*表示可以多個) <!--ATTLIST action name CDATA #REQUIRED class CDATA #REQUIRED --> <!--ATTLIST RESULT name CDATA #IMPLIED redirect (true|false) "false" --> ]> < framework > <!-- 進(jìn)行測試 --> < actions > < action name = "loginAction" class = "cn.hq.Action.LoginAction" > < result name = "success" >success.jsp</ result > < result name = "login" >index.jsp</ result > </ action > </ actions > </ framework > |
注意:空格和<>的書寫規(guī)范。
節(jié)點的層次。
2.定義Action接口
注意:excute參數(shù)的書寫,請求和響應(yīng)。
3.定義一個actionMapping類,視為action節(jié)點(進(jìn)行action節(jié)點的標(biāo)簽的書寫)
進(jìn)行封裝字段和results集合的添加數(shù)據(jù)。
注意:添加數(shù)據(jù)的書寫。(Map集合)
4.定義ActionMappingManage類來管理ActionMapping類(actions節(jié)點)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
/* * action節(jié)點不止一個 * 用來來管理ActionMapping類 */ public class ActionMappingManager { //actionMapping類的集合 private Map<String,ActionMapping> maps= new HashMap<String,ActionMapping>(); public ActionMapping getActionMapping(String name) { return maps. get (name); } //解析在src項目下的所有配置文件 //實例化完畢后進(jìn)行解析 public ActionMappingManager(String[] file){ for (String filename : file) { Init(filename); } } //init初始化方法 //解析xml文檔 public void Init(String path){ try { InputStream is = this .getClass().getResourceAsStream( "/" +path); //解析xml Document doc= new SAXReader().read( is ); //獲取根節(jié)點 Element root = doc.getRootElement(); //獲取actions節(jié)點 Element actions=(Element)root.elementIterator( "actions" ).next(); //使用for循環(huán)來遍歷actions節(jié)點下的所有action節(jié)點 for (Iterator<Element> action=actions.elementIterator( "action" );action.hasNext();) { //獲取到<action>節(jié)點 Element actionnext = action.next(); //分別獲取到action節(jié)點中的name屬性和class屬性 String name = actionnext.attributeValue( "name" ); String classname = actionnext.attributeValue( "class" ); //將以上兩個屬性保存到ActionMapping類中 ActionMapping mapp= new ActionMapping(); mapp.setClassname(classname); mapp.setName(name); //由于一個action節(jié)點下有多個result節(jié)點 遍歷action下所有的result節(jié)點 for (Iterator<Element> result=actionnext.elementIterator( "result" );result.hasNext();) { //獲取到result節(jié)點 Element resultnext = result.next(); //提取result節(jié)點的name屬性值和result節(jié)點中的值 String resultname = resultnext.attributeValue( "name" ); String resultvalue=resultnext.getText(); //將其分別存入到actionMapping中的雙列集合中去,方便調(diào)用actionMapping類(actionMapping類中就有數(shù)據(jù)了!) mapp.addResult(resultname, resultvalue); System. out .println(mapp.getName()); } //得到所有action節(jié)點的集合 maps.put(mapp.getName(), mapp); } } catch (Exception e) { // TODO: handle exception } } } |
概括:
通過dom4j解析Framework.xml配置文件。從而獲取根節(jié)點,以及actions節(jié)點,并通過for循環(huán)遍歷actions節(jié)點下的action節(jié)點拿到name和class的屬性值,由于一個action節(jié)點下有多個result節(jié)點 及遍歷action下所有的result節(jié)點,分別存入到actionMapping中的雙列集合中,最后得到所有action節(jié)點的集合。
注意:Init方法的書寫,以及ActionMappingManager帶參數(shù)組的書寫。
5.定義ActionManager類使用反射機(jī)制根據(jù)字符串類型的類名獲取到具體的類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
public class ActionManager { public static Action getActionClass(String classname) { Class clazz= null ; Action action= null ; //獲取當(dāng)前線程的類加載器 try { //如果線程中的有那么一個類,直接根據(jù)類名獲取該類的類型 clazz=Thread.currentThread().getContextClassLoader().loadClass(classname); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (clazz== null ) { try { //如果該線程中沒有,那么使用class.forname方法獲取 clazz=Class.forName(classname); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if (action== null ) { try { //將獲取到的類型轉(zhuǎn)換為action,調(diào)用無參構(gòu)造函數(shù),某種程度上相當(dāng)于new,不過new需要指定類型 action=(Action)clazz.newInstance(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return action; } } |
web.xml的節(jié)點配置:
6.編寫servlet進(jìn)行運行時機(jī)的控制(servlet,初始化所有的類)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
public class MyServlet extends HttpServlet { /** *你很菜 */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); }<br> /** *繼續(xù)努力 */ ActionMappingManager man= null ; public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //獲取ActionMapping對象 ActionMapping actionMapping = man.getActionMapping(getPath(request)); //獲取action接口反射機(jī)制 Action action = ActionManager.getActionManager(actionMapping.getClassname()); try { String message=action.execute(request, response); String results = actionMapping.getResults(message); response.sendRedirect(results); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /* * 獲取請求的路徑名 */ public String getPath(HttpServletRequest request){ //項目+請求地址 String requestURI = request.getRequestURI(); //項目名稱 String contextPath = request.getContextPath(); //具體請求 String path = requestURI.substring(contextPath.length()); String filename = path.substring(1,path.lastIndexOf( "." )); return filename; } /* *重寫init,程序運行加載所有類 * */ @Override public void init(ServletConfig config) throws ServletException { //config對象是javax.servlet.ServletConfig的對象,功能是獲得初始化配置信息 //config.getInitParameter是取得指定名稱的初始化參數(shù)內(nèi)容 String filename = config.getInitParameter( "config" ); String [] filenames= null ; if (filename== null ){ //如果為空 , filenames= new String[]{ "Framework.xml" }; } else { //若果有其他的配置參數(shù)信息,那么以,分隔存入數(shù)組中 filenames=filename.split( "," ); } //使用init方法進(jìn)行初始化 man= new ActionMappingManager(filenames); } } |
注意:代碼的層次及注釋。
7.定義LoginAction類進(jìn)行測試
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public class LoginAction implements Action{ @Override public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception { String name = request.getParameter( "name" ); String pwd = request.getParameter( "pwd" ); if (name.equals( "1" )&&pwd.equals( "1" )){ return SUCCESS; } else { return LOGIN; } } } |
jsp代碼:
實現(xiàn)效果:
再長的路,一步步也能走完,再短的路,不邁開雙腳也無法到達(dá)。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。