≡(▔﹏▔)≡今天調了很久。。。而且都是一些很碎碎的錯誤。。。所以調程式真心是個痛苦的活>﹏<),經常調半天都調不出來,比較趕時間~~所以先大概寫下來免得忘了今天的痛苦經曆!!!
繼上一次的使用者登陸後加入代碼:
/anli/adminWelcome.jsp(只有管理員有權添加商品)
<a href=\'#\'" /add_products_admin.jsp">添加商品</a>
好了~開始添加商品的地方了~~。。。一堆容易出現的小錯誤我都寫在下面好鳥~
<% Usr u = (Usr)session.getAttribute("usr"); if(u!=null && u.getSuperuser().equals("3")){ %> <!-- 上傳檔案需要encType的屬性為那個,是上傳位元據。。。但這樣不能request.getParameter(),可以考慮smartupload來getRequest --> <form name="form" method="post" action="saveOneProductManagerAction.action" encType=multipart/form-data> 歡迎,<%=u.getUsername()%> <a href="<%=request.getContextPath() %>/clearSession.action">登出</a> <table width="60%"> <tr><td>產品id:<input type="text" name="productId"/></td></tr> <tr><td>產品name:<input type="text" name="productname"/></td></tr> <tr><td>圖片:<input type="file" name="upload" /></td></tr> <tr><td><input type="submit" value="添加"/></td></tr> </table> </form> <% }else{ %> <center><h3>對不起,你沒有權利查看!</h3></center> <% } %>
上面主要代碼和注意部分:1.只有user是admin才可以添加商品u.getSuperuser().equals("3");2.提示歡迎使用者資訊和登出資訊額。。登出的再補上,忘了寫。。。);3.提交表單到saveOneProductManagerAction.action;4.設定encType這個屬性是保證可以上傳檔案用的;5.注意表單的名字productId,productname和upload,和後面的代碼是有關係的像我基礎不太紮實經常都忘了);6.我眼花一直沒看出來的<%=u.getUsername()%>,調了很久,那時候沒有寫"=",覺得奇怪明明後台調試有資料,怎麼就顯示不出來;7.request.getContextPath()
Product.java
private String productId;private String productname;private String structure;//imagepath路徑和名字
ProductDAO.java
public boolean findProductById(String id){//保證傳入的檔案沒有和table重複id的判斷,//比較簡單,不寫了。。。//不過一直漏了這句ps.setString(1, id);//調很久一直都說沒有參數。。。我還以為id沒有傳進去呢。。。}
public void saveProduct(Product product){ String sql = "insert into product(productId,productname,structure) values(?,?,?)"; try{ conn = DBConn.getConnection(); ps = conn.prepareStatement(sql); ps.setString(1, product.getProductId()); ps.setString(2, product.getProductname()); ps.setString(3, product.getStructure()); ps.executeUpdate(); System.out.println("成功添加!內容如下:"); System.out.println("id: "+product.getProductId()+"; name: "+ product.getProductname()+"; imagpath: "+product.getStructure()); }catch(SQLException e){ e.printStackTrace(); }finally{ DBConn.dbClose(conn, ps, rs); } }
上面通過executeUpdate()函數執行
ProductManagerAction.java
和Product.java一樣有這3個欄位
private String productId;private String productname;private String structure;//imagepath
另外,還應該有和上傳檔案相關的屬性:
//上傳檔案屬性欄位,用FIle類型封裝private File upload;//struts2要求定義檔案欄位+FileName 和+ContentType的兩個欄位來封裝檔案名稱和檔案類型private String uploadFileName;private String uploadContentType;//選擇檔案自己的屋裡路徑private String filepath;//儲存路徑屬性,該屬性的值可以通過設定檔來設定,從而動態注入private String savepath;//處理結果展示欄位tip主要用於提示出錯)private String tip;
添加商品用的代碼下面再解析):
public String saveOne()throws Exception{ ProductDAO dao = new ProductDAO();/* if(this.getProductId()!=null) System.out.println(this.getProductId()); else System.out.println("sdkjlk");*/ if(dao.findProductById(this.getProductId())){ this.setTip(this.getText("productM_tip.id.used"));//商品號被佔用,請求重新添加商品 return INPUT; }else{ if(this.getUpload()!=null){ if(this.getUploadContentType().equals("application/vnd.ms-excel")){ this.setTip(this.getText("productM_tip。upload.file.type")); return INPUT;//此處只允許上傳圖片類型檔案,請返回重新選擇 } //儲存圖片名稱到資料庫欄位structure this.setStructure(this.getUploadFileName()); this.setSavepath("D:\\tmp"); //以伺服器的檔案儲存地址和原檔案的名 建立上傳檔案輸出資料流 FileOutputStream fos = new FileOutputStream(this.getSavepath()+"\\"+this.getUploadFileName()); //以上傳檔案建立一個檔案上傳流 FileInputStream fis = new FileInputStream(this.getUpload()); //將上傳檔案的內容寫入伺服器 byte[] buffer = new byte[1024]; int len = 0 ; while((len = fis.read(buffer))>0){ fos.write(buffer, 0, len); } } System.out.println("—————————結束上傳單個檔案—————————"); Product product = new Product(); product.setProductId(this.getProductId()); product.setProductname(this.getProductname()); product.setStructure(this.getSavepath()+"\\"+this.getStructure()); dao.saveProduct(product); } return "anli_saveOnesuccess"; }
解析:1.用dao和資料庫連接起來解耦);2.findProductById(this.getProductId()))用於檢查這個想要添加為檔案的id是否已經在資料庫存在,this.getProductId()方法和頁面add_products_admin.jsp中的text的name屬性productId有關係,注意的是,我們建立的這個Action裡面的屬性就是為了接收頁面傳送過來的屬性值我是這樣理解的:當form提交表單調到某個action時,這個action就可以通過多個屬性值對應接收頁面中的屬性值,只要get、set方法和name對應起來就可以接收);3.關於upload類型要通過File來封裝,而struts2要求通過檔案名稱和檔案類型來封裝檔案;4.如果符合要求則可以進行上傳檔案的操作,通過FileInputStream讀入upload的資料,將它們寫入到FileOutputStream中;5.上傳完畢這時已經在定義的儲存目錄下看到檔案了)封裝Product,並通過dao來儲存當前的product對象,這時db裡面就存有這個檔案的id、name和path
關於struts.xml的設定:
<!-- 此處調用constant元素定義常量 --> <constant name="struts.devMode" value="true"></constant> <!-- 定義資源檔的位置和類型 --> <constant name="struts.custom.i18n.resources" value="properties/myMessages"></constant> <!-- 設定應用使用的解析碼 --> <constant name="struts.i18n.encoding" value="GBK"></constant> <!-- 設定應用使用的上傳解析器類型 --> <constant name="struts.multipart.parser" value="jakarta"></constant> <!-- 設定臨時隱藏檔 --> <constant name="struts.multipart.saveDir" value="/tmp"></constant> <!-- 指定使用按type的自動裝配策略 --> <constant name="struts.objectFactory.spring.autoWire" value="name"></constant> <package name="struts2" extends="struts-default">
第二部分關於攔截器的設定:
<action name="*ProductManagerAction" class="com.ascent.action.ProductManagerAction" method="{1}"> <!-- 配置fileUpload攔截器 --> <interceptor-ref name="fileUpload"> <!-- 設定上傳檔案類型 --> <param name="allowedTypes">image/bmp,image/png,image/jpg,image/jpeg,image/gif, image/pjpeg,image/x-png,application/vnd.ms-excel</param> <!-- 設定上傳檔案大小 --> <param name="maximumSize">200000</param> </interceptor-ref> <!-- 必須顯示配置引用struts預設的攔截器棧 :defaultStack--> <interceptor-ref name="defaultStack"></interceptor-ref> <!-- 設定上傳路徑 --> <param name="savePath">/upload</param> <!-- 必須設定input邏輯視圖,攔截器預設出錯返回input --> <result name="input">/product/upload_error.jsp</result> <!-- 成功添加後跳轉 --> <result name="anli_saveOnesuccess">/anli/addProductSucc.jsp</result></action>
注意allowedTypes類型有幾個多的。。。是為了瀏覽器的相容,IE瀏覽器似乎對尾碼名的設定不太同如image/pjpeg),Firefox瀏覽器倒是正常的尾碼名。另外我之前沒有設定臨時隱藏檔的時候出錯,實際上是不是真的要設定才可以我也不太清楚,注釋也挺清楚的,應該再回頭看也能看懂吧我= _ =
上傳出錯的提示頁面配合struts2標籤,不過我比較不怎麼會用這個表情,習慣<%%>和c表情多一點):
<font color="red" size="3"><s:fielderror/><s:property value="tip"/></font> <a href=\'#\'" /a>