Java學習大全 之 Struts2

royliang_peng發表於2011-08-15

1、struts2是在WebWork2基礎發展而來的,是輕量級的框架也是屬於MVC框架,特點:多action例項的、不依賴servlet和struts1 API。
2、struts2的配置檔案預設是struts.xml,由於struts2通過filter啟動的所以配置檔案放在類路徑下,struts1是通過servlet啟動所以配置檔案放在WEB-INF下。
 servlet過濾器實在java servlet規範定義的,能過對url請求和響應進行檢查和修改。
 <filter>
     <filter-name>struts2</filter-name>
     <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
   <!-- 自從Struts 2.1.3以後,上面的FilterDispatcher已經標註為過時,下面的為新的filter -->
     <!--<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、自定義過濾器
 步驟
 一、實現javax.servlet.Filter介面
  public void init(FilterConfig config) throws ServletException;//servlet容器建立過濾器例項後呼叫
  //完成實際的過濾操作,返回響應之前的會呼叫doFilter方法
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain filter) throws IOException, ServletException;
  public void destroy();//容器在銷燬過濾器前呼叫
 二、在web.xml配置
  <filter>
      <filter-name>過濾器名字</filter-name>
      <filter-class>過濾器類</filter-class>
      <init-param>
       <param-name>引數名字</param-name>
       <param-value>引數值</param-value>
      </init-param>
  </filter>
  <filter-mapping>
      <filter-name>過濾器名字</filter-name>
      <url-pattern>url</url-pattern>
  </filter-mapping>
4、配置action
 package元素是用來把actoin分類進行的管理,還可以重用。
 package的name屬性是不選的,表示該package的名稱
 package的extends屬性是可選的,允許一個包繼承一個或者多前面定義的包
 package的abstract屬性是可選的,設定為true表示抽象包,抽象包不需要action定義,被其他包所繼承
 package的namespace屬性是可選的,將action配置為不同的名稱空間。預設名稱空間是"/",如果指定了名稱空間,請求先去指定的名稱空間找action,如果找不到則去預設的名稱空間找。
 例子:
 配置檔案
  <!--宣告抽象包-->
  <package name="default" abstract="true" extends="struts-default">
  </package>
  <!--繼承抽象包-->
  <package name="package1" extends="default">
   <!--沒有配置method屬性表示執行Action類的預設的方法execute()-->
   <action name="default" class="com.TestAction">
    <result name="success">/index.jsp</result>
   </action>
   <!--指明該action執行add方法-->
   <action name="add" class="com.TestAction" method="add">
    <result name="success">/index.jsp</result>
   </action> 
  </package>
  <!--指定名稱空間的action,那麼訪問delete需要加上名稱空間:admin/delete-->
  <package name="package2" extends="struts-default" namespace="/admin">
   <action name="delete" class="com.TestAction" method="delete">
    <result name="success">/index.jsp</result>
   </action> 
  </package>
 TestAction.java類
  public class TestAction extends ActionSupport {
   @Override
   public String execute() throws Exception {
    System.out.println("預設的處理方法");
    return SUCCESS;
   }
   public String add(){
    System.out.println("add處理方法");
    return SUCCESS;
   }
   public String delete(){
    System.out.println("delete處理方法");
    return SUCCESS;
   }
  }
 index.jsp頁面
  <%
  String path = request.getContextPath();
  String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
  %> 
    <a href="<%=path %>/default">不指定method屬性執行預設的方法</a><br/>
    <a href="<%=path %>/add">指定執行add方法</a><br/>
    <a href="<%=path %>/admin/delete">指定指定名稱空間的action</a><br/>

