跟着視頻做的SSH項目總結


一直沒做過SSH(Struts2+Spring+Hibernate)的實際項目,只是三個框架學的還熟練,但整合起來使用就不知道了。所以前段時間在網上找了一套SSH實際項目的視頻來學習(確切的說是買的...),一直沒時間來總結,得到的經驗主要是SSH的整合及配置,更多的則是SSH之外的一些經驗,比如代碼的書寫及規范上就給了我很大的啟發,很多經驗只有從實際項目中才能得到。總體來說,SSH整合起來使用不是很難,配置文件也基本是固定的模式。

先看下項目截圖

1.首頁

2.商品詳細

3.購物車

4.訂單管理

5.用戶注冊

6.后台管理系統首頁【后台系統使用的是easyui】

7.管理用戶

8.項目工程結構

 

*******************************************************************************************************************************************************************

*******************************************************************************************************************************************************************

 

經驗總結

一.首先說說這個項目

1.之前做過的項目大多只有后台系統,沒有前端,不過學了這個系統之后,其實前端也不難,前端頁面主要由專門的人員做好后,你只需要把數據顯示到上面就行了,然后你可能還需要寫一些js的代碼。

然后說說前端頁面,前端頁面把一些公共的部分提取出來,其它頁面只需引入即可。公共部分如頂部,底部:

通用頁面放到一個文件夾里:

在頁面引入即可:

2.系統不變的數據在系統啟動時就緩存到application中。

比如首頁商品分類,導航欄內容等,這些數據基本是不會變的,可以在系統啟動時就加載出來。就需要寫一個監聽器類,在服務啟動時,將數據庫中的數據加載進內存,並將其賦值給一個屬性名,其它的 Servlet 就可以通過 getAttribute 進行屬性值的訪問

3.導航,如下圖。以前我寫類似的導航代碼時一般是用js判斷各個層級,然后拼湊出一個導航來。然而作者是在服務端生成導航代碼,他將生成導航的方法寫到一個工具類中,每次訪問哪個頁面的時候,直接生成這段導航代碼,然后返回到前端。這種做法不僅提高了開發效率,也提高了代碼的重用性,好!

導航工具類:

 1 package com.lizhou.tools;  2 
 3 import java.util.List;  4 
 5 /**
 6  * 導航工具類  7  * @author Administrator  8  *  9  */
10 public class NavTool { 11 
12     /**
13  * 生成一級導航 14  * @param subName 15  * @return
16      */
17     public static String genNavCode(String subName){ 18         StringBuffer navCode=new StringBuffer(); 19         navCode.append("您現在的位置:"); 20         navCode.append("<a href='index.jsp'>首頁</a>&nbsp;"); 21         navCode.append("&gt; "); 22  navCode.append(subName); 23         return navCode.toString(); 24  } 25     
26     /**
27  * 生成多級導航 28  * @param hrefList 導航標簽鏈接的集合 29  * @return
30      */
31     public static String genNavCode(List<String> hrefList){ 32         StringBuffer navCode=new StringBuffer(); 33         navCode.append("您現在的位置:"); 34         navCode.append("<a href='index.jsp'>首頁</a>&nbsp;"); 35         navCode.append("&gt; "); 36         for(String href : hrefList){ 37  navCode.append(href); 38             navCode.append("&gt; "); 39  } 40         String nav = navCode.substring(0, navCode.lastIndexOf("&gt; ")); 41         return nav; 42  } 43 }

 

二、說一說使用SSH開發的感受

之前做一些完整的項目時一直使用的是JDBC+Servlet+Jsp,然后還有就是DBUtils等一些包來簡化一些工作量。我會將mysql的一些操作封裝成一個工具類,會寫一個BaseDao來操作數據庫,BaseDao能解決簡單的增刪改查功能,但要解決一些比較復雜的,比如涉及到級聯的時候,可能就不適用了,需要重新寫個類來實現相關的功能。自己設計好bean類后,還需要去設計表結構,而如果類有改動,則需要重新設計表,復雜的時候可能設計到幾張表,如果有外鍵關系的話更惱火......

使用SSH的話,首先來說你需要設計好類結構,然后加上注解或者聲明式配置好,hibernate會自動生成表結構,而如果類有改動,表結構也會自動更改,這算是大大節省了開發時間了。然后,hibernate只需要一個BaseDao就基本能解決所有的數據操作,因為hibernate支持泛型。還有傳數據和參數的問題,我們只需在action里寫一個字段即可,省了很多代碼。

總的來說,使用SSH框架,我們只需要關心業務邏輯的實現即可,其它的很多問題不必擔心。不過我在想我是不是離底層越來越遠了......我個人還是挺喜歡寫原生代碼的...不喜歡框架。

 

三、代碼上得到的一些經驗

