Struts2概述與MVC模式

truts分爲兩個主要版本,struts1和struts2,struts2是由webwork2發展而來的

1、Framework概念:將相同類型問題的解決途徑進行抽象,抽取成爲一個應用框架。這就是Framework。

Framework的體系提供了一套明確的機制,從而讓開發人員很容易寬展和控制整個Framework開發上的結構;通常,Framework的結構中都有一個“命令和控制”組件(“command and control” component)

    通過基於請求響應模式的應用Framework,基本上有如下幾個表現邏輯結構組成:
    - 控制器(Controller)——控制整個Framework中各個組件的協調工作。
    - 業務邏輯層(Business Logic)——對Framework本身來說,這裏僅僅只是概念和幾個提供服務的基礎組件,真正的實現與客戶的業務邏輯接軌,還需要開發人員在Framework上再次擴展。
    - 數據邏輯層(Data Logic ) ——絕大多數應用系統都需要涉及到數據交互,這一層主要包括了數據邏輯和數據訪問接口
2、Struts有其自己的控制器(Controller),同時整合了其他的一些技術去實現模型層(Model)和視圖層(View)。

Struts的概念和體系結構

    Struts有一組相互協作的類、Servlet以及Jsp TagLib組成。基於Struts架構的web應用程序基本上符合JSP Model2的設計標準,可以說是MVC設計模式的一種變化類型。

3、MVC的概念,MVC結構圖

MVC處理過程:

    - 首先控制器接收用戶的請求,並決定應該調用哪一個模型來進行處理。
    - 然後模型根據用戶請求進行相應的業務邏輯處理,並返回數據。
    - 最後控制器調用相應的視圖格式化模型返回的數據,並通過視圖呈現給用戶,

MVC的優點:

   - 首先,最重要的一點是多個視圖能共享一個模型。同一個模型可以被不同的視圖重用,大大提高了代碼的可重用性。
   - 由於MVC的三個模塊相互獨立,改變其中一個不會影響其他兩個,所以依據這種設計思想能構造良好的松耦合的構件。
   - 此外,控制器提高了應用程序的靈活性和可配置性。控制器可以用來聯接不同的模型和視圖去完成用戶的需求,這樣控制器可以爲構造應用程序提供強有力的手段

MVC的適用範圍

    - 使用MVC需要精心的計劃,由於它的內部原理比較複雜,所以你需要花費一些時間去理解它。將MVC運用到你的應用程序,會帶來額外的工作量,增加應用的複雜性。
    - 但對於開發存在大量用戶界面,並且業務邏輯複雜的大型應用程序,MVC將會使你的軟件在健壯性、代碼重用和結構方面上一個新的臺階。儘管在最初構建MVC框架時會花費一定的工作量,但從長遠角度看,它會大大提高後期軟件開發的效率。

4、JavaWeb應用結構的發展

    - 階段1:JSP是一個獨立的、自主完成所有任務的模塊
    - 階段2:JSP Model1
    - 階段3:JSP Model2

早期的Java Web應用中,JSP文件同時負責生成網頁、控制到下一個網頁的流程,以及負責業務邏輯,這給Web開發帶來一系列問題:
–HTML 和Java 強耦合在一起,JSP 文件的編寫者必須既是網頁設計者,又是Java 開發者。
–可讀性差。
–調試困難。
–不利於維護,更改業務邏輯或數據可能牽涉相關的多個網頁。

Model1

Model2:

•JSP負責生成動態網頁
•Servlet負責流程控制
•JavaBean負責業務邏輯

5、Struts與Web App的關係
–既然struts叫做webframework,那麼其肯定主要基於web層的應用系統開發。按照J2EEArchitecture的標準,struts應當和jsp/servlet一樣,存在於webcontainer一層

6、完全手動配置一個Struts程序

    1)下載struts-2.3.14-all.zip,解壓縮,四個文件夾:apps,示例,是.war;lib目錄,庫,struts依賴的一些包,庫;docs,文檔;src,源代碼
    2)myeclipse中創建一個web project
    3)導入jar包,不能將解壓出的lib目錄下的Jar包都拷入項目的WebRoot/WEB-INF/lib下,多拷貝也能出問題,最小需求包有:commons-fileupload-1.2.2.jar、commons-io-2.0.1.jar、commons-logging-1.1.1.jar、ognl-3.0.6.jar、struts2-core-2.3.14.jar、xwork-core-2.3.14.jar、freemarker-2.3.19.jar
    4)修改web.xml,添加struts過濾器:

[html] view plain copy
  1. <filter>  
  2.     <filter-name>struts2</filter-name>  
  3.     <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>  
  4.   </filter>  
  5.     
  6.   <filter-mapping>  
  7.     <filter-name>struts2</filter-name>  
  8.     <url-pattern>/*</url-pattern>  
  9.   </filter-mapping>  


在這裏的filter配置就說明添加上了struts框架,所有的應用都納入到了struts的管轄範圍了。

    5)在src目錄下創建struts.xml文件,注意,我們的應用運行時訪問的不是src目錄下的這個struts.xml,而是WebRoot\WEB-INF\classes目錄下的struts.xml,任何src目錄下的東西,IDE(myeclipse)都會自動拷貝一份到WebRoot\WEB-INF\classes目錄下,爲什麼不直接在WebRoot\WEB-INF\classes下建呢?因爲在IDE中看不到classes目錄。

創建好struts.xml後,從apps中的現有struts.xml中拷貝頭幾行,如下:

[html] view plain copy
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <!DOCTYPE struts PUBLIC  
  3.     "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"  
  4.     "http://struts.apache.org/dtds/struts-2.3.dtd">  


這時在寫下面內容時,如果沒有提示功能,可以這樣解決:

      a: 點擊window – preferences – 搜索 catalog – add

     b:選擇key type爲URI

     c:key: http://struts.apache.org/dtds/struts-2.3.dtd    該文件是 struts.xml文件中的,複製即可

     d:location: 對應的dtd文件,位於struts-core包中,解壓開,指定相應位置,

      如:D:\Struts2.1.6\soft\struts- 2.1.6 \lib\struts2-core-2.1.6\struts-2.3.dtd

    6)做完以上配置啓動服務器,會出現錯誤,根據錯誤提示,是缺少jar依賴包,添加了javassist-3.11.0.GA.jar、asm-3.3.jar、asm-commons-3.3.jar、commons-lang3-3.1.jar、commons-lang-2.4.jar、struts2-convention-plugin-2.3.14.jar後啓動正常。

    7)編寫測試程序

一個登錄頁面login.jsp:

[html] view plain copy
  1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>  
  2. <%  
  3. String path = request.getContextPath();  
  4. String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";  
  5. %>  
  6.   
  7. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
  8. <html>  
  9.   <head>  
  10.     <base href="<%=basePath%>">  
  11.       
  12.     <title>My JSP 'login.jsp' starting page</title>  
  13.       
  14.     <meta http-equiv="pragma" content="no-cache">  
  15.     <meta http-equiv="cache-control" content="no-cache">  
  16.     <meta http-equiv="expires" content="0">      
  17.     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">  
  18.     <meta http-equiv="description" content="This is my page">  
  19.     <!-- 
  20.     <link rel="stylesheet" type="text/css" href="styles.css"> 
  21.     -->  
  22.   
  23.   </head>  
  24.     
  25.   <body>  
  26.     <form action="aas.action">  
  27.         username:<input type="text" name="username"><br>  
  28.         password:<input type="password" name="password"><br>  
  29.         <input type="submit" value="submit">  
  30.     </form>  
  31.   </body>  
  32. </html>  


一個結果頁面result.jsp

[html] view plain copy
  1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>  
  2. <%  
  3. String path = request.getContextPath();  
  4. String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";  
  5. %>  
  6.   
  7. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
  8. <html>  
  9.   <head>  
  10.     <base href="<%=basePath%>">  
  11.       
  12.     <title>My JSP 'result.jsp' starting page</title>  
  13.       
  14.     <meta http-equiv="pragma" content="no-cache">  
  15.     <meta http-equiv="cache-control" content="no-cache">  
  16.     <meta http-equiv="expires" content="0">      
  17.     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">  
  18.     <meta http-equiv="description" content="This is my page">  
  19.     <!-- 
  20.     <link rel="stylesheet" type="text/css" href="styles.css"> 
  21.     -->  
  22.   
  23.   </head>  
  24.     
  25.   <body>  
  26.     username:${requestScope.username } <br>  
  27.     password:${requestScope.password }  
  28.   </body>  
  29. </html>  


一個class:LoginAction

[java] view plain copy
  1. package com.cdtax.struts2;  
  2.   
  3.   
  4.   
  5. public class LoginAction   
  6. {  
  7.     private String username;  
  8.     private String password;  
  9.       
  10.     public String getUsername()  
  11.     {  
  12.         return username;  
  13.     }  
  14.     public void setUsername(String username)  
  15.     {  
  16.         this.username = username;  
  17.     }  
  18.     public String getPassword()  
  19.     {  
  20.         return password;  
  21.     }  
  22.     public void setPassword(String password)  
  23.     {  
  24.         this.password = password;  
  25.     }  
  26.       
  27.       
  28.       
  29.     public String execute()  
  30.     {  
  31.         System.out.println("execute()......");  
  32.         return "success";  
  33.     }  
  34. }  


然後配置struts.xml

[html] view plain copy
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <!DOCTYPE struts PUBLIC  
  3.     "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"  
  4.     "http://struts.apache.org/dtds/struts-2.3.dtd">  
  5.   
  6. <struts>  
  7.     <package name="struts2" extends="struts-default">  
  8.         <action name="aas" class="com.cdtax.struts2.LoginAction">  
  9.             <result name="success">/result.jsp</result>  
  10.         </action>  
  11.     </package>  
  12. </struts>  


啓動服務器,然後訪問login.jsp,輸入用戶名密碼提交直接就返回一個result頁面。

一開始在配置struts.xml時,將action配置成如:<action name="login" class="com.cdtax.struts2.LoginAction">,login.jsp中的action爲login.action,結果死活出不來結果,一直提示No result defined for action com.cdtax.struts2.LoginAction and result success,經過查資料,在struts.xml中action 的name="login"是有衝突的。

至此,手工配置一個struts2.3.14環境完成。

7、通過上面的例子,在struts中,重要的是struts.xml中的配置

由web.xml中的filter可知(url-pattern爲 /*),所有的應用都要經過struts的filter,所以login.jsp提交的action,即aas也不例外,對於jsp提交的action,如果沒有後綴,filter會自動加上.action後綴,即action="aas" 等同於action="aas.action"

    過程,請求先被struts  filter過濾器接收,然後查找struts.xml,找其中的action,通過name找到匹配的action,然後就進入這個action,就是執行action的class屬性指定的類生成的對象來處理請求,這個例子就是com.cdtax.struts2.LoginAction,因爲這個類有兩個成員變量與頁面表單中用戶名、密碼屬性一樣,會自動調用對應的get和set方法進行類成員變量設置,並且會將這個信息放到request作用域中,設置完後,執行execute()方法,執行完畢後,轉到struts.xml的action的下一步,找到result的name值等於execute()返回值的那一標籤,執行其標籤內容,就是/result.jsp。

 8、關於struts.xml中的package,也有繼承的概念,extends屬性,繼承某個package,這裏是struts-default,這個包在struts2-core-2.3.14.jar中,有一個struts-default.xml文件,這個文件定義了struts如何自動賦值、類型轉換等,如果沒有繼承這個文件,struts就會出錯。

9、生成struts的幫助文檔:1)新建一個java project ;2)將struts-2.3.14-all\struts-2.3.14\src\core\src\main\java下的org拷貝到新建java project的src下;3)導入依賴的包,主要是struts-2.3.14-all\struts-2.3.14\lib下的包和tomcat的lib下的jsp-api.jar和servlet-api.jar,haiyou一個是velocity-tools-view-1.4.jar,導入後應該沒有錯誤了;4)執行Myeclipse的project下的generate javadoc,生成幫助文檔。

10、關於LoginAction類中成員變量的賦值,不是根據成員變量的名字來進行set,而是根據setXXX方法來進行賦值。實驗:

將login.jsp中form加一個age:<input type="text" name="age">,LoginAction中增加private int age;並增加get和set方法,result中增加age:${requestScope.age },這是正常情況,login中輸入後,點擊提交,結果result.jsp顯示出結果,現在將LoginAction中的private int age改爲private int aaa,在result.jsp中增加${requestScope.aaa },修改LoginAction中setAge和getAge方法爲:public int getAge()
 {
  return aaa;
 }
 public void setAge(int aaa)
 {
  this.aaa = aaa;
 }

則再次操作,結果age依舊能夠顯示出來,而aaa則爲空;

如果將login.jsp中的age input的name改爲aaa,則結果爲age:0,aaa爲空,因爲login.jsp雖然沒有傳遞名字爲age的屬性,但是LoginAction中有getAge和setAge方法,根據其爲int型,設置一個age變量,int沒有默認爲0,雖然login.jsp傳遞了一個aaa屬性值對,因爲LoginAction中沒有相應的get和set方法,所以沒有設置aaa變量,因此爲空。

11、關於服務器啓動時命令行提示:有這樣三行提示xml的解析順序

信息: Parsing configuration file [struts-default.xml]
2013-5-13 14:12:02 com.opensymphony.xwork2.util.logging.commons.CommonsLogger info
信息: Parsing configuration file [struts-plugin.xml]
2013-5-13 14:12:02 com.opensymphony.xwork2.util.logging.commons.CommonsLogger info
信息: Parsing configuration file [struts.xml]

可以看到先是解析了struts-default.xml,這就是struts的默認配置,也是我們自定義的struts.xml所extends的,然後是struts-plugin.xml,這是一些插件的配置文件,格式與struts.xml一樣,最後是我們自己定義的struts.xml。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章