5、result元素
 location:指定邏輯檢視
 parse:是否允許在實際檢視中使用ongl表示式,引數預設為true
 success:表示請求處理成功
 error:表示請求失敗
 none:表示請求完成後不跳轉任何頁面
 input:表示輸入時如果驗證失敗調到什麼地方
 login:表示登入失敗時候跳轉的目標
 chain:用來處理action鏈
 chart:用來整合JFreeChart的結果型別
 dispatcher:用來轉向頁面
 freemarker:處理FreeMark模板
 httpheader:控制特殊HTTP行為的結果型別
 jasper:用於JasperReports整合的結果型別
 jsf:JSF整合的結果型別
 redirect:重定向到一個url
 redirect-action:重定向一個action
 stream:向瀏覽器傳送InputStream物件,通常用來處理檔案下載的,還可以用於返回ajax資料
 titles:與Title整合的結果型別
 velocity:處理Velocity模板
 xslt:處理XML/XSLT模板
 plaintext:顯示原始檔案內容,如下載原始碼
 全域性result的配置使得連線得到共享
  <package ....>
   <global-results>
    <result name="success">/success.jsp</result>
   </global-results>
  </package>

6、struts.properties配置
 struts.action.extension: 指明action的字尾,如action,do,"struts.action.extension=action,do,"表示字尾為action或者do或者不用點字尾
 struts.configuration:配置檔案管理器預設為org.apache.struts2.config.DefaultConfiguration類
 struts.configuration.files: struts自動載入的一個配置檔案列表
 struts.configuration.xml.reload:是否載入xml配置值為true、false
 struts.continuations.package:含有actions的完整連續的package名稱
 struts.custom.i18n.resources:指定國際化檔案的字首,多個檔案用逗號分開
 struts.custom.properties:配置使用者自定義配置檔案的路徑,若有多個可以用逗號隔開
 struts.devMode:設定是否為struts開發模式。這樣會顯示更多友好的錯誤提示
 struts.enable.DynamicMethodInvocation:是否允許動態方法呼叫,值為true、false
 struts.i18n.encoding:指定字符集
 struts.i18n.reload:該屬性設定是否每次HTTP請求到達時,系統都重新載入資原始檔。該屬性預設值是false
 struts.locale:設定預設的國際化地區資訊
 struts.multipart.maxSize:multipart請求資訊的最大尺寸(檔案上傳用)
 struts.multipart.parser:專為multipart請求資訊使用的org.apache.struts2.dispatcher.multipart.MultiPartRequest解析器介面(檔案上傳用)
 struts.multipart.saveDir:設定儲存上傳檔案的目錄
 struts.tag.altSyntax:是否能在struts2標籤中使用表示式,值為true、false
 struts.serve.static:表示是否通過jar檔案提供靜態內容服務,預設為true
 struts.ui.templateDir:該屬性指定檢視主題所需要模板檔案的位置,該屬性的預設值是template
 struts.ui.theme:該屬性指定檢視標籤預設的檢視主題,該屬性的預設值是xhtml
 struts.url.http.port設定http埠
 struts.url.https.port:設定https埠,該屬性指定的是Web應用的加密服務埠
 struts.velocity.configfile:設定velocity框架配置檔案路徑
 struts.velocity.contexts:velocity:該屬性指定Velocity框架的Context位置
 struts.velocity.toolboxlocation:指定Velocity框架的toolbox的位置

7、獲得使用者表單與ModelDriven<T>介面
 一、不實現ModelDriven介面的例子:
 LoginAction.java請求處理類
  public class LoginAction extends ActionSupport {
   private String username;//使用者名稱,對應表單輸入框的name屬性值
   private String password;//密碼,對應表單輸入框的name屬性值
   public String getUsername() {
    return username;
   }
   public void setUsername(String username) {
    this.username = username;
   }
   public String getPassword() {
    return password;
   }
   public void setPassword(String password) {
    this.password = password;
   }
   @Override
   public String execute() throws Exception {
    System.out.println(username);
    System.out.println(password);
    return SUCCESS;
   }
  }
 action配置
  <package name="login" extends="struts-default" >
   <action name="login" class="com.LoginAction">
    <result name="success">/index.jsp</result>
   </action>
  </package> 
 index.jsp頁面
  <form action="login" method="post">
   使用者名稱<input name="username" type="text"/><br/>
   密碼<input name="password" type="password"/><br/>
   <input type="submit" value="登入"/><br/>
  </form>
 二、實現ModelDriven介面的例子:
 LoginAction.java請求處理類
  public class LoginAction extends ActionSupport implements ModelDriven<User> {
   private User user = new User();//需要手動new一個User物件
   //實現介面的方法,返回User物件
   public User getModel() {
    return this.user;
   }
   @Override
   public String execute() throws Exception {
    System.out.println(user.getUsername());
    System.out.println(user.getPassword());
    return SUCCESS;
   }
  }
 action配置同上
 index.jsp頁面同上,這時表單輸入框的name屬性值對應的是User物件的屬性名
 
