Struts2(一)— 入門
一、概述
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入門
? struts的jar比較多,可以從Struts官方提供的demo中拿到必要的jar就行. 在apps/struts2-blank
項目下
3. 編寫Action類
-
新建一個類,裏面定義一個方法
-
/** *一,創建了一個普通的類 ,定義了一個execute()方法 *好比我們之前:創建了一個ProductServlet,然後創建了一個doGet()方法一樣 *二, 配置Action 好比配置Servlet一樣,只不過不在web.xml裏面配置,自己整了一套 * 在src目錄下struts.xml的文件裏面配置
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.xml文件名不可隨意取,必須叫做struts.xml
-
struts.xml必須放在src類路徑下
-
到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的編寫規範
-
action類需要提供無參構造函數
-
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通過動態方法訪問【了解】
? 第三種方式可讀性不強 ,這種方式使用動態代理訪問。用的很少. 使用步驟:
-
打開動態訪問開關,在Struts.xml文件配置
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
-
配置Action的名字
<action name="userAction" class="com.itheima.web.UserAction"></action>
-
訪問路徑通過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
-
使用openSession(), 不手動調用close() [千萬不要用]
-
不使用懶加載, 再查詢類別的同時就把商品查詢出來
<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>
-
還使用懶加載, 在CategoryDao使用一個商品就行了
Struts2(一)— 入門