慕課網 structs

一、概述

Struts2.0發展歷史

Struts2.0不是一個全新的框架,因此穩定性、性能等各方面都有很好的保證,同時收了Strus1.0和webwork兩者的優勢

eclipse下第一個實例

(1)要導入的jar包:(共9個)

commons-fileupload(上傳下載包)
commons-io(輸入輸出包)
commons-lang 3-3.2(基礎包)
commons-logging(日誌包)
freemarker(模板引擎,通過模板生成文本輸出的通用工具)
structs2-core(核心包)
xwork-core(一些類基於xwork)
ognl(表達式)
javassist-3.11.0.GA.jar(解析java類文件的一個包)

下載地址
http://struts.apache.org
http://people.apache.org/builds/struts/

(2)配置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>*.action</url-pattern>
  </filter-mapping></web-app>

(3)創建HelloWorldAction類

import com.opensymphony.xwork2.ActionSupport;
public class HelloWorldAction extends ActionSupport {
	@Override
	public String execute() throws Exception {
		System.out.println("執行Action");
		return SUCCESS;
	}
}

(4)創建並配置struts.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
	<package name="default" namespace="/" extends="struts-default">
		<action name="helloworld" class="com.imooc.action.HelloWorldAction">
			<result>/index.jsp</result>
		</action>
	</package>
</struts>  

Struts2工作原理


1.客戶端通過HttpServletRequest發送指向Servlet容器(例如Tomcat)的請求 
2.這個請求經過一系列的過濾器.(這些過濾器中有一個叫做ActionContextCleanUp的可選過濾器,這個過濾器對於Struts2和其他框架的集成很有幫助,例如:SiteMesh Plugin,最終被struts核心過濾器過濾,
即FilterDispatcher) 
3.接着FilterDispatcher詢問ActionMapper來決定這個請是否需要調用某個Action
4.如果ActionMapper決定需要調用某個Action,FilterDispatcher將把請求的處理交給ActionProxy
5.ActionProxy通過Configuration Manager詢問框架的配置文件,找到需要調用的Action類
6.ActionProxy創建一個ActionInvocation的實例
7.ActionInvocation實例使用命名模式來調用,在調用Action的過程前後,涉及到相關攔截器(Intercepter)的調用
8.一旦Action執行完畢,ActionInvocation負責根據struts.xml中的配置找到對應的返回結果(result),返回結果通常是一個需要被表示的JSP或者FreeMarker的視圖,也可能是另外的一個Action鏈.在表示的過程中可以使用Struts2框架中繼承的標籤,在這個過程中需要涉及到ActionMapper

9.當返回這個結果以後,將之前執行過的攔截器反向執行一遍,然後通過response響應客戶端的請求

在上述過程中所有的對象(Action,Results,Interceptors等)都是通過ObjectFactory來創建的

struts2.1.0的核心過濾器是:FilterDispatcher
struts2.1.3後的核心過濾器是:StrutsPrepareAndExecuteFilter
區別:
StrutsPrepareAndExecuteFilter過濾器可以在執行Action之前添加自己的過濾器但FilterDispatcher不可以

文件結構

(1)web.xml
任何MVC框架都需要與Web應用整合,這就不得不借用於web.xml文件,只有配置web.xml文件中Servlet纔會被應用加載
Model2:  JSP+JavaBean+Servlet
通常,所有MVC框架都需要Web應用加載一個核心控制器,對於Struts2框架而言,需要加載StrutsPerpareAndExecuteFilter,只負責Web應用加載StrutsPerpareAndExecuteFilter,StrutsPerpareAndExecuteFilter將會加載Struts2框架。
遇到.acton文件就會攔截並進行處理

(2)struts.xml
struts2的核心配置文件,在開發過程中利用率最高。

該文件主要負責管理Action的映射,以及該Action包含的Result定義等。


struts.xml中包含的內容:
1、全局屬性
2、用戶請求和相應Action之間的對應關係
3、Action可能會用到的參數和返回結果
4、各種攔截器的配置

.dtd就是約束struts.xml中可以有哪些標籤不能有哪些標籤

可以通過 <include file=“”>包含其他文件,可以把每個功能模塊獨立到一個xml配置文件中,然後用Include節點引用
<include file="struts-default.xml"></include>

<package>
package提供了將多個Action組織成爲一個模塊的方式
package的名字必須是唯一的,可以在這個包上加一些拓展的包
<package name="包名" extends="繼承的父類的名稱" abstract設置package的屬性爲抽象,抽象的package不能定義action的值,ture或false   namespace=包的命名空間>

<!-- 定義攔截器 -->
<interceptor name="名稱" class="類路徑"></interceptor>
<!-- 定義攔截器棧 -->
<interceptor-stack name="mystack">
<interceptor-ref name="time"></interceptor-ref>
<interceptor-ref name="logger"></interceptor-ref>
</interceptor-stack> 
</interceptors>
<!-- 定義默認攔截器,每個action都會引用,如果action引用了其他攔截器,則默認攔截器無效 -->
<default-interceptor-ref name="mystack"></default-interceptor-ref>

<!-- 全局results設置 -->
<global-results>
<result name="input" >/error.jsp</result>
</global-results>

<!-- action配置,一個action可以被多次映射(只要action配置中name不同)--> 
<action name="action名稱" class="對應的類路徑" method="默認進入的方法">
<!-- 引用攔截器
name:攔截器名稱或攔截器棧名稱 -->
<interceptor-ref name="time"></interceptor-ref>

<!-- 節點配置
name:result名稱和action中返回的值相同
type:result類型 不寫則選用superpackage的type struts-default.xml中默認爲dispatcher -->
<result name="success" type="dispatcher">/talk.jsp</result>

<!-- 參數配置
name:對應Action中的get/set方法 -->
<param name="url">http://www.sina.com</param>

<!-- struts.properties 中的內容>
<constant name="" value=""></constant>


(3)struts.properties
struts2框架的全局屬性文件,自動加載
和strusts.xml在一個路徑
該文件包含很多key-value鍵值對。
這個文件可以不要,可以在structs.xml中進行配置,使用constant元素可以替換

#制定默認編碼集,對於請求參數帶有中文的情況應該設置成gbk.gb2312,默認值utf-8
1.struts.i18n.encoding=utf-8
#是否每次HTTP請求到達時,都重新加載國際化資源文件,默認爲false
2.struts.i18n.reload = true
#但struts.xml改動後,是否重新加載該文件,在開發階段建議設置成true,提高開發效率,默認爲false
3.struts.configuration.xml.reload=true
#是否使用struts2的開發模式,可以獲得更多報錯信息,便於調試,在開發階段設置爲true,默認爲false
4.struts.devMode =true
#設置瀏覽器是否緩存靜態頁面,開發階段設置爲false,以獲得服務器最新響應,默認爲true
5.struts.serve.static.browserCache=true
#指定後綴爲.action形式的請求可以被struts2處理,可配置多個請求後綴,比如.do,struts等,配置多個後綴名用逗號隔開
6.struts.action.extendsion=action,do,struts2,
#配置服務器運行時的端口號,一般情況下該屬性不用修改,如果端口號佔用則重新分配端口號,默認爲80
7.struts.url.http.port = 8080

二、深入

1.訪問Servlet API
(1)ActionContext
(2)實現***Aware接口
(3)ServletActionContext

2.Action搜索順序

http://localhost:8080/struts2/path1/path2/path3/student.action
第一步:判斷package是否存在,如:path1/path2/path3
(1)存在
第二步:判斷action是否存在,如果不存在則去默認的namespace的
package裏面尋找action
第三步:如果沒有,則報錯
(2)路徑包不存在
第二步:檢查上一級路徑的package是否存在(直到默認namespace,重複第一步)

3.動態方法調用

解決一個Action對應多個請求的處理,以免Action太多
public class HelloWorldAction extends ActionSupport {
	public String add(){
		System.out.println("執行add Action");
		return SUCCESS;
	}
	public String update(){
		System.out.println("執行update Action");
		return SUCCESS;
	}
}