8、 攔截器配置
 <package name="login" extends="struts-default">
  <!--
   攔截器棧(或堆)
   攔截器棧就是將多個攔截器進行打包,
   攔截器包裡還可以引用其他的攔截器棧
   如果有多個action的話,直接呼叫棧即可。
   比如struts1.xml中也想引用exectue_action_timer_interceptor的話,
   struts1.xml中繼承login包即可
  -->
  <interceptors>
   <!--定義了一個攔截器名字為timer型別是com.opensymphony.xwork2.interceptor.TimerInterceptor,可以算出action的執行時長-->
      <interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>
      <!--interceptor-stack表示攔截器棧可以包含多個攔截器-->
   <interceptor-stack name="exectue_action_timer_interceptor">
    <interceptor-ref name="timer" /><!--引用了上面的攔截器timer-->
    <interceptor-ref name="defaultStack" /><!--預設的攔截器defaultStack-->
   </interceptor-stack>
  </interceptors>
  <action name="login" class="cn.serup.struts2.login.LoginAction">
   <result name="success">/success.jsp</result>
   <result name="input">/index.jsp</result>
   <result name="error">/error.jsp</result>
   <!--如果指定攔截器,那麼預設的就沒有執行,那麼就獲取不了表單傳來的值。所以指定攔截器時候需要加上預設的攔截defaultStack-->
   <interceptor-ref name="exectue_action_timer_interceptor" />
  </action>
 </package>

9、服務端action跳轉chain和客戶端action跳轉redirectAction
 chain例子:
  <!--
   如果使用chain來跳轉到某個Action上,
   則需要指定param引數的name屬性為actionName,
   不指定則預設是location,location是指定某個資源JSP/HTML
  --> 
  <action name="test1" class="cn.serup.struts2.Test1Action">
   <result name="success" type="chain">
    <!-- name="actionName"表示請求的名字,不需要加字尾 ,告訴我action名稱即可-->   
    <param name="actionName">test2</param><!--服務端跳轉到名字為test2的actoin-->
   </result>
  </action>
  <action name="test2" class="cn.serup.struts2.Test2Action">
   <result>/test1.jsp</result>
  </action>
 redirectAction例子
  <!--
   可以通過Result來傳參,可以在struts.xml檔案中 編寫EL表示式 ${nane}是屬性的名稱
   在Test1Action中獲得name的值,然後傳到到Test2Action中 在Test2Action中接收
  -->
  <action name="test11" class="cn.serup.struts2.Test1Action">
   <result name="success" type="redirectAction">
    <param name="actionName">test22?name=${name}</param>
   </result>
  </action>
  <action name="test22" class="cn.serup.struts2.Test2Action">
   <!--
    這裡獲得了test11 請求中的屬性name的值, 然後通過URL來傳遞引數 在頁面中通過EL表示式來接收並輸入${param.name}
   -->
   <!--redirect表示客戶端重定向到那個頁面-->
   <result type="redirect">/test1.jsp?name=${name}</result>
  </action>

10、獲得非servlet繫結的request、session和application
 方法一:
 ActionContextTest.java類
 public class ActionContextTest extends ActionSupport {
  private Map request ;//request的鍵值對
  private Map session ;//session的鍵值對
  private Map application ;//application的鍵值對
  /**
   * 第一種獲取方法:非Ioc(控制反轉)
   * 通過ActionContext物件的 get(Object) 、getSession() 、getApplication()
   * 這三個方法分別能獲取Map型別的request 和 session 以及 application
   * 獲取是首先需要獲取一個ActionContext物件,然後再呼叫上面三個方法
   * 注意:如果使用此方法獲得,則必須在execute()方法中初始化,或構造方法
   */
  public ActionContextTest() {
   //非Ioc意思就是自己控制,自己建立物件 ActionContext.getContext();
   ActionContext c = ActionContext.getContext() ;
   request = (Map)c.get("request") ;
   session = c.getSession() ;
   application = c.getApplication() ;
  }
  @Override
  public String execute() throws Exception {
   request.put("r1","r1_value") ;
   session.put("s1","s1_value") ;
   application.put("a1","a1_value") ;
   return SUCCESS ;
  }
 }
 方法二:
 ActionContextTest2.java類
 public class ActionContextTest2 extends ActionSupport implements RequestAware,SessionAware,ApplicationAware{
  private Map request ;//request的鍵值對
  private Map session ;//session的鍵值對
  private Map application ;//application的鍵值對
  /**
   * 第二種獲取方法:Ioc(控制反轉)
   * 通過RequestAware、SessionAware、ApplicationAware
   * 這三個介面分別能獲取Map型別的request 和 session 以及 application
   * 需要實現它們的方法。
   * 然後由struts容器來注入
   */
  public void setRequest(Map<String, Object> request) {
   this.request = request;
  }
  public void setSession(Map<String, Object> session) {
   this.request = session;
  }
  public void setApplication(Map<String, Object> application) {
   this.application = application;
  }
  public String execute() throws Exception {
   request.put("r1","r1_value") ;
   session.put("s1","s1_value") ;
   application.put("a1","a1_value") ;
   return SUCCESS ;
  }
 }
 頁面顯示
 <%@page contentType="text/html;charset=utf-8"%>
 <%@taglib prefix="s" uri="/struts-tags" %>
 request-s.tags:<s:property value="#request.r1"/><br/>
 request-el:${requestScope.r1} ;<br/>
 <p></p>
 session-s.tags:<s:property value="#session.s1"/><br/>
 session-el:${sessionScope.s1} ;<br/>
 <p></p>
 application-s.tags:<s:property value="#application.a1"/><br/>
 application-el:${applicationScope.a1} ;<br/>

11、獲得與servlet繫結的request、session和application
 方法一:
 ServletActionContextTest.java類
 public class ServletActionContextTest extends ActionSupport {
  private HttpServletRequest request ;
  private HttpSession session ;
  private ServletContext application ;
  /**
   * 第一種獲取方法:與servlet容器繫結
   * 通過ServletActionContext物件來獲得,
   * 返回的是HttpServletRequest...
   */
  public String execute() throws Exception {
   request = ServletActionContext.getRequest() ;
   session = request.getSession() ;
   application = ServletActionContext.getServletContext() ;
   
   request.setAttribute("r1","r1_value") ;
   session.setAttribute("s1","s1_value") ;
   application.setAttribute("a1","a1_value") ;
   return SUCCESS ;
  }
 } 
 方法二:
 ServletActionContextTest2.java類
 public class ServletActionContextTest2 extends ActionSupport implements ServletRequestAware,ServletContextAware {
  private HttpServletRequest request ;
  private HttpSession session ;
  private ServletContext application ;
  /**
   * 第一種獲取方法:與servlet容器繫結
   * 通過ServletActionContext物件來獲得,
   * 返回的是HttpServletRequest...
   */
  public void setServletRequest(HttpServletRequest request) {
   this.request = request;
  }
  public void setServletContext(ServletContext application) {
   this.application = application;
  }
  public String execute() throws Exception {
   request.setAttribute("r1","r1_value") ;
   session.setAttribute("s1","s1_value") ;
   application.setAttribute("a1","a1_value") ;
   return SUCCESS ;
  }
 }
 頁面顯示同上
 
12、OGNL(Object-Graph Navigation Language)物件圖導航語言
 功能一、支援物件方法呼叫,形式如:objName.methodName();   
 功能二、支援類靜態的方法呼叫和值訪問,表示式的格式為@[類全名(包括包路)]@[方法名 |  值名],struts.ognl.allowStaticMethodAccess=true表示允許靜態方法訪問。
 <s:property value="@java.lang.Math@floor(44.56)"/>呼叫靜態方法和方法(非私有的)
 功能三、支援賦值操作和表示式串聯
 功能四、訪問OGNL上下文(OGNL context)和ActionContext
 功能五、操作集合物件
 
 #號用於訪問非根物件(struts中值棧為根物件)
 #號用於過濾和投影集合
 #號用於構造一個map,如#{'foo1':'bar1', 'foo2':'bar2'}
 %號的用途是在標籤的屬性值被理解為字串型別時,告訴執行環境%{}裡的是OGNL表示式。
 $號在國際化資原始檔中,引用OGNL表示式。   
 $號在Struts 2配置檔案中,引用OGNL表示式。

 首先在頁面中引入<%@taglib prefix="s" uri="/struts-tags" %>標籤
 訪問物件中的屬性:
 user.name:<s:property value="user.name"/><br/>
 user.sex:<s:property value="user.sex"/><br/>
 user.addr.address:<s:property value="user.addr.address"/><br/>
 
 訪問集合:
 <s:property value="arrays"/><BR/>
 訪問陣列某個元素:
 <s:property value="arrays[0]"/><p></p>
 
 訪問Set集合:
 為什麼只輸出3個,但我的set集合中有6個元7D20?原因:set是無序的,重複的被覆蓋<br/>
 <s:property value="set"/><br/>
 
 為什麼獲取不出set集合中的某個屬性?原因是set是無序的
 <s:property value="set[0]"/><p></p>
 
 獲取Map集合:
 <s:property value="map"/><br/>
 獲取Map集合中的某個元素:
 <s:property value="map.key1"/><br/>
 獲取所有Map中的所有Key值:
 <s:property value="map.keys"/><br/>
 獲取所有Map中的所有value值:
 <s:property value="map.values"/><br/>
 
 集合中的偽類
 list:<s:property value="list.size"/>個<br/>
 array:<s:property value="arrays.length"/>個<br/>
 set:<s:property value="set.size"/>個<br/>
 map:<s:property value="map.size"/>個<br/>
 
 獲取List中的所有物件
 <s:property value="listObject[0].name"/>
 <s:property value="listObject[0].sex"/>
 <s:property value="listObject[0].addr.address"/>
 <br/>
 <s:property value="listObject[1].name"/>
 <s:property value="listObject[1].sex"/>
 <s:property value="listObject[1].addr.address"/>
 <br/>
 使用投影來獲得集合中的物件
 <s:property value="listObject.{name}"/><br/>
 <s:property value="listObject.{name}[0]"/><br/>
 <s:property value="listObject.{name}[1]"/><br/>
 
 

13、ValueStack值棧物件
 值棧(Value Stack)是Struts 2框架的核心概念,所有核心元件都以某種方式與之進行互動,它提供對上下文資訊和執行環境中元素的訪問機制
 值棧就是記憶體空間,棧在記憶體中是後進先出,先進後出,每個請求都會建立一個值棧。值棧的生命週期是跟request請求一致的。客戶端跳轉的話無法共享值棧。
 ValueStack物件貫穿整個Action的生命週期(每個Action類的物件例項會擁有一個ValueStack物件)。
 當Struts 2接收到一個.action的請求後,會先建立Action類的物件例項,但並不會呼叫Action方法,而是先將Action類的相應屬性放到ValueStack物件的頂層節點(ValueStack物件相當於一個棧)。只是所有的屬性值都是預設的值,如String型別的屬性值為null,int型別的屬性值為0等。
 在處理完上述工作後,Struts 2就會呼叫攔截器鏈中的攔截器,如獲得請求引數的攔截器是params等,在這些攔截器內部讀取相應的值,並更新ValueStack物件頂層節點的相應屬性的值。
 當呼叫完所有的攔截器後,最後會呼叫Action類的Action方法,但在呼叫Action方法之前,會將ValueStack物件中的屬性的值終值賦給Action類的相應屬性。
 對於值棧,則是通過那些使用OGNL(Object Graph Navigational Language,物件圖導航語言)語法所編寫的特定表示式來查詢,或者是在該表示式之上求值。

