1. 程式人生 > >Struts2(一)— 入門

Struts2(一)— 入門

進入 模塊 知識 自己 屬性 名稱 rop 流程 method

一、概述

1、什麽是Struts2

  Struts2是一個基於MVC設計模式的Web應用框架,它本質上相當於一個servlet,在MVC設計模式中,Struts2作為控制器(Controller)來建立模型與視圖的數據交互。Struts 2是Struts的下一代產品,是在 struts 1和WebWork的技術基礎上進行了合並的全新的Struts 2框架。其全新的Struts 2的體系結構與Struts 1的體系結構差別巨大。Struts 2以WebWork為核心,采用攔截器的機制來處理用戶的請求,這樣的設計也使得業務邏輯控制器能夠與ServletAPI完全脫離開,所以Struts 2可以理解為WebWork的更新產品。雖然從Struts 1到Struts 2有著太大的變化,但是相對於WebWork,Struts 2的變化很小。

二、Struts2入門

1.環境下載

下載地址:http://struts.apache.org/download.cgi;

技術分享圖片

2. 導入jar

? struts的jar比較多,可以從Struts官方提供的demo中拿到必要的jar就行. 在apps/struts2-blank項目下

技術分享圖片

3. 編寫Action類

  • 新建一個類,裏面定義一個方法

  • /**
     *一,創建了一個普通的類 ,定義了一個execute()方法
     *好比我們之前:創建了一個ProductServlet,然後創建了一個doGet()方法一樣
     *二, 配置Action 好比配置Servlet一樣,只不過不在web.xml裏面配置,自己整了一套
    *   在src目錄下struts.xml的文件裏面配置
    
    */ public class ActionDemo { public void execute(){ System.out.println("收到到了請求..."); } }

4. 配置struts.xml文件

  • 在src底下新建一個xml 名稱為 struts.xml. 在struts.xml裏面配置action

    <?xml version="1.0" encoding="UTF-8"?>
     <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
        "http://struts.apache.org/dtds/struts-2.3.dtd"
    > <struts> <package name="test" extends="struts-default" namespace="/"> <!--一個請求對應一個Servlet, struts2裏面一個請求配置一個Action --> <action name="demo" class="com.itheima.web.ActionDemo"></action> </package> </struts>

註意:

  1. struts.xml文件名不可隨意取,必須叫做struts.xml

  2. struts.xml必須放在src類路徑下

  3. 到struts的核心包中可以找到struts-2.3.dtd文件(建議配置本地的dtd,沒網情況下也可以使用...)

5. 前端控制器配置

  • 在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>

    其實就是在web.xml中配置struts2的filter

6. 編寫訪問路徑,進行測試

http://localhost:8080/day42A_Struts2/demo

三、Struts2的運行流程

1.服務器啟動(項目部署)

  • 當項目部署的時候,會執行StrutsPrepareAndExecuteFilter的init()方法,在init方法裏面有這樣的一行代碼 :

    dispatcher = init.initDispatcher(config);

  init_DefaultProperties(); // [1] —> 加載 default.properties 常量配置(國際化編碼, 文件上傳的size...)
  init_TraditionalXmlConfigurations(); // [2] ->加載 struts-default.xml,struts-plugin.xml,struts.xml
  init_LegacyStrutsProperties(); // [3] —> 加載struts.properties
  init_CustomConfigurationProviders(); // [5] ---> 加載自定義的一些初始化類. 一般不寫
  init_FilterInitParameters() ; // [6]  ---> 加載初始化參數。 initparam
  init_AliasStandardObjects() ; // [7] ---> 給對象起別名

  • 圖示

    順序配置文件名所在位置說明
    1 default.properties ..src\core\src\main\resources\org\apache\struts2 不能修改
    2 struts-default.xml ..\struts-2.3.32\src\core\src\main\resources 不能修改
    3 strtuts-plugin.xml 在struts2提供的插件jar包中 不能修改
    4 struts.xml 我們的應用中 我們修改的:推薦
    5 struts.properties 我們的應用中 我們修改的:不建議用
  • 後面配置的會把前面的覆蓋

技術分享圖片

技術分享圖片

2.請求到來

? 當我們在瀏覽器輸入請求路徑 http://localhost:8080/day01A_Struts2/demo01

技術分享圖片

技術分享圖片