1.一類操作寫到一個方法里:比如,根據產品名稱查詢,根據產品類別查詢,模糊查詢,查詢所有等操作本屬於一個操作:查詢產品。在以前,我可能會分別寫幾個方法來查詢,getByProductName(String name), getByProductType(String type), getProductList(),然而這些方法只是sql語句不一樣而已,代碼非常冗余。這些參數本就是產品這個類的字段,所以完全可以將這些查詢參數封裝到一個Product對象里,在一個方法里每個條件一個判斷語句,然后拼湊Sql語句即可:getProductList(User user).

比如下面這個service里查詢產品的操作:使用一個集合來裝參數,根據條件拼SQL語句。這樣減少了代碼,邏輯性也更強了,維護也方便。

 1 public List<Product> getProductList(Product product, PageBean pageBean) {  2     StringBuffer sbHQL = new StringBuffer("FROM Product ");  3     //存放參數
 4     List<Object> param = new LinkedList<Object>();  5     if(product != null){  6         //獲取特價商品
 7         if(product.getSpecialPrice() == 1){  8             sbHQL.append("AND specialPrice=1 ORDER BY specialPriceTime DESC ");  9  } 10         //獲取熱賣商品
11         if(product.getHot() == 1){ 12             sbHQL.append("AND hot=1  ORDER BY hotTime DESC "); 13  } 14         //獲取大類下的商品
15         if(product.getBigType() != null){ 16             //添加參數
17  param.add(product.getBigType().getId()); 18             sbHQL.append("AND bigType.id=? "); 19  } 20         //獲取大類下的某個小類商品
21         if(product.getSmallType() != null){ 22             //添加參數
23  param.add(product.getSmallType().getId()); 24             sbHQL.append("AND smallType.id=? "); 25  } 26         //模糊搜索
27         if(!StringTool.isEmpty(product.getName())){ 28             //添加參數
29             param.add("%"+product.getName()+"%"); 30             sbHQL.append("AND name like ?"); 31  } 32  } 33     String hql = sbHQL.toString().replaceFirst("AND", "WHERE"); 34     //是否分頁
35     if(pageBean != null){ 36         return baseDao.find(hql, param, pageBean); 37     } else{ 38         return baseDao.find(hql, param); 39  } 40 }

 

2.關於json的一個技巧:可以寫一個處理器來轉換JSON中的一些對象。比如產品有一個日期屬性,類型為java.util.Date。如果不重新處理這個日期,

首先看一下應用場景:

 1 /**
 2  * 查詢產品集合  3  * @return
 4  * @throws Exception  5  */
 6 public String list() throws Exception{  7     //分頁對象
 8     PageBean pageBean = new PageBean(page, Integer.parseInt(rows));  9     //根據查詢條件和分頁對象查詢產品集合
10     List<Product> productList = productService.getProductList(product, pageBean); 11     //產品總記錄數
12     long total = productService.getProductCount(searchProduct); 13     
14     //JSON配置
15     JsonConfig config = new JsonConfig(); 16     //過濾掉的屬性
17     config.setExcludes(new String[]{"orderProductList"}); 18     JSONArray rows = JSONArray.fromObject(productList, config); 19     JSONObject result = new JSONObject(); 20     result.put("rows", rows); 21     result.put("total", total); 22     //返回json字符串
23  ResponseTool.write(ServletActionContext.getResponse(), result); 24  System.out.println(result.toString()); 25     return null; 26 }

這里沒有對產品的日期做處理,輸出如下結果:"hotTime":{"date":1,"day":3,"hours":0,"minutes":0,"month":0,"nanos":0,"seconds":0,"time":1388505600000,"timezoneOffset":-480,"year":114}

可以看到把Date類型直接按對象來解析了,這不是我們想要的。在以前我的處理辦法是在Product里再添加一個String類型的日期字段,這種方法雖然可行,但其實不符合程序設計,用起來着實不爽O(∩_∩)O哈哈~。

然后這次學到了,可以寫一個處理器類,該類需要實現JSON的一個接口:net.sf.json.processors.JsonValueProcessor

實現類如下:

 1 package com.lizhou.tools;  2 
 3 import java.text.SimpleDateFormat;  4 
 5 import net.sf.json.JsonConfig;  6 import net.sf.json.processors.JsonValueProcessor;  7 
 8 /**
 9  * json-lib 日期處理類 10  * @author bojiangzhou 11  * 12  */
13 public class DateJsonValueProcessor implements JsonValueProcessor{ 14 
15     /**
16  * 日期格式 17      */
18     private String format; 19     
20     public DateJsonValueProcessor(String format){ 21         this.format = format; 22  } 23     
24     public Object processArrayValue(Object value, JsonConfig jsonConfig) { 25         // TODO Auto-generated method stub
26         return null; 27  } 28     
29     public Object processObjectValue(String key, Object value, JsonConfig jsonConfig) { 30         if(value == null) 31  { 32             return ""; 33  } 34         if(value instanceof java.sql.Timestamp) 35  { 36             String str = new SimpleDateFormat(format).format((java.sql.Timestamp)value); 37             return str; 38  } 39         if (value instanceof java.util.Date) 40  { 41             String str = new SimpleDateFormat(format).format((java.util.Date) value); 42             return str; 43  } 44           
45         return value.toString(); 46  } 47 
48 }