14、檔案上傳
 UploadAction.java類
 public class UploadAction extends ActionSupport {
  private List<File> upload;//上傳的檔案列表
  private List<String> uploadFileName;//檔案的名稱不能亂寫,變數名= 檔案變數 + FileName
  private List<String> uploadContentType;//該變數不能亂寫,File物件變數+ContentType獲得檔案型別,由struts來填充。同上原理。
  public List<File> getUpload() {
   return upload;
  }
  public void setUpload(List<File> upload) {
   this.upload = upload;
  }
  public List<String> getUploadFileName() {
   return uploadFileName;
  }
  public void setUploadFileName(List<String> uploadFileName) {
   this.uploadFileName = uploadFileName;
  }
  public List<String> getUploadContentType() {
   return uploadContentType;
  }
  public void setUploadContentType(List<String> uploadContentType) {
   this.uploadContentType = uploadContentType;
  }
  @Override
  public String execute() throws Exception {
   if(upload!=null){
    //獲得絕對目錄
    String dir = ServletActionContext.getServletContext().getRealPath("upload");
    for (int i = 0; i < upload.size(); i++) {
     File file = upload.get(i);
     InputStream is = new FileInputStream(file);
     //根據要保持的檔案來建立輸出流
     OutputStream os = new FileOutputStream(dir + "/" + uploadFileName.get(i));
     byte[] buff = new byte[(int) file.length()];
     int len = 0;
     while((len = is.read(buff, 0, buff.length)) != -1){
      os.write(buff, 0, len);
     }
     os.close();
     is.close();
    }
   }
   return SUCCESS;
  }
 }
 index.jsp頁面
   <form action="testUpload" method="post" enctype="multipart/form-data">
  <input name="upload" type="file"  /><br/>
  <input name="upload" type="file" /><br/>
  <input type="submit" value="上傳"/><br/>
 </form>
 struts配置
 <package name="upload" extends="struts-default">
  <action name="testUpload" class="com.UploadAction">
   <result name="success">/index.jsp</result>
  </action>
 </package>
 <constant name="struts.multipart.saveDir" value="upload"></constant><!--表示上傳檔案的預設目錄-->
 <constant name="struts.multipart.maxSize" value="102400000000"></constant><!--限制上傳檔案的大小-->

15、struts2和spring2.5整合:把struts2的建立交給spring
 需要匯入struts2的包:struts2-spring-plugin.jar(用途是:在spring容器找到所需要的Action例項,通過class屬性值對應bean的id來找。)
 web.xml配置檔案
 <!--listener是servlet的監聽器,它可以監聽客戶端的請求、伺服器的操作等。-->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener> 
  <context-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>classpath:applicationContext.xml</param-value>
  </context-param>
  
 applicationContext.xml配置檔案:監聽器監聽到web容器建立好了就載入applicationContext.xml,這樣就載入了bean
  <bean id="loginAction" class="bean.LoginAction" scope="prototype"></bean>
  
 struts.xml配置檔案:由於Action被spring建立了所以action元素的class屬性值直接寫bean的id就可以了
     <package name="default" extends="struts-default">
      <!--loginAction是指哪 個bean-->
      <action name="login" class="loginAction">
       <result>/index.jsp</result>
      </action>
     </package>
    
    index.jsp頁面
    <form action="login" method="post" >
     <input name="username" type="text"/><br/>
     <input name="password" type="text"/><br/>
     <input type="submit"/><br/>
    </form>   
16、

 

相關文章