(1)method屬性

<action name="action名稱" class="對應的類路徑" method="默認進入的方法">

struts.xml文件修改
 <action name="helloworld" method="execute" class="com.imooc.action.HelloWorldAction">
	 <result>/result.jsp</result>
 </action>		
 <action name="add" method="add" class="com.imooc.action.HelloWorldAction">
		 <result>/result.jsp</result>
 </action>

(2)感嘆號方式(不推薦)

struts.xml文件修改
<struts>
<package> 
<action name="helloworld" class="com.imooc.action.HelloWorldAction">
	 <result>/result.jsp</result>
	 <result name="add">/result.jsp</result>
	 <result name="update">/result.jsp</result>
 </action>
</package>
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
</struts>

第二步
http://localhost:8080/Struts2/helloworld!add.action (重要2)

(3)通配符方式(推薦)

<struts>
	<package name="default" namespace="/" extends="struts-default">
	<action name="*_*" method="{2}" class="com.imooc.action.{1}Action">
		 <result >/result.jsp</result>
	 	<result name="add">/{2}.jsp</result>
	 	<result name="update">/{2}.jsp</result>
 	</action>
	</package>
		<constant name="struts.enable.Dystruts-defaultMethodInvocation" value="true"></constant>
</struts>

第二步
http://localhost:8080/Struts2/HelloWorld_add.action


通配符會覆蓋掉默認action,所以不能有【*_*】這樣子的action,要改成【log_*_*】這類型的命名,否則,【*_*】裏面的第一個*就包括了所有的字符,直接進入了這個action進行處理,無法進入默認的action了

4.指定多個配置文件

<include file="login.xml"></include>

5.默認Action

<default-action-ref name="index"></default-action-ref>
<action name="index">
    <result>/error.jsp</result>
</action>
經過多次反覆試驗設置的default-action是不生效的,它依然會去找上面那個通配符設置的action,找不到就會報錯,所以本人認爲這是一個bug。 
若想使用 default-action-ref的功能,就只有改配置文件如以下這樣配置 
    <action name="User_*" 

6.struts2後綴

(1)struts.xml中配置
<constant name="strust.action.extension" value="html"></constant>
不想要後綴就把value的值設爲空,或者刪除上面的標籤。

(2)struts.properties 
strust.action.extension=**


(3)在web.xml過濾器中配置init-param參數:
<init-param>
<param-name>struts.action.extension</param-name>
<param-value>do,action,strtus2</param-value>
</init-param>
param-value便爲其後綴值。
後綴值多個可以用英文逗號分開

注意: 以上所有方法,需要注意的是action的擴展名更改了之後,<url-pattern>*.json</url-pattern>,此處的配置要麼是"/*",要麼與更改之後的 擴展名一致。若配置不一致,例如配置爲"*.html",當訪問時的擴展名爲html時,能通過Struts2的過濾,但是會報404錯誤;當訪問時擴展名爲json時,Struts2的過濾都不能通過。


7.接收參數

(1)使用Action屬性接收參數

第一步:login.jsp
    <form action="LoginAction.action" method="post">
    用戶名:<input type="text" name="username"><br>
    密碼:<input type="password" name="password"><br>
    <input type="submit" value="提交"/><br>
    </form>>

第二步:LoginAction.java
	private String username;
	private String password;	
	public String login(){
		System.out.println(username);//參數
		return SUCCESS;
	}

第三步:struts.xml
	<action name="LoginAction" method="login" class="com.imooc.action.LoginAction">
		 <result >/success.jsp</result>	 	
 	</action>


(2)使用DomainModel接收參數

第一步:User.java
public class User {
	private String username;
	private String password;
	public String getUsername() {
		return username;
	}

第二步:LoginAction.java
public class LoginAction extends ActionSupport {
	private User user ;
	public String login(){
		System.out.println(user.getUsername());
		return SUCCESS;
	}

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}
}

第三步:login.jsp
  