然后只需注冊該處理器即可:config.registerJsonValueProcessor(java.util.Date.class, new DateJsonValueProcessor("yyyy-MM-dd"));

 1 /**
 2  * 查詢產品集合  3  * @return
 4  * @throws Exception  5  */
 6 public String list() throws Exception{  7     //分頁對象
 8     PageBean pageBean = new PageBean(page, Integer.parseInt(rows));  9     //根據查詢條件和分頁對象查詢產品集合
10     List<Product> productList = productService.getProductList(product, pageBean); 11     //產品總記錄數
12     long total = productService.getProductCount(searchProduct); 13     
14     //JSON配置
15     JsonConfig config = new JsonConfig(); 16     //過濾掉的屬性
17     config.setExcludes(new String[]{"orderProductList"}); 18 //注冊日期處理器 19 config.registerJsonValueProcessor(java.util.Date.class, new DateJsonValueProcessor("yyyy-MM-dd")); 20     JSONArray rows = JSONArray.fromObject(productList, config); 21     JSONObject result = new JSONObject(); 22     result.put("rows", rows); 23     result.put("total", total); 24     //返回json字符串
25  ResponseTool.write(ServletActionContext.getResponse(), result); 26  System.out.println(result.toString()); 27     return null; 28 }

輸出結果:"hotTime":"2014-01-01"

同樣的,也可以實現其它級聯對象處理器,比如產品里有個BigType(大類別,有id,name,remark,productList),但我在顯示產品列表時只需要大類別的名稱和id,這時就可以寫一個對象處理器。

如下:

 1 package com.lizhou.tools;  2 
 3 import java.beans.PropertyDescriptor;  4 import java.lang.reflect.Method;  5 
 6 import net.sf.json.JSONObject;  7 import net.sf.json.JsonConfig;  8 import net.sf.json.processors.JsonValueProcessor;  9 
10 /**
11  * 解決對象級聯問題 12  * @author Administrator 13  * 14  */
15 public class ObjectJsonValueProcessor implements JsonValueProcessor{ 16 
17     /**
18  * 保留的字段 19      */
20     private String[] properties; 21     
22     /**
23  * 處理類型 24      */
25     private Class<?> clazz; 26     
27     /**
28  * 構造方法 29  * @param properties 30  * @param clazz 31      */
32     public ObjectJsonValueProcessor(String[] properties,Class<?> clazz){ 33         this.properties = properties; 34         this.clazz =clazz; 35  } 36     
37     public Object processArrayValue(Object arg0, JsonConfig arg1) { 38         // TODO Auto-generated method stub
39         return null; 40  } 41 
42     public Object processObjectValue(String key, Object value, JsonConfig jsonConfig) { 43         PropertyDescriptor pd = null; 44         Method method = null; 45         StringBuffer json = new StringBuffer("{"); 46         try{ 47             for(int i=0;i<properties.length;i++){ 48                 pd = new PropertyDescriptor(properties[i], clazz); 49                 method = pd.getReadMethod(); 50                 String v = String.valueOf(method.invoke(value)); 51                 json.append("'"+properties[i]+"':'"+v+"'"); 52                 json.append(i != properties.length-1?",":""); 53  } 54             json.append("}"); 55         }catch (Exception e) { 56  e.printStackTrace(); 57  } 58         return JSONObject.fromObject(json.toString()); 59  } 60 
61 }

同樣,注冊該處理器即可:

1 config.registerJsonValueProcessor(ProductBigType.class, new ObjectJsonValueProcessor(new String[]{"name", "id"}, ProductBigType.class)); 2 config.registerJsonValueProcessor(ProductSmallType.class, new ObjectJsonValueProcessor(new String[]{"name", "id"}, ProductSmallType.class));

 

*******************************************************************************************************************************************************************

*******************************************************************************************************************************************************************

 

總的來說就是這些,還有些比較細節的忘了,最大的收獲就是經驗還是得從實際項目中來....

然后還遇到一個非常糾結的問題:那就是session的過期時間。場景是這樣的,以前做項目的時候我在session中存的數據幾乎是在10秒內就消失了,比如我存登錄用戶的信息(User對象)到session中,如果一直刷新頁面不會消失,但停留幾秒鍾,再刷新一次,數據就消失了,但是session並沒有銷毀。以前百度過很多資料,包括修改session過期時間,都沒用,也有說是tomcat的配置問題,我就懶得改了。

直到做這個項目,我發現存在session中的登錄用戶信息、包括購物車里的數據同樣是如此,過不了多久就消失了;但是存的其它的一些信息,比如字符串形式的數據,一直沒有消失,在不關閉瀏覽器的情況下,那些數據一直都在;我就糾結了,難道消失的只是那些對象型數據?后面再找時間測試,如果你們知道問題所在,請告訴我,O(∩_∩)O謝謝!!!

 

 

 -------------------------------------------------------------------------------------------------------------

 附上源碼:僅供學習,后台大部分沒有做完!

文件包含:

 

地址:SSH商城系統(ebuy)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM