熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java開源技術 >> 正文

Struts1.x系列教程(1):用MyEclipse開發第一個Struts程序

2013-11-23 20:25:23  來源: Java開源技術 

  本系列教程將詳細介紹Struts x的基本原理和使用方法讀者可以參閱《Struts 系列教程》來比較Struts x和Struts x的相同點和不同點

  在這篇文章中將以一個簡單的例子(mystruts)來演示如何使用MyEclipse來開發運行Struts程序並給出了解決ActionForm出現亂碼問題的方法讀者可以從本文中了解開發Struts x程序的基本過程

  本文給出的程序要實現什麼功能

  mystruts是一個錄入和查詢產品信息的程序為了方便起見本例中的產品信息表只包括了產品ID產品名稱和產品價格三個字段mystruts的主要功能如下

   接受用戶輸入的產品ID產品名稱和產品價格

   驗證這些字段的合法性如果某些字段的輸入不合法(如未輸入產品ID)程序會forward到一個信息顯示頁並顯示出錯原因

   如果用戶輸入了正確的字段值程序會將這些字段值保存到數據庫中並顯示保存成功信息

   用戶輸入產品名稱並根據產品名稱進行模糊查詢如果存在符合要求的產品信息程序會以表格形式顯示這些產品的信息同時顯示記錄數如果未查到任何記錄會顯示沒有符合要求的記錄!信息

  編寫程序前的准備工作

   建立數據庫

  在編寫程序之前需要建立一個數據庫(struts)和一個表(t_products)建立數據庫和表的SQL腳本如下所示

  

  # 建立數據庫struts
  CREATE DATABASE IF NOT EXISTS struts DEFAULT CHARACTER SET GBK;

  # 建立表t_products
  CREATE TABLE IF NOT EXISTS strutst_products (
    product_id varchar() NOT NULL
    product_name varchar() NOT NULL
    price float NOT NULL
    PRIMARY KEY  (product_id)
  ) ENGINE=InnoDB DEFAULT CHARSET=gbk;

   建立一個支持strutsx的samples工程

  用MyEclipse建立一個samples工程(Web工程)現在這個samples工程還不支持Strutsx(沒有引入相應的Struts jar包strutsconfigxml文件以及其他和Struts相關的配置)然而在MyEclipse中這一切並不需要我們手工去加入而只需要使用MyEclipse的「New Struts Capabilities」對話框就可以自動完成這些工作

  首先選中samples工程然後在右鍵菜單中選擇「MyEclipse」 > 「New Struts Capabilities」啟動「New Struts Capabilities」對話框對默認的設置需要進行如下的改動

  ()將Struts specification改為Struts

  ()將Base package for new classes改為struts

  ()將Default application resources改為strutsApplicationResources

  改完後的「New Struts Capabilities」對話框如圖所示

  

  在設置完後點擊Finish按鈕關閉對話框在向samples工程添加支持Struts的功能後主要對samples工程進行了三個操作

  ()引入了Struts 的jar包(在samples的工程樹中多了一個Struts Libraries節點)

  ()在WEBINF目錄中添加了一個strutsconfigxml文件文件的默認內容如下面的代碼所示

  

  <?xml version= encoding=UTF?>
  <!DOCTYPE strutsconfig PUBLIC //Apache Software Foundation//DTD Struts Configuration //EN
config__dtd>  
  <strutsconfig>
    <datasources />
    <formbeans />
    <globalexceptions />
    <globalforwards />
    <actionmappings />
    <messageresources parameter=strutsApplicationResources />
  </strutsconfig>

  ()在WEBINF中的webxml文件中添加了處理Struts動作的ActionServlet的配置代碼如下

  

  <servlet>
    <servletname>action</servletname>
    <servletclass>orgapachestrutsactionActionServlet</servletclass>
    <initparam>
      <paramname>config</paramname>
      <paramvalue>/WEBINF/strutsconfigxml</paramvalue>
    </initparam>
    <initparam>
      <paramname>debug</paramname>
      <paramvalue></paramvalue>
    </initparam>
    <initparam>
      <paramname>detail</paramname>
      <paramvalue></paramvalue>
    </initparam>
    <loadonstartup></loadonstartup>
  </servlet>
  <servletmapping>
    <servletname>action</servletname>
    <urlpattern>*do</urlpattern>
  </servletmapping>

  到目前為止samples工程已經完全支持Struts了讀者可以看到如果不使用MyEclipse那麼上面所列出的配置文件的內容都必須手工輸入因此使用MyEclipse來開發Struts程序可以省去很多配置xml文件的工作

  實現程序的首頁(indexjsp)

  首先在<samples工程目錄>中建立一個mystruts目錄然後在<samples工程目錄> mystruts目錄中建立一個indexjsp文件這個文件的內容如下

  

  <%@ page pageEncoding=GBK%>
  <% 引用Struts tag%>
  <%@ taglib uri=html prefix=html%>
  <html>
      <head>
          <title>主界面</title>
      </head>
      <body>
          <table align=center cellpadding= width=%>
              <tr>
                  <td align=right width=%>
                  <% 使用Struts tag%>
                      <html:link forward=newProduct>錄入產品信息</html:link>
                  </td>
                  <td>
                      <html:link forward=searchProduct>查詢產品信息</html:link>
                  </td>
              </tr>
          </table>
      </body>
  </html>

  在MyEclipse中啟動Tomcat(如果Tomcat處於啟動狀態在修改完配置文件後建議在MyEclipse的Servers頁重新發布samples工程以使修改生效)在IE中輸入如下的URL

  

  我們發現在輸入上面的URL後在IE中並未顯示正確的運行結果而是拋出了如下的異常

  MalformedURLException Cannot retrieve ActionForward named newProduct

  這個異常表明程序並未找到一個叫newProduct的forward(forward將在後面詳細地講述)因此可以斷定在JSP中使用forward時這個forward必須存在下面我們來添加indexjsp頁面中所使用的兩個forwardnewProduct和searchProduct這兩個forward分別引向了建立產品信息的頁面(newProductjsp)和查詢產品信息的頁面(searchProductjsp)我們可以在strutsconfigxml文件中<strutsconfig>節點中添加兩個全局的forward代碼如下

  

  <globalforwards>
      <forward name=newProduct path=/mystruts/newProductjsp />
      <forward name=searchProduct path=/mystruts/searchProductjsp />
</globalforwards>

  上面的代碼中所示的newProductjsp和searchProductjsp目前並不存在(將在以後實現這兩個JSP頁面)現在重新輸入上述的URL會得到如圖所示的效果

  

  圖

  如果想讓indexjsp成為默認的JSP頁面可以在webxml中的<welcomefilelist>節點中加入如下的內容

  

  <welcomefile>indexjsp</welcomefile>

  這時在IE中只要輸入如下的URL就可以訪問indexjsp頁面了

  //localhost/samples/mystruts

  實現添加和查詢產品信息頁面

  在本節中主要實現了用於輸入產品信息(newProductjsp)和查詢產品信息(searchProductjsp)的JSP頁面

  在newProductjsp頁面中有一個form在form中含有三個文本框用於分別輸入產品ID產品名稱和產品價格

  在<samples工程目錄>mystruts目錄中建立一個newProductjsp文件代碼如下

  

  <%@ page pageEncoding=GBK%>
  <%@ taglib uri=html prefix=html%>
  <html>
      <head>
          <title>錄入產品信息</title>
      </head>
      <body>
          <% 向saveProduct動作提交產品信息 %>
          <html:form action=saveProduct
              <table width=%>
                  <tr>
                      <td align=center>
                          產品編號
                          <html:text property=productID maxlength= />
                          <p>
                              產品名稱
                              <html:text property=productName />
                          <p>
  
                              產品價格
                              <html:text property=price />
                      </td>
                  </tr>
                  <tr>
                      <td align=center>
                          <br>
                          <html:submit value= 保存  />
                      </td>
                  </tr>
              </table>
          </html:form>
      </body>
  </html>

  在searchProductjsp頁面中有一個form為了方便起見在form中只提供了一個文本框用於對產品名稱進行模糊查詢在<samples工程目錄> mystruts目錄中建立一個searchProductjsp文件代碼如下

  

  <%@ page pageEncoding=GBK%>
  <%@ taglib uri=html prefix=html%>
  <html>
      <head>
          <title>查詢產品信息</title>
      </head>
      <body>
          <%  向searchProduct動作提交查詢請求 %>
          <html:form action=searchProduct>
              <table width=%>
                  <tr>
                      <td align=center>
                          產品名稱
                          <html:text property=productName />
                      </td>
                  </tr>
                  <tr>
                      <td align=center>
                          <br>
                          <html:submit value= 查詢  />
                      </td>
                  </tr>
              </table>
          </html:form>
      </body>
  </html>

  現在啟動Tomcat並使用如下兩個URL來訪問newProductjsp和searchProductjsp

  

  

  在IE中輸入上面的兩個URL後並不能顯示出相應的界面而會拋出JspException異常表明未找到saveProduct和searchProduct動作從這一點可以看出如果在JSP中使用Struts Action這些Action必須事先在strutsconfigxml文件中定義否則JSP程序就無法正常訪問在這兩個頁面所使用的動作(saveProduct和searchProduct)將會在下面的部分介紹

  通過模型類操作數據庫

  在這一節我們來編寫用於操作數據庫的模型類由於本例子是Web程序因此建議在連接數據庫時使用數據庫連接池在<Tomcat安裝目錄>confCatalinalocalhost目錄中打開samplesxml文件(如果沒有該文件則建立一個samplesxml文件)在<Context>節點中加入如下的內容

  配置連接池(用於連接數據庫struts)

  

  <Resource name=jdbc/struts auth=Container
                type=javaxsqlDataSource
                driverClassName=commysqljdbcDriver
                url=jdbc:mysql://localhost:/struts?characterEncoding=GBK
                username=root
                password=              
                maxActive=
                maxIdle=
                maxWait=/>

  本例中提供了兩個可以操作數據庫的模型類Product和SearchProduct其中Product用於驗證由客戶端提交的產品信息並向t_products表中寫入這些信息而SearchProduct類用於對t_products表的product_name字段進行模糊查詢並返回查詢到的產品信息(包括產品ID產品名稱和產品價格)

  由於Product和SearchProduct都需要使用數據庫連接池來連接數據庫因此可以將連接數據庫的工作提出來作為一個父類(Struts類)提供代碼如下

  

  package util;
import javasqlConnection;
public class Struts
{
    protected javaxnamingContext ctx = new javaxnamingInitialContext();
    protected javaxsqlDataSource ds;
    protected Connection conn;
    public Struts() throws Exception
    {
        ds = (javaxsqlDataSource) ctxlookup(java:/comp/env/jdbc/struts);
        conn = dsgetConnection();  // 從數據庫連接池獲得一個Connection
    }
}

  在<samples工程目錄>src目錄中建立一個Productjava文件代碼所示

  

  package mystrutsmodel;
  
  import javasql*;
  import mystrutsactionform*;
  
  public class Product extends utilStruts
  {
      private ProductForm form;
  
      public Product(ProductForm form) throws Exception
      {
          super();
          thisform = form;
          validate();
      }
      // 驗證客戶端提交的數據
      public void validate() throws Exception
      {
          if (formgetProductID()trim()equals())
              throw new Exception(產品ID不能為空!);
          if(formgetProductID()length() > )
              throw new Exception(產品ID最長為位!);
          if (formgetProductName()trim()equals())
              throw new Exception(產品名稱不能為空);
          if (pare(formgetPrice() ) <= )
              throw new Exception(產品價格必須大於);
      }
      // 將客戶端提交的產品信息保存到t_products中
      public void save() throws Exception
      {
          try
          {
              String productID = formgetProductID();
              String productName = formgetProductName();
              float price = formgetPrice();
              String sql = INSERT INTO t_products VALUES( + productID + 
                      +  + productName +  + StringvalueOf(price) + );
              PreparedStatement pstmt = connprepareStatement(sql);
              pstmtexecuteUpdate();   // 執行INSERT語句
              pstmtclose();
              connclose();
          }
          catch (Exception e)
          {
              throw new Exception(egetMessage());
          }
      }
  }

  在Product類中使用了一個ProductForm類這個類是一個ActionForm類它的功能是保存客戶端提交的數據關於這個類將在下面詳細介紹Product類通過構造方法的form參數將客戶端提交的數據傳入Product類的對象實例中並在構造方法中驗證這些數據如果發現數據不合法就會拋出一個異常當客戶端提交的數據合法後成功建立了一個Product類的對象實例然後可以通過簡單地調用save方法將數據保存到t_products表中

  與Product類似在<samples工程目錄>src目錄中建立一個SearchProductjava文件代碼如下

  

  package mystrutsmodel;
  
  import javasql*;
  import javautil*;
  import mystrutsactionform*;
  
  public class SearchProduct extends utilStruts
  {
      private ProductForm form;
  
      public SearchProduct(ProductForm form) throws Exception
      {
          super();
          thisform = form;
      }    
      // 查詢產品信息並通過List返回查詢結果
      public List<String[]> search() throws Exception
      {
          List<String[]> result = new LinkedList<String[]>();
          String sql = SELECT * FROM t_products WHERE product_name like % 
+ formgetProductName() + %;
          PreparedStatement pstmt =  connprepareStatement(sql);
          ResultSet rs = pstmtexecuteQuery();  // 開始執行SELECT語句
          while(rsnext())
          {
              String[] row = new String[];
              row[] = rsgetString();
              row[] = rsgetString();
              row[] = rsgetString();
              resultadd(row);
          }
          rsclose();
          connclose();
          return result;
      }
  }

  在SearchProduct類也使用了ProductForm類但在SearchProduct中並不會驗證ProductForm對象實例中的數據而只是將ProductForm對象作為傳遞查詢請求信息(實際上只需要產品名稱)的工具而已

  實現控制器

  在這一節要實現的控制器是基於Struts的Web程序的核心部分之一控制器實質上也是普通的Java類但這個Java類一般要從orgapachestrutsactionAction類繼承控制器的主要功能是接受並處理從JSP頁面提交的數據通過模型(Model)和數據庫交互以及forward到相應的頁面(可以是任何頁面如htmlJSP和Servlet等)在實現控制器之前需要先實現一個ActionForm類 這個類的作用是保存JSP頁面提交的數據在<samples工程目錄>src目錄中建立一個ProductFormjava文件代碼如下

  

  package mystrutsactionform;
  
  import orgapachestrutsaction*;
  
  public class ProductForm extends ActionForm
  {
      private String productID;  // 產品ID
      private String productName; // 產品名稱
      private float price;  // 產品價格
      public String getProductID()
      {
          return productID;
      }
      public void setProductID(String productID)
      {
          thisproductID = productID;
      }
      public String getProductName()
      {
          return productName;
      }
      public void setProductName(String productName)
      {
          thisproductName = productName;
      }
      public float getPrice()
      {
          return price;
      }
      public void setPrice(float price)
      {
          thisprice = price;
      }
  }

  從上面的代碼可以看出ActionForm類一般從orgapachestrutsactionActionForm類繼承而且在類中需要按著需要保存的數據表字段添加屬性如產品ID的屬性是productName在MyEclipse中可以只定義三個private變量然後使用MyEclipse的「Source」 > 「Generate Getters and Setters……」功能自動產生getter和setter方法但在給這些屬性取名時要注意private變量的名子和數據表的字段名沒有直接的關系但必須和JSP頁面中的<html>標簽的property屬性值一致如<htmltext property=productName />表示輸入產品名稱的文本框其中property屬性的值就是ProductForm類中的productName變量如果不一致將會拋出異常其他和ProductForm類的屬性對應的<html>標簽可以查看上面的代碼

  光有ActionForm類還不夠還需要在strutsconfigxml中的<strutsconfig>節點中添加如下的內容

  

  <formbeans>
     <formbean name=saveProductForm type= mystrutsactionformProductForm />
     <formbean name=searchProductForm type=mystrutsactionformProductForm />
</formbeans>

  上面的代碼所配置的兩個ActionForm實際上指的是同一個ProductForm類但這個ProductForm類在後面要講的兩個動作裡都要使用為了更容易理解為這個ProductForm起了兩個不同的別名(saveProductForm和searchProductForm)

  下面來實現saveProduct動作的代碼Struts Action類必須一般從orgapachestrutsactionAction類繼承一般在Struts Action類需要覆蓋Action類的execute方法這個方法有每次客戶端訪問Struts Action時調用我們可以在方法中處理客戶端提交的數據訪問數據庫等工作這個方法返回一個ActionForward類型的值表明在執行完execute後要forward到的頁面描述saveProduct動作的類叫SaveProductAction代碼如下

  

  package mystrutsaction;
  
  import javaxservlethttp*;
  import orgapachestrutsaction*;
  import mystrutsactionform*;
  import mystrutsmodel*;
  
  public class SaveProductAction extends Action
  {
      // 在客戶端訪問saveProduct動作時執行該方法
      public ActionForward execute(ActionMapping mapping ActionForm form
              HttpServletRequest request HttpServletResponse response)
      {
          ProductForm saveProductForm = (ProductForm) form;
          try
          {
              Product product = new Product(saveProductForm);
              productsave();  // 保存產品信息
              requestsetAttribute(info 保存成功!);   
          }
          catch (Exception e)
          {
              requestsetAttribute(info egetMessage());
          }
          return mappingfindForward(save);
      }
  }

  在SaveProductAction類中使用了模型類Product驗證並保存產品信息並將操作結果信息保存在request的屬性中key為info在execute的最後使用了ActionMapping類的findForward方法在strutsconfigxml中尋找一個叫save的forward這個forward是一個JSP頁用於顯示是否將產品信息保存成功的信息為了可以在strutsconfigxml中查找這個forward需要在strutsconfigxml的<actionmappings>節點中加入如下的內容

  

  <action name=saveProductForm path=/saveProductscope=request type= mystrutsactionSaveProductAction>
    <forward name=save path=/mystruts/savejsp />
</action>

  從上面的代碼可以看出那個用於顯示保存狀態信息的JSP頁面叫savejsp在<samples工程目錄>mystruts目錄中建立一個savejsp文件代碼如下

  

  <%@ page pageEncoding=GBK%>
  ${}

  在IE中輸入如下的URL

  

  在文本框中輸入相應的信息後保存按鈕如果輸入的數據是合法的就會將數據保存在t_products中否則會顯示出錯的原因    searchProduct動作的實現和saveProduct差不多也會為三步實現動作類(SearchProductAction)在strutsconfigxml中添加配置信息和實現用於顯示查詢結果的JSP文件下面的代碼分別顯示了這三步所要編寫的代碼

  SearchProductActionjava

  

  package mystrutsaction;
  
  import javaxservlethttp*;
  import orgapachestrutsaction*;
  import mystrutsactionform*;
  import mystrutsmodel*;
  import javautil*;
  
  public class SearchProductAction extends Action
  {
  
      public ActionForward execute(ActionMapping mapping ActionForm form
              HttpServletRequest request HttpServletResponse response)
      {
          ProductForm searchProductForm = (ProductForm) form;
          try
          {
              SearchProduct searchProduct = new SearchProduct(searchProductForm);
              List<String[]> result = searchProductsearch();  // 查詢產品信息
              if (resultsize() > )  // 有符合條件的產品信息
              {
                  requestsetAttribute(result result);
                  requestsetAttribute(info 記錄數 + StringvalueOf(resultsize()));
              }
              else  // 沒有查到任何產品信息
                  requestsetAttribute(info 沒有符合要求的記錄!);
          }
          catch (Exception e)
          {
              requestsetAttribute(info egetMessage());
          }
          return mappingfindForward(search);
      }
  }

  在strutsconfigxml中配置searchProduct動作

  

  <action name=searchProductForm path=/searchProduct scope=request type=mystrutsactionSearchProductAction>
    <forward name=search path=/mystruts/searchjsp />
