隨筆 - 117  文章 - 72  trackbacks - 0

          聲明:原創作品(標有[原]字樣)轉載時請注明出處,謝謝。

          常用鏈接

          常用設置
          常用軟件
          常用命令
           

          訂閱

          訂閱

          留言簿(7)

          隨筆分類(130)

          隨筆檔案(123)

          搜索

          •  

          積分與排名

          • 積分 - 155795
          • 排名 - 390

          最新評論

          [標題]:[原]Struts2-深入探索
          [時間]:2009-8-26
          [摘要]:Struts2中一些零碎的知識點:struts.xml詳解、模型驅動、Preparable接口、防止表單重復提交、ActionContext、動態方法調用、異常
          [關鍵字]:浪曦視頻,Struts2應用開發系列,WebWork,Apache,深入探索
          [環境]:struts-2.1.6、JDK6、MyEclipse7、Tomcat6
          [作者]:Winty (wintys@gmail.com) http://www.aygfsteel.com/wintys

          [正文]:
          1、struts.xml詳解
          a. struts.properties
              在struts.xml中可以定義constant覆蓋struts-core.jar/org/apache/struts2/default.properties中的設置。
              例:<constant name="struts.custom.i18n.resources" value="message"/>

              也可以直接新建struts.properties(與struts.xml在同一目錄),在struts.properties中配置。推薦在struts.properties中進行配置。
              例:struts.custom.i18n.resources = message

          b. abstract package
              struts-core.jar/struts-default.xml,中有如下定義。
              <package name="struts-default" abstract="true">
                  ......
              </package>
              其中abstract="true"中,表示在此package中不能定義Action(與Java abstract類相似),僅供繼承。

          c. namespace
              strut.xml中:
              <package name="MyStruts" extends="struts-default" namespace="/mystruts">
              ......
              </package>

              默認命名空間為namespace="",命名空間要以"/"開頭。
              JSP訪問:<s:form action="miscellaneous" namespace="/mystruts">。
              不能寫成<s:form action="/mystruts/miscellaneous"> ,否則會發生錯誤:"No configuration found for the specified action: '/mystruts/miscellaneous' in namespace: '/miscellaneous'. Form action defaulting to 'action' attribute's literal value."[2]。

          d. 模塊化配置
              ......
              <struts>
                  <include file="struts1.xml" />
                  <package ...>
                      ......
                  </package>
              </struts>
              include中struts1.xml的編寫與struts.xml是類似的。


          2、屬性驅動與模型驅動
          屬性驅動:直接在Action中寫表單屬性。

          /StrutsHelloWorld/src/wintys/struts2/miscellaneous/MiscellaneousAction.java:

          package wintys.struts2.miscellaneous;
          import com.opensymphony.xwork2.ActionSupport;
          /**
           *
           * @author Winty (wintys@gmail.com)
           * @version 2009-8-24
           * @see http://wintys.blogjava.net
           */
          @SuppressWarnings("serial")
          public class MiscellaneousAction extends ActionSupport {
              private String name;
              private String password;
              public String getName() {
                  return name;
              }
              public void setName(String name) {
                  this.name = name;
              }
              public String getPassword() {
                  return password;
              }
              public void setPassword(String password) {
                  this.password = password;
              }
              
              @Override
              public String execute() throws Exception {
                  return SUCCESS;
              }
          }

          模型驅動:將屬性放到JavaBean中,Action需要實現com.opensymphony.xwork2.ModelDriven接口。ModelDrivenInterceptor 必須在之前StaticParametersInterceptor and ParametersInterceptor。這個順序已在defaultStack Interceptor中定義。

          /StrutsHelloWorld/src/wintys/struts2/miscellaneous/User.java:
          package wintys.struts2.miscellaneous;
          /**
           * 模型驅動Action中的模型
           * @author Winty (wintys@gmail.com)
           * @version 2009-8-25
           * @see http://wintys.blogjava.net
           */
          public class User {
              private String name;
              private String password;
              public String getName() {
                  return name;
              }
              public void setName(String name) {
                  this.name = name;
              }
              public String getPassword() {
                  return password;
              }
              public void setPassword(String password) {
                  this.password = password;
              }
          }

          /StrutsHelloWorld/src/wintys/struts2/miscellaneous/MiscellaneousModelDrivenAction.java:
          package wintys.struts2.miscellaneous;
          import com.opensymphony.xwork2.ModelDriven;

          @SuppressWarnings("serial")
          public class MiscellaneousModelDrivenAction extends ActionSupport implements
                  ModelDriven<User>{
              
              private User user = new User();
              
              @Override
              public User getModel() {
                  return user;
              }
              
              @Override
              public String execute() throws Exception {
                  return SUCCESS;
              }
          }

          3、Preparable接口
              Action還可以實現com.opensymphony.xwork2.Preparable接口,用于準備Action自己。Preparable中的prepare方法在Action執行其它方法前執行。

          4、使用simple 主題時,如何單獨格式化Struts錯誤提示信息
              單獨顯示name字段的fielderror:
          <s:fielderror>
              <s:param>name</s:param>
          </s:fielderror>

          5、Struts防止表單重復提交
              JSP頁面中加入token和actionerror:
          <s:actionerror />
          <s:form .../>
              <s:token />
          </s:form>

              token產生的actionerror的i18n key為:struts.message.invalid.token。

              在struts.xml中的Action配置中加入token interceptor,和invalid.token result:
                  <action name="miscellaneous" class="wintys.struts2.miscellaneous.MiscellaneousModelDrivenAction">
                      <result name="success">/miscellaneous/output.jsp</result>
                      <result name="input">/miscellaneous/input.jsp</result>

                      <result name="invalid.token" >/miscellaneous/input.jsp</result>
                      <interceptor-ref name="token" />
                      <interceptor-ref name="defaultStack" />
                  </action>

              生成的JSP頁面如下:
              <input type="hidden" name="struts.token.name" value="struts.token" />
              <input type="hidden" name="struts.token" value="ORU0RZIP8JWQ7BDZG4P1NJSEKITGG6X5" />

              struts.token.name指<s:token />中的name,默認為struts.token。也可以自己指定<s:token name="mytoken" />。則生成如下token:
              <input type="hidden" name="struts.token.name" value="mytoken" />
              <input type="hidden" name="mytoken" value="GFD13EW206G2DY9AB3SRIAVXXT1S915C" />

          6、通過Struts獲取Servlet API
              一般Java Web程序不能離開容器進行測試。容器內測試常用框架:Cactus(jakarta.apache.org/cactus/index.html) 、Mock。

              通過Struts獲取Servlet API,使程序可脫離容器測試。Struts中可通過如下方法獲取Servlet API:ActionContext 、ServletActionContext、ServletXXXAware。首選ActionContext,其次選擇ServletActionContext,再次ServletXXXAware。

          a. ActionContext
              com.opensymphony.xwork2.ActionContext.getActionContext()獲取ActionContext實例。

              ActionContext的get()和put()方法與HttpServletRequest的對應關系:
              ActionContext.get() <=> HttpServletRequest.getAttribute()
              ActionContext.put() <=> HttpServletRequest.setAttribute()

              例:
                  ActionContext context = ActionContext.getContext();
                  context.put("info", "this is ActionContext value");
              
              但是ActionContext無法獲取Servlet HttpResponse對象。

          b. ServletActionContext
              org.apache.struts2.ServletActionContext是com.opensymphony.xwork2.ActionContext的子類。

              使用靜態方法直接獲取Servlet對象:
              Request: ServletActionContext.getRequest();
              Response: ServletActionContext.getResponse();
              Session: ServletActionContext.getRequest().getSession();

              例:
                  Cookie cookie = new Cookie("mycookie" , "10000");
                  HttpServletResponse response = ServletActionContext.getResponse();
                  response.addCookie(cookie);

          c. ServletXXXAware接口
              org.apache.struts2.util.ServletContextAware接口
              org.apache.struts2.interceptor.ServletRequestAware接口
              org.apache.struts2.interceptor.ServletResponseAware接口
              org.apache.struts2.interceptor.SessionAware接口

              實現ServletXXXAware接口的Action會被Struts自動注入相應的Servlet對象。

              例:
          package wintys.struts2.miscellaneous;

          import org.apache.struts2.interceptor.ServletRequestAware;
          import com.opensymphony.xwork2.ActionSupport;

          @SuppressWarnings("serial")
          public class MiscellaneousModelDrivenAction extends ActionSupport implements
                  ServletRequestAware {
              private HttpServletRequest request;
              ......
              @Override
              public String execute() throws Exception {
                  //實現ServletRequestAware接口,Struts自動注入的request
                  Cookie[] cookies = this.request.getCookies();
                  for(Cookie ck : cookies){
                      System.out.print("cookie:" + ck.getName());
                      System.out.println(" = " + ck.getValue());
                  }

                  return SUCCESS;
              }
              ......
              @Override
              public void setServletRequest(HttpServletRequest request) {
                  this.request = request;
              }
          }

          7、動態方法調用
          a. Action配置中,由method指定動態調用方法的名稱。
          <action name="myaction" class="com.tests.MyAction" method="myexecute">
          ......
          </action>

          b.在JSP頁面中,調用Action時加感嘆號指定動態調用方法的名稱。
          <s:form action="myaction!myexecute" />

          c.通配符
          <action name="*action" class="com.tests.MyAction" method="{1}">
          則請求中helloaction對應到action中的hello()方法,以此類推。


          8、異常
              發生異常時,可轉到指定的result。由exception-mapping配置
          <action name="miscellaneous" class="wintys.struts2.miscellaneous.MiscellaneousModelDrivenAction">
              <result name="success">/miscellaneous/output.jsp</result>
              <result name="input">/miscellaneous/input.jsp</result>
              <exception-mapping  exception="wintys.struts2.miscellaneous.NameInvalidException" result="nameInvalid" />
              <result name="nameInvalid">/miscellaneous/nameInvalidException.jsp</result>
          </action>

              也可以配置全局exception mapping
          <global-exception-mapping>
              <exception-mapping result="nameInvalid" />
          </global-exception-mapping>

              nameInvalidException.jsp:
          <s:property value="exception"/>
          <s:property value="exceptionStack" />

          NameInvalidException.java:
          package wintys.struts2.miscellaneous;
          @SuppressWarnings("serial")
          public class NameInvalidException extends Exception {
              public NameInvalidException(String message) {
                  super(message);
              }
          }

          9、詳細代碼
          /StrutsHelloWorld/WebRoot/miscellaneous/input.jsp:
          <%@ page language="java"  contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>
          <%@ taglib uri="/struts-tags" prefix="s" %>
          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
          <html>
            <head>
              <title>Input</title>
            </head>
            <body>
               <s:actionerror/>
               
              <s:form action="miscellaneous" method="post" theme="simple" namespace="/mystruts">
                  <s:token name="mytoken"/>
                  
                  用戶名:<s:textfield name="name" />
                  <s:fielderror >
                      <s:param>name</s:param>
                  </s:fielderror>
                  <br />
                  
                  
                  密碼:<s:textfield name="password"/>
                  <s:fielderror >
                      <s:param>password</s:param>
                  </s:fielderror>
                  <br />
                  
                  <s:submit name="提  交" />
              </s:form>
              
              <hr />
              動態方法調用方法二:    miscellaneous!myexecute
              <s:form action="miscellaneous!myexecute" namespace="/mystruts">
                  <s:token name="mytoken"/>
                  <s:hidden name="name" value="test" />
                  <s:hidden name="password" value="test" />
                  <s:submit name="提交執行myexecute() " />
              </s:form>
            </body>
          </html>


          /StrutsHelloWorld/WebRoot/miscellaneous/output.jsp:
          <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
          <%@ taglib uri="/struts-tags" prefix="s" %>
          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
          <html>
            <head>
              <title>Output</title>
            </head>
            <body>
                提交結果:<br/>
              用戶名:<s:property value="name"/> <br />
              密碼:<s:property value="password"/> <br />
              <hr />
              ${request.info}
              ${cookie.mycookie.value }
            </body>
          </html>


          /StrutsHelloWorld/src/wintys/struts2/miscellaneous/MiscellaneousModelDrivenAction.java:
          package wintys.struts2.miscellaneous;
          import javax.servlet.http.Cookie;
          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;
          import org.apache.struts2.ServletActionContext;
          import org.apache.struts2.interceptor.ServletRequestAware;
          import com.opensymphony.xwork2.ActionContext;
          import com.opensymphony.xwork2.ActionSupport;
          import com.opensymphony.xwork2.ModelDriven;
          /**
           * Struts2深入探索
           * @author Winty (wintys@gmail.com)
           * @version 2009-8-26
           * @see http://wintys.blogjava.net
           */
          @SuppressWarnings("serial")
          public class MiscellaneousModelDrivenAction extends ActionSupport implements
                  ModelDriven<User> , ServletRequestAware {
              
              private User user = new User();
              private HttpServletRequest request;
              
              @Override
              public User getModel() {
                  return user;
              }
              
              @Override
              public String execute() throws Exception {
                  System.out.println("this is model driven action");
                  
                  if(user.getName().equals("admin")){
                      throw new NameInvalidException("name 'admin' is invalid");
                  }
                  
                  //ActionContext.put相當于HttpServletRequest.setAttribute()
                  ActionContext context = ActionContext.getContext();
                  context.put("info", "this is ActionContext value");
                  
                  //ServletActionContext.getResponse得到Response對象
                  Cookie cookie = new Cookie("mycookie" , "10000");
                  HttpServletResponse response = ServletActionContext.getResponse();
                  response.addCookie(cookie);
                  
                  //實現ServletRequestAware接口,Struts自動注入的request
                  Cookie[] cookies = this.request.getCookies();
                  for(Cookie ck : cookies){
                      System.out.print("cookie:" + ck.getName());
                      System.out.println(" = " + ck.getValue());
                  }

                  return SUCCESS;
              }
              
              public String myexecute()throws Exception{
                  System.out.println("myexecute()");
                  
                  return SUCCESS;
              }
              
              @Override
              public void validate() {
                  if(user.getName() == null || user.getName().equals("")){
                      this.addFieldError("name", "invalid name");
                  }
              }

              @Override
              public void setServletRequest(HttpServletRequest request) {
                  this.request = request;
              }
          }


          /src/struts.xml:
          <?xml version="1.0" encoding="UTF-8" ?>
          <!DOCTYPE struts PUBLIC
              "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
              "http://struts.apache.org/dtds/struts-2.0.dtd">

          <struts>  
              <package name="MyStruts" extends="struts-default" namespace="/mystruts">
                  <!-- Struts2深入探索 -->
                  <action name="miscellaneous" class="wintys.struts2.miscellaneous.MiscellaneousModelDrivenAction">
                      <result name="success">/miscellaneous/output.jsp</result>
                      <result name="input">/miscellaneous/input.jsp</result>
                      <exception-mapping  exception="wintys.struts2.miscellaneous.NameInvalidException" result="nameInvalid" />
                      <result name="nameInvalid">/miscellaneous/nameInvalidException.jsp</result>
                      <result name="invalid.token" >/miscellaneous/input.jsp</result>
                      <interceptor-ref name="token" />
                      <interceptor-ref name="defaultStack" />
                  </action>
              </package>
          </struts>

          [參考資料]:
              [1]《浪曦視頻之Struts2應用開發系列》
              [2] No configuration found for the specified action : http://javasunnyboy.javaeye.com/blog/254753

          [附件]:
              源代碼 : http://www.aygfsteel.com/Files/wintys/struts_miscellaneous.zip
          posted on 2009-08-29 20:32 天堂露珠 閱讀(918) 評論(0)  編輯  收藏 所屬分類: Struts
          主站蜘蛛池模板: 左云县| 华容县| 太仆寺旗| 定南县| 衢州市| 高台县| 汉中市| 庄浪县| 苍溪县| 阳山县| 鲁山县| 金山区| 长子县| 昌吉市| 临武县| 三门县| 漠河县| 沧源| 潍坊市| 双江| 辽宁省| 清水县| 沽源县| 清远市| 赤水市| 抚宁县| 明水县| 昆明市| 武山县| 冀州市| 突泉县| 扶余县| 晋江市| 阳山县| 吉安市| 柳林县| 突泉县| 山阳县| 苍溪县| 张家界市| 邳州市|