通過實例學習Struts2 - 從struts-blank開始 (1)

最近發現一些網站在Copy&Paste我的文章, 請尊重我的勞動成果,在轉載的時候註明出處,謝謝。

前言

一直用Struts1 , 現在新的項目要轉向Struts2了, 先研究學習一下,做點技術儲備。

我一直認爲計算機軟件行業是一個實踐性非常強的行業,書讀了多少都不管用, 一定要捲起袖子,親自動手,才能學到一門技術的精髓,才能談得上精通。

否則浮在表面,只懂概念,誇誇奇談,一進入真正的項目就傻眼了。

但是自己完全從零開始來學習一個技術還是太慢了,一定要找到一個切入點, 就像打仗一樣,集中優勢兵力,從一點突破,向縱深發展,迂迴包抄,各個殲滅。

這個切入點就是優秀的源代碼, 看看大牛們是怎麼做的,然後模仿學習,能極大的減少你學習的時間。

現在市面上有很多講Struts2的書籍,Struts2權威, 大全,指南, 魚龍混雜, 我的觀點是先不要急着讀他們,先找一本小冊子瞭解一下基本知識,然後找優秀的Struts2項目代碼學習, 在學習思考,不僅僅要知道What, How, 要多問自己幾個Why , 假想一下如果讓你去設計,你會怎麼做,然後和Struts 的設計思想對比, 這樣才能真正的提高。

至於那些“權威/大全/指南” , 我更多的會用來查找技術細節,作爲參考書。


基於這個思路, 先在網上搜索了一本InfoQ的書 <<深入淺出Struts2>> , 還湊合,很快就能翻完,建立了一個基本印象。

至於優秀的Struts2項目代碼,沒有找到合適的,決定拿struts2 中自帶的應用來研究學習,畢竟是官方出品,差不到哪兒去。

哪位同學知道更好的使用Struts2的項目源碼,請不吝賜教。


建立環境

廢話說了這麼多,趕緊開工

先來準備環境:
1. 從Struts2官網下載源碼: http://struts.apache.org/release/2.1.x/, 寫這篇文章的時候版本是struts-2.3.15.1, 注意下載那個Full Distribution, 會包含源碼和例子
2. 開發工具當然少不了, 從http://www.eclipse.org/downloads/ 下載一個 “Eclipse IDE for Java EE Developers,”   這個版本可以和Web Server和 Application Server集成
3. 用Tomcat做Web服務器吧 : http://tomcat.apache.org/  ,我下載的版本是7.0.42


把下載的struts2 解壓開,裏邊有個struts-2.3.15.1/apps  目錄, 其中就是我們要的所有項目例子

這裏的WAR包都是直接可以放到Tomcat中運行的,但是爲了研究, 我們需要把它解開, 別告訴我你不知道怎麼解壓開WAR 文件啊 :-)

從名稱來看struts2-blank.war最簡單, 解壓開大概是這個樣子


啓動Eclipse 啓動,在Preferences -> Server -> Runtime Enviroment  中添加一個Apache Tomcat 7 的 Server runtime , 具體過程就不說了,相信各位同學都能輕鬆搞定


建立一個Dynamic Web project ,名稱就叫做struts2-blank 吧,然後重要的步驟來了:

(1) 把上面圖片中的所有文件都Copy到 新建項目的WebContent下, 如果Eclipse 提示是否覆蓋文件的話,就選擇“是”

(2) 然後把WEB-INF/src/java 下的所有文件都copy 到 struts-blank項目的 src 目錄下 ------ 這是真正的源代碼

(3) 刪除WEB-INF/src 目錄, 清空WEB-INF/classes 目錄    ---- 這些目錄沒用了

最好系統長這個樣子:


建立一個基於Tomcat7 的Server ,用來部署項目, 然後把struts2-blank 這個web 項目加到Server 中, 啓動server , 就能看到tomcat server 在啓動, 然後就是struts2 啓動的log 了

在瀏覽器中運行 http://localhost:8080/struts2-blank/   就能看到最最簡單的界面了:

看起來費了很大的勁, 實際上還是挺簡單的, 之所以要建立一個Eclipse 環境,主要是爲了看源代碼方便。