四、Struts.xml中的配置詳解

  • eg

    <struts>
        <!--一, package指的是一組請求的集合; 一般一個模塊創建一個package
                1.1 name: 包名; 隨便取, 不要重復就行
                1.2 extends: 繼承的意思, 我們當前的test包繼承了名字叫struts-default這個包, struts-default這個包裏面的功能我們test包都可以使用的
                1.3 namespace: 名稱空間; 用意在於訪問action的時候加一層路徑(方便自己看的)
                    eg: 當前配置的是/, http://localhost:8080/day42A_Struts2/demo01
                        當前配置的是/test, http://localhost:8080/day42A_Struts2/test/demo01
                1.4 abstract: 抽象, 用意在於表明這個包是抽象的, 也就是說讓別的包繼承的; 如果這個包讓別的包繼承,習慣設置為true
           -->
        <package name="test" extends="struts-default" namespace="/" >
            <!--二, 一個請求配置一個Action標簽, 不是說一個請求就要創建一個Action類
                2.1 name: action的名字,  說白了就是當前action的訪問路徑. 名字隨便取, 不要重復就行了
                2.2 class:當前Action類的全限定名
                2.3 method: 處理當前請求的方法; 說白了也就是當前Action類裏面的方法名(默認是execute)
             -->
            <action name="demo01" class="com.itheima.web.ActionDemo01"></action>
            <action name="demo01_regist" class="com.itheima.web.ActionDemo01" method="regist">
                <!--三, 配置的就是結果
                    3.1 name: 結果視圖的名字; 說白了就是處理這個請求對應方法的返回值
                    3.2 type: 配置跳轉的類型(默認就是轉發到頁面) 
                    3.3 result標簽裏面值: 就是要跳轉的路徑
                  -->
                <result name="registSuccess">
                    /registSuccess.jsp
                </result>
            </action>
        </package>
    </struts>

五、Action進階

1、Action規範和特點

1.1 Action的編寫規範
  1. action類需要提供無參構造函數

  2. action中方法規定

    ? 修飾符:方法的修飾符必須是public

    ? 參數列表:方法必須是無參方法

    ? 返回值類型:String

1.2 action多例性

?  每次url訪問時,action的實例就會被創建一次。action類是多實例的。

2.Action的通用寫法

2.1普通類

? 這種方式就是我們最開始給大家寫的, 就是一個普通類,然後裏面寫一個方法,具有String類型返回值即可。

2.2實現Action接口
  • 好處是 : 我們少寫一點代碼, 可以使用接口裏面定義的常量 SUCCESS \ ERROR ....

    public class HelloWorld02 implements Action{
        @Override
        public String execute() throws Exception {
            System.out.println("hi struts");
            return SUCCESS;
        }
    }
2.3繼承ActionSupport【重點】

?   這種做法,相比較前面的好處在於, ActionSupport 雖然是實現了Action的接口 , 但是內部自己也擴展了些功能 :eg: 提供了信息的校驗、並且能夠根據校驗的結果回到原來的頁面。如 : 它裏面也集成了獲取國際化資源的方法,我們可以直接使用。

  • Java代碼

    public class ActionDemo03 extends ActionSupport {
        @Override
        public String execute() throws Exception {
            System.out.println("ActionDemo03 execute()...");
            return SUCCESS;
        }
    }

3.Action訪問的路徑配置

3.1通過method屬性訪問【重點】

?   一般來講,我們的action類都不會只有一個execute方法,如果存在很多的方法 ,我們如何在struts.xml 裏面映射到方法裏面去呢? struts提供的第一種方法是在action裏面使用method屬性來指定訪問的具體的方法。 舉例如下:

<action name="user_login" class="com.itheima.web.UserAction" method="login"></action>
<action name="user_regist" class="com.itheima.web.UserAction" method="regist"></action>
<action name="user_active" class="com.itheima.web.UserAction" method="active"></action>
<action name="user_loginout" class="com.itheima.web.UserAction" method="logout"></action>

  這樣看上去是挺好的。 直接指定method ,就會找到具體的方法。 但是如果以後我們的方法很多,這樣就要配置很多的action標簽了。這就不太好維護了。代碼先就顯得很多,所以這種方式用的不多.

3.2通過通配符訪問【重點】