用戶名:<input type="text" name="user.username"><br>
    密碼:<input type="password" name="user.password"><br>

(3)使用DomainDriven接收參數

第一步:LoginAction.java
public class LoginAction extends ActionSupport implements ModelDriven<User>{
	private User user =new User();
	public String login(){
		System.out.println(user.getUsername());
		return SUCCESS;
	}
	public User getModel() {
		// TODO Auto-generated method stub
		return user;
	}
	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}
}

第二步:login.jsp
    用戶名:<input type="text" name="username"><br>
    密碼:<input type="password" name="password"><br>

(4)List類型

第一步:User.java
public class User {
	private String username;
	private String password;
	private List<String> bookList;

第二步:LoginAction.java
	public String login(){
		System.out.println(user.getUsername());
		System.out.println(user.getBookList().get(0));
		return SUCCESS;

第三步:login.jsp
    書籍1:<input type="text" name="bookList[0]"><br>   
    書籍2:<input type="text" name="bookList[1]"><br>
  

8.關於input的代碼演示

關於input,如果發生以下兩種情況就會自動跳轉到input界面對應的界面
1.如果struts轉換參數發生錯誤。
2.this.addFileError函數有值,就代表着也發生了錯誤。
第一步:Struts.xml
	<action name="LoginAction" method="login" class="com.imooc.action.LoginAction">
		 <result >/success.jsp</result>	
		  <result name="input">/login.jsp</result>	 	
 	</action>

第二步:LoginAction.java
	@Override
	public void validate() {
		if(user.getUsername()==null || "".equals(user.getUsername())){
			this.addFieldError("username", "用戶名不能爲空");
			//return INPUT;
		}
	}

第三步:login.jsp
<%@ taglib prefix="s" uri="/struts-tags" %>
用戶名:<input type="text" name="username"><br><s:fielderror name="username"></s:fielderror>

9.處理結果類型

Structs2處理流程
用戶請求→Structs框架→控制器(Action)→Structs框架→視圖資源
返回String,提供代碼複用性,有利於框架分離。

(1)<result name="success" >/success.jsp</result>
result 元素中name就是result元素的邏輯視圖名稱
(2)<result>/success.jsp</result>
如果省略了name屬性,系統將採用默認的name屬性值,默認的name值是success

Action中五種內置屬性(com.opensymphony.xwork2.Action)
(1) SUCCESS Action正確的執行完成,返回相應的視圖,success是name屬性的默認值。 
(2) NONE 表示Action正確的執行完成,但並不返回任何事視圖。
(3) ERROR 表示Action執行失效,返回錯誤處理視圖。
(4) LOGIN Action因爲用戶沒有登錄的原因沒有正確執行,將返回該登錄視圖,要求用戶進行登錄驗證
(5) INPUT Action的執行,需要從前端界面獲取參數,INPUT就是代表這個參數輸入界面,一般在應用中,會對這些 參數進行驗證,如果驗證沒有通過,將自動返回該視圖。

<result>/success.jsp</result>與<result>/success.jsp</result>的區別
帶斜槓是:絕對路徑,開始是整個項目的上下文路徑
去掉斜槓:相當於執行該action namespace指定的路徑


result具有子標籤param標籤,result具有兩個屬性,一個是location,一個是prase屬性,location定義了該視圖對應的實際視圖資源,parse即是指定是否可以在result中使用ognl表達式,默認值爲true
<result>
<param name="location">/login.jsp</param>
<param name="prase">false</param>   //默認爲true
</result>

在result中使用ognl表達式:
${#request.path}這中形式,即action中request對象的一個屬性值
${username}這種形式,即action中的一個成員變量的值,action中該成員變量應該有getter和setter方法

(1)在result裏面最重要的屬性是type類型,
type的默認值爲dispatcher,這個類型支持JSP視圖技術。
(2)Struts 2 支持多種視圖技術,例如JSP、Valocity(模板引擎)、FreeMaker(模板引擎)等


chain定義從action到action的映射
redirect重定向
stream返回inputstream用於文件上傳下載
plaintext返回網頁源代碼
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章