</action>

  searchjsp

  

  <%@ page pageEncoding=GBK%>
  <%@ taglib uri=logic prefix=logic%>
  <%@ taglib uri= prefix=c%>
  <html>
      <body>
<% 從request的result中取出查詢結果 %>
          <c:set var=result value=${requestScoperesult} />
          <table width=%>
              <tr align=center>
                  <td>
                      ${}
                  </td>
              </tr>
              <tr align=center>
                  <td>
                      <logic:present name=result>
                          <table border=>
                              <tr align=center>
                                  <td> 產品ID </td>
                                  <td> 產品名稱 </td>
                                  <td> 價格 </td>
                              </tr>
                              <logic:iterate id=row name=result>
                                  <tr> <td> ${row[]} </td>
                                      <td> ${row[]} </td>
                                      <td> ${row[]} </td>
                                  </tr>
                              </logic:iterate>
                          </table>
                      </logic:present>
                  </td>
              </tr>
          </table>
      </body>
  </html>

  在IE中輸入如下的URL

  //localhost/samples/%mystruts/searchProductjsp

  在產品名稱文本框中輸入產品名稱的一部分程序就會查詢出所有包含輸入的產品名稱的產品信息並將結果顯示出來

  解決ActionForm的亂碼問題

  到現在為止程序的功能部分已經全部實現完了但還存在一個問題當我們在產品名稱中輸入中文時雖然將客戶端提交的數據成功保存到數據庫中但是在t_products表中的product_name字段顯示的都是亂碼產生這個問題的原因只有一個就是客戶端提交的數據的編碼格式和數據庫的編碼格式不一致造成的當然解決這個問題的方法有很多但筆者認為最容易的就是使用過濾器所謂過濾器就是在客戶端提交數據後在交由服務端處理之前所執行的一段服務端代碼(一般為Java代碼)一個過濾器是一個實現javaxservletFilter接口的類在本例中要使用的過濾器類叫EncodingFilter實現代碼如下

  EncodingFilterjava

  

  package filter;
  import javaioIOException;
  import javaxservlet*;
  public class EncodingFilter implements Filter
  {
      public void destroy() {  }
      public void doFilter(ServletRequest request ServletResponse response
              FilterChain chain) throws IOException ServletException
      {
          requestsetCharacterEncoding(GBK);  // 將客戶端提交的數據設為GBK編碼格式
          // 繼續處理客戶端提交的數據如果不寫這條語句Servlet引擎將不會處理所過濾的頁面
          chaindoFilter(request response);      
      }
      public void init(FilterConfig filterConfig) throws ServletException {   }  
  }

  Filter接口的doFilter方法是過濾器的核心方法其中FilterChain類的doFilter方法允許繼續處理客戶端提交的數據我們還可以使用這個方法來臨時關閉Web站點的某個或全部的頁面(根據過濾器的設置而定)由於本書的數據庫使用的是GBK編碼格式因此需要使用ServletRequest的setCharacterEncoding方法將客戶端提交的數據也設為GBK編碼格式

  除了實現過濾器類我們還需要在webxml中的<webapp>節點加入如下的配置信息才能使過濾器生效

  在webxml中配置過濾器

  

  <filter>
    <filtername>EncodingFilter</filtername>
    <filterclass>
        filterEncodingFilter
    </filterclass>
</filter>
<filtermapping>
    <filtername>EncodingFilter</filtername>
    <urlpattern>/*</urlpattern>
</filtermapping>

  在重新啟動Tomcat後重新輸入一條帶中文的產品信息看看是否可以將中文保存在數據庫中?


From:http://tw.wingwit.com/Article/program/Java/ky/201311/28470.html
  • 上一篇文章:

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.