1. 程式人生 > >Java框架之Struts2(二)

Java框架之Struts2(二)

war cit post extend bst edi 關系 執行 erp

一、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進行繼承的。

Java框架之Struts2(二)