跟著視頻做的SSH項目總結

来源:http://www.cnblogs.com/chiangchou/archive/2016/02/27/ssh-ebuy.html
-Advertisement-
Play Games

一直沒做過SSH(Struts2+Spring+Hibernate)的實際項目,只是三個框架學的還熟練,但整合起來使用就不知道了。所以前段時間在網上找了一套SSH實際項目的視頻來學習(確切的說是買的...),一直沒時間來總結,得到的經驗主要是SSH的整合及配置,更多的則是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謝謝!!!

 

 

 

 

 

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 有文檔,但是,寫文檔的人明白,看文檔的人很有難度。 沒有SDK,要自已寫。 然後,錢的流入流出都必須經過虛擬錢包,提現還要綁取現卡,這個我也能理解,不能理解的是,訂單退款,為什麼要退到虛擬錢包,這個時候要程式來幫用戶綁取現卡,可是這不是用戶主動操作呀。要有密碼呀。可是我們沒有存用戶的密碼呀。 就接了
  • 第一章什麼是xml 電腦里的數據文件分為倆大類,二進位文件和文本文件。 二進位文件是一個比特流(1或0系列),只有創建二進位的應用程式才會理解這個比特流的實際含義。 文本文件也是比特流,文本文件里的比特流是以一種標準格式組織起來的,因此他們總是組成一個個數,每個數再映射為字元。 標記語言的簡史 探
  • 本文分別對Cookie與Session做一個介紹和總結,並分別對兩個知識點進行對比分析,讓大家對Cookie和Session有一個更深入的瞭解,並對自己的開發工作中靈活運用帶來啟示。 cookie機制 Cookies是伺服器在本地機器上存儲的小段文本並隨每一個請求發送至同一個伺服器。IETF RFC
  • 關於這份指南 之前有不少學弟學妹問我如何學習編程,根據DRY法則(Don't Repeat Yourself),還是把自己學習過程中的一些經驗整理成一篇博客吧。由於本人目前也處在學習的階段,文章中列出來的內容也並未全部學習過,所以文章的客觀性可能存在一些問題,還望讀者自行判斷。 這份指南會不定期更新
  • 多少年來,許多的編程語言和工具都包含對正則表達式的支持,.NET基礎類庫中包含有一個名字空間和一系列可以充分發揮規則表達式威力的類,而且它們也都與未來的Perl 5中的規則表達式相容。 此外,regexp類還能夠完成一些其他的功能,例如從右至左的結合模式和表達式的編輯等。 在這篇文章中,我將簡要地介
  • powershell的return使用方法研究,案例詳解。
  • 一.Golang安裝 1.下載golang安裝包http://golangtc.com/download,我這裡下載的是go1.6rc2.linux-amd64.tar.gz。 2.解壓到安裝目錄,我這裡是/usr/local 1 sudo tar -zxf go1.6rc2.linux-amd64
  • c 參照編譯器底層實現一個 json引擎. 這是第一篇 主要講解解析部分. 可能 寫的不流利,主要看代碼吧. 之前寫了一個,後面看了cJSON的實現,簡單 合併重構了一下. 歡迎嘗試吐槽
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...