? 通配符的訪問其實還是要依賴於method的屬性,只不過在匹配來訪的地址 和 action的名稱的時候使用通配符來匹配。采取method屬性訪問的方式,一個請求需要寫一個Action。

  如果采取通配符的方式,只需要配置一個Action就可以了, *用於表示匹配任意字符。 後面的{1} 就表示能夠取到 * 所處位置的字符,然後找到對應的方法。

<action name="user_*" class="com.itheima.web.UserAction"  method="{1}"></action>

  我們在開發中通常采取通配符方式訪問.

3.3通過動態方法訪問【了解】

?   第三種方式可讀性不強 ,這種方式使用動態代理訪問。用的很少. 使用步驟:

  1. 打開動態訪問開關,在Struts.xml文件配置

    <constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
  2. 配置Action的名字

    <action name="userAction" class="com.itheima.web.UserAction"></action>
  3. 訪問路徑通過actionName + !+ action類中的方法名訪問

    http://localhost:8080/day02D_Struts2/userAction!login

知識點補充:Constant用來配置常量值的,目的是修改Struts的default.propertis中的默認值的;

?  在Struts.xml中使用 <constant name="" value=""></constant>標簽

  • 常量舉例

    常量名常量值說明
    struts.i18n.encoding UTF-8 應用中使用的編碼
    struts.multipart.maxSize 2097152 文件上傳總文件大小限制:2M
    struts.action.extension action,, 能進入Struts2框架內部的url地址後綴名。多個值用逗號分隔
    struts.enable.DynamicMethodInvocation false 是否允許動態方法調用
    struts.devMode false 是否是開發模式。開發模式:改了配置文件,不需要重啟。輸出更多的錯誤信息。開發階段建議為true。
    struts.ui.theme xhtml 頁面展示用的主題
  • eg,在struts.xml裏面配置常量

    <struts>
        <!-- 一,配置常量的 -->
        <!-- 1.1 打開允許動態方法訪問的權限 -->
        <!-- <constant name="struts.enable.DynamicMethodInvocation" value="true"></constant> -->
        <!--1.2 添加action的訪問的後綴(有用的,權限的框架(Shiro,SpringSecurity))  -->
        <constant name="struts.action.extension" value="pri,do,action,,"></constant>
        <!-- 1.3配置改了struts.xml配置文件,不需要重啟服務器 -->
        <constant name="struts.devMode" value="true"></constant>
    </struts>

六、Struts2 + Hibernate整合

1. 案例需求

  • 使用Struts2 + Hibernate完成展示商品的案例.

2. 案例實現

2.1 創建web層(struts2)
  • 創建web項目, 導入jar包

  • 創建CategoryAction

    public class CategoryAction extends ActionSupport {
        
        public String findAll(){
            try {
                //1. 獲得請求參數
                //2. 調用業務
                CategoryService categoryService = new CategoryService();
                List<Category> list =  categoryService.findAll();
                //3. 把list存到域裏面, 轉發頁面 
                HttpServletRequest request = ServletActionContext.getRequest();
                request.setAttribute("list", list);
                return "findAllSuccess";
            } catch (Exception e) {
                e.printStackTrace();
                ServletActionContext.getRequest().setAttribute("msg", "查詢失敗...");
                return "findAllError";
            }
        }
    }
  • 在classpath(src)目錄下創建struts.xml配置CategoryAction

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
        "http://struts.apache.org/dtds/struts-2.3.dtd">
    <struts>
        <package name="category" extends="struts-default" namespace="/">
            <action name="category_*" class="com.itheima.web.CategoryAction" method="{1}">
                <result name="findAllSuccess">
                    /list.jsp
                </result>
                <result name="findAllError">
                    /msg.jsp
                </result>
            
            </action>
        </package>
    </struts>
  • 在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>

3. 發現獲得商品的時候出現了bug

? org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.itheima.bean.Category.products, could not initialize proxy - no Session

  1. 使用openSession(), 不手動調用close() [千萬不要用]

  2. 不使用懶加載, 再查詢類別的同時就把商品查詢出來

    <set name="products" fetch="select" lazy="false">
         <!--1.2 column: 外鍵的列名  -->
         <key column="cid"/>
         <!--1.3  class: 對方類的全限定名  -->
         <one-to-many class="com.itheima.bean.Product"/>
    </set>
  3. 還使用懶加載, 在CategoryDao使用一個商品就行了

Struts2(一)— 入門