一、Action 配置說明 訪問的時候 : http://localhost:8080/Struts2-02/addUser 註意 1) action 沒有寫 class 屬性 2) action 沒有寫 method 屬性 3) result 沒寫 name 屬性 那它們的值是怎麼得到的呢? 實際 ...
一、Action 配置說明
//請求的直接轉發 <package name="packageUser" namespace="" extends="struts-default"> <action name="addUser"> <result>success.jsp</result> </action> </package>
訪問的時候 : http://localhost:8080/Struts2-02/addUser
註意
1) action 沒有寫 class 屬性
2) action 沒有寫 method 屬性
3) result 沒寫 name 屬性
那它們的值是怎麼得到的呢? 實際上,它們都是有預設值的,在每個action被執行的時候,它都會被反射成一個java對象,// struts2中的action是多實例的
action 配置中,各項的預設值
1) 如果不寫class 它的預設值是 ActionSupport
2) 如果不指定 method 它的預設值是 execute
3) 如果不指定result 的name 預設是 success
上面的寫法,相當於
<action name="addUser" class="com.opensymphony.xwork2.ActionSupport" method="execute" >
<result name="success" >success.jsp</result>
</action>
二、result 的配置說明
在 struts2-core-2.3.16.3.jar -> 下的 struts-default.xml 文件中有如下聲明:
<package name="struts-default" abstract="true"> <result-types> <result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/> <result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/> <result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/> <result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/> <result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/> <result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/> <result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/> <result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/> <result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/> <result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" /> <result-type name="postback" class="org.apache.struts2.dispatcher.PostbackResult" /> </result-types> .... </package>
1) dispatcher(預設值) //內部請求轉發,和過去servlet 中 forwart 一樣
2) redirect //重定向 註意,重定向,是不可能定向到 WEB-INF 下的
3) redirectAction //重定向到某個Action上 ,最典型的應用,比如添加用戶以後,重定向到一個用戶查詢的action上
4) plainText //以文本的形顯示jsp或html
5) chain //用來處理Action鏈,一個action處理完後,轉發到下一個action
6) stream //向瀏覽器發送InputStream 對象,通常用來下載,還可以返回ajax數據
7) freemarker //處理 freemarker 模板
8) httpheader //控制特殊HTTP行為的結果類型 根據值棧返回自定義的HttpHeader,status指定響應狀態
9) velocity //處理Velocity模板 //Velocity是一個基於java的模板引擎
10) xslt // 處理XML/XLST模板
11)postback
//例子 使用 redirect方式在 url 後面傳值的例子 <package name="packageThree" namespace="" extends="struts-default"> <action name="usrEdit" class="cat.action.UserEditAction" method="execute" > <result name="success" type="redirect" >/test_redirect.jsp?userName=${userName}</result> 註意,這裡的 type 為redirect </action> </package> //並且,在 UserEditAction 中: public class UserEditAction { private String userName; //要生成get set 方法 public String execute(){ try { userName=URLEncoder.encode("這是很久很久沒來的高睿","UTF-8"); //為了處理亂碼,這裡要URLEncoder } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return "success"; }
//在test_redirect.jsp中,可以用 ${userName} 取出來值,但如果有中文將出現亂碼,可以如下處理 <% String userName= request.getParameter("userName"); userName=new String(userName.getBytes("iso8859-1"),"UTF-8"); // userName=URLDecoder.decode(userName,"UTF-8"); 實測不加也可以 out.println(userName); %
//例子 重定向到別的action <action name="redirectOtherActionTest"> <result type="redirectAction">otherActionName</result> </action> <action name="otherActionName"> <result>success.jsp</result> </action>
//例子 重定向到別的包中的 action <action name="redirectOtherPackageActionTest"> <result type="redirectAction"> <param name="actionName">xxx</param> <param name="namespace">/two</param> </result> </action>
三、配置全局視圖
<global-results> <result name="g_error">/error.jsp</result> //這是包範圍內的全局視圖 </global-results> <action name="userAdd" class="cat.action.UserAction" method="add" > //這裡沒有配置 result </action> public class UserAction extends ActionSupport { public String add(){ return "g_error"; //全局視圖 } }
如果視圖要做成全局的怎麼辦 (跨包)
1) 聲明一個包 並繼承 struts-default ,把它交給別人繼承。在這個包里,聲明全局視圖
2) 用別的包來繼承它
//這個包是專門用來給別的包繼承的 <package name="base" extends="struts-default" > <global-results> <result name="g_success">/success.jsp</result> <result name="g_eror">/error.jsp</result> </global-results> </package> <package name="packageUser" namespace="" extends="base"> <action name="userAdd" class="cat.action.UserAction" method="add" > //如果這裡也有一個 <result name="g_eror">/error.jsp</result> ,則會覆蓋全局視圖 </action> </package> public class UserAction extends ActionSupport { public String add(){ return "g_success"; //全局視圖 } }
result 用來配置邏輯視圖與物理視圖之間的映射關係,視圖資源不一定是JSP頁面,目前的視圖資源有:
Velocity
FreeMarker
JFreeChart
報表 JasperReports
XSLT
四、為 Action 的屬性註入值
public class NumZhuRuAction { private String compName; //公司名稱 private String money; //公司現金 ... get set 方法 public String execute(){ return "success"; } } <package name="packageUser" namespace="" extends="base"> <action name="numZhuRuAction" class="cat.action.NumZhuRuAction" method="execute"> <param name="compName">海康公司</param> <param name="money">100元</param> <result name="success">/zhuru_ok.jsp</result> </action> </package>
五、struts2 中的常用常量
指定 struts2 請求的尾碼,在前面,訪問請求地址都可以加上.action 尾碼。寫在web.xml中的過濾器 org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter 是Struts 2框架的核心控制器,它負責攔截由 <url-pattern>杠*</url-pattern>指定的所有用戶請求,當用戶請求到達時,該Filter會過濾用戶請求。預設情況下,如果用戶請求的路徑以.action結尾,該請求將被轉入Struts2框架處理,否則該請求將略過Struts2 框架的處理。
可以通過配置常量,來指定這個請求的尾碼 struts.action.extension
<constant name="struts.action.extension" value="do,action,cat"></constant> 可以指定多個
常量可以在struts.xml或struts.properties中配置,建議在struts.xml中配置,兩種配置方式如下:
--struts.xml
<struts> <constant name="struts.action.extension" value="do"/> </struts>
--struts.properties 文件中
struts.action.extension=do
通常,struts2按如下搜索順序載入struts2常量:
struts-default.xml //struts-core-2.3.25.2.jar 中
struts-plugin.xml //struts2-convention-plugin-2.1.6.jar ?
struts.xml
struts.properties //它在哪兒? 在src下手工建一個就行了 裡面放上 struts.action.extension=cat,dog 則會覆蓋 struts.xml 中的配置
web.xml
如果在多個文件中配置了同一個常量,則後一個文件中配置的常量值會覆蓋前面文件中配置的常量值
Struts2常用的常量 svn 極限開發,可以在幫助文檔中的 home.html 中的指南下找到。struts2 的常量,也叫 struts2 的屬性,主要用來控制整個struts2 的運行特性。
--<constant name="struts.i18n.encoding" value="UTF-8" />//指定預設編碼集 作用於HttpServletRequest的SetCharaterEncoding方法和 freemarker,velocity(模板技術) 輸出
--<constant name="struts.action.extension" value="do" /> //指定請求尾碼 ,多個用逗號分開
--<constant name="struts.serve.static.browserCache" value="false" /> //指定瀏覽器是否緩存靜態內容,預設值為true(生產環境下使用),開發階段最好關閉
jsp——servlet——class 好:提高執行效率0.05s 0.7s 不好:不能及時的反應程式上的變化
--<constant name="struts.Configuration.xml.reload" value="true" /> //指定struts配置文件修改後,系統是否自動重新載入該文件,預設為false(生產環境下用),開發除階段最好打開
--<constant name="struts.devMode" value="true" /> //開發模式下使用,這樣可以列印出更詳細的錯誤信息
--<constant name="struts.ui.theme" value="simple" /> //指定預設的視圖主題(Struts2 中有一些標簽使用了視圖主題 後面會有介紹)
--<constant name="struts.objectFacvtory" value="spring" /> //指定創建Action 對象明的工廠類(本例:與 spring集成時,指定由sping負責Action的創建)
--<constant name="struts.enable.DynamicMethodInvocation" value="false" /> //指定Struts2 是否支持動態方法調用,預設值是 false
--<constant name="struts.mutipart.maxSzie" value="10701096" /> //設定上傳文件的大小(不是指一個,是指一組)
--<constant name="struts.multipart.saveDir" value="" /> 設置上傳言語件的臨時目錄
六、Struts2的處理流程
用戶請求 ---->
--->StrutsPreparedAndExecuteFilter //配置在web.xml中的過濾器
--->Interceptor //struts2內置的一些攔截器或用戶自定義的攔截器
--->Action //用戶定義的業務處理類,
--->Result //視圖
--->jsp / html /其他
StrutsPrepareAndExceuteFilter 是Struts 框架的核心控制器, 它負責攔截由<url-pattern>杠*</url-pattern> 指定的用戶請求
當用戶請求到達時,該filter 會過濾用戶請求,預設情況下,如果用戶請求的路徑不帶尾碼, 或以.action結尾,則這時請求被轉入到Struts2 框架進行處理,否則Sttuts2將略過該請求。
當請求進入Struts2框架處理時會先經過一系列的攔截器, 然後再到Action與Struts1不同,Struts 2 對用戶的每一次請示都會創建一個Action,所以Struts2中的Action是線程安全的管理方式,是一個常見的面試題(線程安全)Struts1 創建Action 中,會放到緩存里去(單例)。
附:可以在action的構造函數中,輸出內容,觀察到每次訪問,都會引起構造函數的調用。
//為應用指定多個struts 配置文件 //在主文件中 <include file="good_conf.xml" /> //新建一個 配置文件,名稱為 good_conf.xml <?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="package_xxx" extends="base"> <action name="hellowGoods" > <result name="success">/goods_add.jsp</result> </action> </package> </struts>
七、動態方法調用和使用通配符定義Action
//動態方法調 <constant name="struts.enable.DynamicMethodInvocation" value="true" /> <action name="userAction" class="cat.action.UserAction" > <result name="add_success">/add_success.jsp</result> <result name="del_success">/del_success.jsp</result> <result name="update_success">/update_success.jsp</result> </action>
訪問的時候: 在! 後面傳要被調用的方法名
http://localhost:8080/Struts2-02/userAction!delUser(不推薦 使用)
//使用通配符的方式 <action name="userActionNew_*" class="cat.action.UserAction" method="{1}"> <result name="xxx_success">/{1}_success.jsp</result> // 這裡可以寫成 {1}.jsp </action>
http://localhost:8080/Struts2-02/userActionNew_updateUser
http://localhost:8080/Struts2-02/userActionNew_addUser
http://localhost:8080/Struts2-02/userActionNew_delUser
附: 可以在視圖中使用 ognl 表達式,以達到動態視圖的效果,如下
<result name="success">/WEB-INF/page/${某屬性}.jsp</result>
八、請求參數接收
1.採用基本類型接收請求參數(get/post)
在Action類中定義與請求參數同名的屬性,struts2便能自動接收請求參數並賦予給同名屬性。
請求路徑: http://localhost:8080/view.action?id=78
Public class HellowAction{ private integer id; 生成get 和set 方法 //struts用反射技術處理,調用與請求參數同名的屬性的seeter方法來獲取請求參數值 }
2.採用複合類型接收請求參數
請求路徑 同上 http://localhost:8080/view.action?id=78
Public class ProductAction{ private Product prod; public void setProd(Product prod){this.prod=prod} public Product getProd(){ return this.prod} }
struts2首先通過反射技術調用Product 的預設構造方法,創建出product對象,然後再通過反射技術調用product中與請示參數同名的屬性的setter方法來獲取請求參數值。
代碼實例:
1 建立Action類
public class ParamTestAction { private String userName; //為之生成get 和set方法 private String password; public String execute() { //if (this.userName.equals("admin") && this.password.equals("123")) { if ("admin".equals(this.userName) && "123".equals(this.password)) { //註意,這樣的技可以避免空指針異常 return "success"; } else { return "err"; } } }
2 在structs.xml中配置
<package name="packageSix" namespace="" extends="struts-default"> //註意,放在了預設的命名空間下,訪問就不用寫上/test了 <action name="ParamTestAction" class="cat.action.ParamTestAction" method="execute"> <result name="success">/ParamSucc.jsp</result> <result name="err">/ParamErr.jsp</result> </action> </package>
=====簡單類型
3 在ParamSucc.jsp中
<body>
登錄成功
${userName }
${password }
</body>
4 訪問,以get方式傳參
http://localhost:8080/Struts/ParamTestAction?userName=admin&password=1234
5 訪問,以 form表單的post方式傳參 在 Login.Jsp 中以form表單形式提交,結果同上
<form action="ParamTestAction" method="post"> <input type="text" name="userName" /> <input type="password" name="password" /> <input type="submit" value="提交" > </form>
===採用複合類型
1 建立Action類 先創建包bean ,再裡面然添 UserInfo類,然後再創建Action
public class BeanParamAction { private UserInfo userInfo; //生成get和set方法 public String execute() { if ("admin".equals(userInfo.getUserName()) && ("123".equals(userInfo.getPassword()))) { return "success"; } else { return "err"; } } }
2 在structs.xml中配置 可以發現,這裡的配置基本與上例相同
<action name="BeanParamAction" class="cat.action.BeanParamAction" method="execute">
<result name="success">/BeanParamSucc.jsp</result>
<result name="err">/BeanParamErr.jsp</result>
</action>
3 在BeanParamSucc.jsp 中
<body>
登錄成功 採用複合類型接收參數
${userInfo.userName}
${userInfo.password}
</body>
4 訪問,創建 BeanLogin.Jsp
<form action="BeanParamAction" method="post"> <input type="text" name="userInfo.userName" /> //註意參數的傳法 <input type="password" name="userInfo.password" /> //註意參數的傳法 <input type="submit" value="提交" > </form>
5 訪問 http://localhost:8080/Struts/BeanLogin.jsp ,添加入數據進行驗證
需要註意的是:
1)struts2 是通過反射,給userInfo註入的,所以 UserInfo 類必須提供預設的構造函數
2)UserInfo中可以有多餘欄位
九、訪問或添加request/session/application屬性
在struts2中 ,沒有繼承自HttpServlet , 方法,也沒有傳過來 request ,response 等參數。但假如我們想在作用域中傳值,怎麼處理?
struts2 有兩種處理方式
1.偽訪問 ActionContext
public String execute(){ ActionContext ctx=ActionContext.getContext(); //是struts2 提供的 ctx.getApplication().put("app_key", "全局範圍內的值"); //相當於往 ServletContext 中放入 ctx.getSession().put("session_key", "這是session內的值") ; //相當於往 session中放入 ctx.put("request_key", "這是request中的值"); //ctx.getSession() 等操作,得到的是 map集合 return "success"; }
//success.jsp <body> application : ${applicationScope.app_key} session: ${sessionScope.session_key } request: ${requestScope.request_key } </body>
2.真訪問 ServletActionContext 方式一
public String testScope(){ HttpServletRequest request = ServletActionContext.getRequest(); ServletContext application=ServletActionContext.getServletContext(); HttpSession session=request.getSession(); request.setAttribute("requestKey", "用request對象設置的request的值"); session.setAttribute("sessionKey", "用session對象設置的session的值"); application.setAttribute("appKey", "用application 對象設置的 application的值"); return "success"; } application : ${applicationScope.appKey} <br> session: ${sessionScope.sessionKey } <br> request: ${requestScope.requestKey } <br>
取得 作用域對象方式 二
(實現介面,由struts2 運行的時候註入)
public class BaseAction extends ActionSupport implements ServletRequestAware,ServletContextAware,ServletResponseAware { public HttpServletRequest request; public ServletContext servletContext; public HttpServletResponse response; public HttpSession session; public String execute(){ request.setAttribute("hahaha", "哈哈哈,這都是啥子"); return "success"; } @Override public void setServletResponse(HttpServletResponse response) { this.response=response; } @Override public void setServletContext(ServletContext context) { this.servletContext=context; } @Override public void setServletRequest(HttpServletRequest request) { this.request=request; this.session=request.getSession(); } }
說明:一般情況下,這個BaseAction是用來給別的Action進行繼承的。