對於Struts2自帶的其他例子, 各位同學如法炮製即可

Struts2 blank project

終於可以開始看源碼了, 首先引起我注意的就是struts.xml , 是直接放在Eclipse 項目的src 目錄下,這就意味着運行時Eclipse 會自動把它copy到WEB-INF/classes 目錄下, 和編譯過的java class文件放在一起, 而在struts1 中,配置文件叫做struts-config.xml , 是直接放在WEB-INF 目錄下的, 這是一個很大的區別。

打開這個文件瞧一瞧:

    <constant name="struts.devMode" value="true" />  <--- 肯定是指定開發模式

    <package name="default" namespace="/" extends="struts-default">

        <default-action-ref name="index" />  <--- 指定缺省的Action引用, 在下面定義
        <global-results>
            <result name="error">/error.jsp</result>  <--- Global result, Action的結果如果是error,就可以用這個result
        </global-results>

        <global-exception-mappings>
            <exception-mapping exception="java.lang.Exception" result="error"/>  <--- 這個功能不錯, 把所有的代碼異常都映射到error這個result
        </global-exception-mappings>

        <action name="index">  
            <result type="redirectAction">  <--- 調用另外一個Action  : "/example/HelloWorld" ,  namespace其實指的就是url
                <param name="actionName">HelloWorld</param>
                <param name="namespace">/example</param>
            </result>
        </action>
    </package>

    <include file="example.xml"/>  <--- 不錯,可以include 別的文件,模塊化更好,更容易支持團隊開發


順藤摸瓜,再來看看example.xml
    <package name="example" namespace="/example" extends="default"> <---注意namespace是/example, 即這個package下面的所有action 調用都得這麼寫: 
                                                                    <---http://xxxx/structs-blank/example/xxxx

        <action name="HelloWorld" class="example.HelloWorld">   <--- 很明顯, 這裏的Action 實現類是HelloWorld, 可以猜測到,執行成功的話會調用
                                                                <--- HelloWorld.jsp
             <result>/example/HelloWorld.jsp</result>
        </action>

      ......
    </package>


趕緊瞄一眼HelloWorld.java
public class HelloWorld extends ExampleSupport {
    //毫無疑問,這個方法會被調用,設置一個消息的key (HelloWorld.message) 然後返回sucess, 
    //在package.properties中能看到Helloworld.message , 但是struts2到底是怎麼調用它的呢?先彆着急,
    //記下問題, 先看完整個流程再說
    public String execute() throws Exception {  
        setMessage(getText(MESSAGE));          
        return SUCCESS;                         
    }

    /**
     * Provide default valuie for Message property.
     */
    public static final String MESSAGE = "HelloWorld.message";

    /**
     * Field for Message property.
     */
    private String message;

    /**
     * Return Message property.
     *
     * @return Message property
     */
    public String getMessage() {
        return message;
    }

    /**
     * Set Message property.
     *
     * @param message Text to display on HelloWorld page.
     */
    public void setMessage(String message) {
        this.message = message;
    }
}

在HelloWorld.jsp中,有這麼一句  <h2><s:property value="message"/></h2>  , 可以猜測這裏的message 應該和Action 中的getMessage()有關聯, 要不然struts2如何拿到message 的值?

這樣,基本的流程就走完了, 我們看到了struts2的Action定義是在struts.xml 中(以及其他被include的xml 文件), Action 的execute方法會被調用, jsp中可以引用Action中設置的屬性的值。

好像還少了點什麼東西, 對了,struts2到底是通過什麼配置起作用的? 答案當然是在web.xml 中

    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>


和Struts1 不同, Struts2是用一個filter 來處理所有請求的。

如果你之前有struts2開發經驗的話,可能會注意到這裏使用的不是FilterDispatcher,而是StrutsPrepareAndExecuteFilter 。

這是因爲對於Struts2的老版本,使用的是FilterDispatcher,對於2.1.3以上的版本,就開始使用StrutsPrepareAndExecuteFilter了

今天就到此爲止吧, 明天再仔細看一下其他的分支。







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