日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

JavaWeb入门_模仿天猫整站Tmall_SSH实践项目

發(fā)布時間:2025/5/22 java 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JavaWeb入门_模仿天猫整站Tmall_SSH实践项目 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Tmall_SSH

技術(shù)棧 Struts2 + Hibernate + Spring + Jsp + Tomcat , 是 Java Web 入門非常好的練手項目

效果展示:

模仿天貓前臺
模仿天貓后臺

項目簡介

關(guān)聯(lián)項目
github - 天貓 JavaEE 項目
github - 天貓 SSH 項目
github - 天貓 SSM 項目

之前使用 JavaEE 整套技術(shù)來作為解決方案,實現(xiàn)模仿天貓網(wǎng)站的各種業(yè)務(wù)場景,現(xiàn)在開始使用框架技術(shù),畢竟工作中還是要用框架。
本項目技術(shù)相對老舊,現(xiàn)在很少用 Struts2 了,但如果接手老項目的話還是要懂的,學(xué)習(xí)過程我們也可以認識到它們當時優(yōu)秀的設(shè)計理念,
當時解決了哪些痛點,后面又是因為什么被新技術(shù)替代,這樣才能加深對 Java Web 整個平臺的理解,不虧。

項目用到的技術(shù)如下:
Java:Java SE基礎(chǔ)
前端:HTML,CSS, JavaScript,AJAX, JQuery, Bootstrap
J2EE:Tomcat, Servlet, JSP, Filter
框架: Hibernate,Struts,Spring,SSH整合
數(shù)據(jù)庫:MySQL

表結(jié)構(gòu)

建表sql 已經(jīng)放在 Github 項目的 /sql 文件夾下

表名中文含義介紹
Category分類表存放分類信息,如女裝,平板電視,沙發(fā)等
Property屬性表存放屬性信息,如顏色,重量,品牌,廠商,型號等
Product產(chǎn)品表存放產(chǎn)品信息,如LED40EC平板電視機,海爾EC6005熱水器
PropertyValue屬性值表存放屬性值信息,如重量是900g,顏色是粉紅色
ProductImage產(chǎn)品圖片表存放產(chǎn)品圖片信息,如產(chǎn)品頁顯示的5個圖片
Review評論表存放評論信息,如買回來的蠟燭很好用,么么噠
User用戶表存放用戶信息,如斬手狗,千手小粉紅
Order訂單表存放訂單信息,包括郵寄地址,電話號碼等信息
OrderItem訂單項表存放訂單項信息,包括購買產(chǎn)品種類,數(shù)量等

一多
Category-分類Product-產(chǎn)品
Category-分類Property-屬性
Property-屬性PropertyValue-屬性值
Product-產(chǎn)品PropertyValue-屬性值
Product-產(chǎn)品ProductImage-產(chǎn)品圖片
Product-產(chǎn)品Review-評價
User-用戶Order-訂單
Product-產(chǎn)品OrderItem-訂單項
User-用戶OrderItem-訂單項
Order-訂單OrderItem-訂單項
User-用戶User-評價

以上直接看可能暫時無法完全理解,結(jié)合后面具體到項目的業(yè)務(wù)流程就明白了。


開發(fā)流程

首先使用經(jīng)典的 SSH 模式進行由淺入深地開發(fā)出第一個分類管理模塊 ,
然后分析這種方式的弊端,對其進行項目重構(gòu),重構(gòu)這一塊可以學(xué)習(xí)到不少 Java 里的中高級處理手法,
使得框架更加緊湊,后續(xù)開發(fā)更加便利和高效率。

實體類設(shè)計

準備 Category 實體類,并用 Hibernate 注解標示其對應(yīng)的表,字段等信息。
舉個例子,對于 分類 / category 的 實體類 和 表結(jié)構(gòu) 設(shè)計如下:

DAOImpl 類設(shè)計

DAO 是 Data Access Object 的縮寫,專門用于進行數(shù)據(jù)庫訪問的操作。
DAOImpl 繼承了 HibernateTemplate,這是一個 Hibernate 框架提供的模板類,提供了各種各樣的 CRUD方法,滿足各種數(shù)據(jù)庫操作的需要。

重寫 HibernateTemplate 的 setSessionFactory() 方法, 以用于注入 SessionFactory ,

SessionFactory 是在 spring 的配置文件里面定義的 bean ,可以看到其配置了連接數(shù)據(jù)庫的數(shù)據(jù)源等信息,這樣 dao 操作的時候,就不必獲取對應(yīng)的數(shù)據(jù)庫連接進行操作,
Spring 將數(shù)據(jù)源 ds 對象注入 SessionFactory ,sf 又被注入到 HibernateTemplate ,dao 繼承 HibernateTemplate 就可以直接操作數(shù)據(jù)庫了,非常簡便。

對比不使用 Spring+Hibernate 的情況,我們需要利用數(shù)據(jù)管理類 DBUtil 獲取 Connectoion ,
并在 dao 里面獲取對應(yīng)的 Statement 分別實現(xiàn) CURD 等方法,利用 JDBC 從數(shù)據(jù)庫取出數(shù)據(jù),再構(gòu)造成 bean 對象返回。


Service 類

設(shè)計 CategoryService 接口,用于提供業(yè)務(wù)方法 list() ,即查詢所有的分類。

public interface CategoryService{public List list(); }

CategoryServiceImpl 實現(xiàn)了 CategoryService 接口,提供list()方法的具體實現(xiàn),同時自動裝配(注入) 了 DAOImpl 的實例 dao ,
在 list() 方法中,通過 dao 獲取所有的分類對象。

@Service public class CategoryServiceImpl implements CategoryService {@Autowired DAOImpl dao;@Overridepublic List list() {DetachedCriteria dc = DetachedCriteria.forClass(Category.class); // 獲取DetachedCriteria對象dc.addOrder(Order.desc("id"));return dao.findByCriteria(dc); //這是 HibernateTemplate 提供的方法} }

Action 類

CategoryAction 類作為 MVC 設(shè)計模式中的控制層起作用。

  • 使用 basicstruts ,對應(yīng)配置文件 struts.xml 中定義的 basicstruts 保持一致
  • 在 Result 注解中,定義了返回的頁面為 /admin/listCategory.jsp
  • 自動裝配(注入)categoryService 對象,用于從數(shù)據(jù)庫獲取所有分類對象的集合。
  • 把對 admin_category_list 路徑的訪問映射到 list 方法上
  • list() 方法通過 categoryService 獲取到所有的分類對象,放在 categories 屬性中。
  • 同時提供了 getCategories() 方法,用于向listCategory.jsp頁面?zhèn)鬟f數(shù)據(jù)
  • 配置文件

    web.xml

    這個web.xml做了3件事情
    1.讓所有請求都進入 Struts2 的過濾器 StrutsPrepareAndExecuteFilter
    2.對所有請求進行 UTF-8 編碼
    3.指定Spring配置文件 applicationContext.xml 的位置

    <web-app><filter><filter-name>struts2</filter-name><filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class></filter><filter-mapping><filter-name>struts2</filter-name><dispatcher>FORWARD</dispatcher><dispatcher>REQUEST</dispatcher> <url-pattern>/*</url-pattern></filter-mapping><filter><filter-name>encodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param></filter><filter-mapping><filter-name>encodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener> </web-app>
    struts.xml
    <struts><constant name="struts.i18n.encoding" value="UTF-8"></constant><constant name="struts.objectFactory" value="spring"/><package name="basicstruts" extends="struts-default"></package> </struts>
    applicationContext.xml

    applicationContext 除了配置上述的 SessionFactory ,還要配置事務(wù)管理器

    <!-- 配置事務(wù)管理器(聲明式的事務(wù)) --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sf"></property> </bean>
    訪問 jsp 顯示數(shù)據(jù)

    Action 攜帶數(shù)據(jù)跳轉(zhuǎn)到 jsp ,作為視圖,擔當?shù)慕巧秋@示數(shù)據(jù),借助 JSTL 的 c:forEach 標簽遍歷從CategoryAction 的 list() 的傳遞過來的集合。

    完整版的 listCategory.jsp 還包含4個公共文件,分別是 頭部,導(dǎo)航,行業(yè),頁腳。
    分類管理還有增加,編輯,修改,刪除,分頁,另外后臺其他管理頁面,前臺頁面。具體的需要瀏覽代碼,篇幅原因就不展開了。

    思路流程圖

    重構(gòu)(這里非常精彩)

    分類管理的 CURD 功能全部做好之后,代碼層面的問題開始逐漸浮現(xiàn)出來了,問題主要表現(xiàn)在 Service 層,和 Action 層。

    Service層的問題

    Service 層代碼如下:

    首先看接口:CategoryService。 其聲明的方法基本上就是 CURD 和分頁。可以預(yù)見的是,在后續(xù)做產(chǎn)品管理,用戶管理,訂單管理等等,
    也會有這么一個非常近似的 CURD 的接口,換句話說,這里是有做抽象和代碼重構(gòu)的機會和價值的。

    然后看實現(xiàn)類:CategoryServiceImpl。 CategoryServiceImpl本身其實就是個架子,真正起作用的是為其注入的DAO對象,
    所以這個地方也是可以引入委派模式,使得代碼調(diào)用更加順暢。

    Service 層的重構(gòu)

    Service層 的重構(gòu)行為主要包括兩種角度

  • 對CURD進行抽象
  • 委派模式的重構(gòu)
  • 由于可以預(yù)見的在后續(xù)做產(chǎn)品管理,用戶管理,訂單管理等等,也會有這么一個非常近似的CURD的接口,
    那么我們就做一個BaseService,里面就提供這些CRUD和分頁查詢的方法。

    接著設(shè)計 BaseServiceImpl 類,其 CURD 關(guān)鍵方法都是調(diào)用的被注入的 dao 完成的,這樣就十分適合使用委派模式來重構(gòu)這塊代碼。

    不使用委派模式訪問數(shù)據(jù)庫都需要通過dao.XXX()來進行。 而委派重構(gòu)之后,數(shù)據(jù)庫相關(guān)方法,不再需要通過dao,直接調(diào)用即可,代碼看上去更簡潔。

    委派類 ServiceDelegateDAO

    設(shè)計一個新的類,叫做 ServiceDelegateDAO ,在其中注入 dao ,然后讓對 dao 的每一個方法進行委派。
    那么到底什么是委派呢? 如 ServiceDelegateDAO 類所示:
    public void delete(Object entity) throws DataAccessException { dao.delete(entity); }

    當調(diào)用 ServiceDelegateDAO 對象的 delete(Object entity) 的時候,其實就是委派給的 dao 的 delete(Object entity) 方法。
    但是從調(diào)用者的角度來看,調(diào)用者只知道 ServiceDelegateDAO 這個類的 delete(Object entity) 方法,而意識不到 dao 的存在。
    而 dao 繼承了 HibernateTemplate ,一共有一百多個方法,哈哈這么麻煩肯定有工具可以一鍵生成,
    果然利用 idea 立馬就生成了所有委派方法,即快速又不會出錯,突然感覺好開心。

    BaseServiceImpl

    BaseServiceImpl 的構(gòu)造器非常騷氣,BaseServiceImpl 的 clazz 對象需要引用實體類對象,這樣 CURD 方法中的 DetachedCriteria dc = DetachedCriteria.forClass(clazz); 才能獲取到對應(yīng)的查詢對象。
    所以這里利用反射,在構(gòu)造方法中,借助異常處理和反射得到 Category.class 或者 Product.class 。 即要做到哪個類繼承了 BaseServiceImpl ,clazz 就對應(yīng)哪個類對應(yīng)的實體類對象。

    首先要獲取是哪個類繼承了 BaseServiceImpl ,因為實例化子類,父類的構(gòu)造方法一定會被調(diào)用,
    所以在父類 BaseServiceImpl 里故意拋出一個異常,然后手動捕捉住它,
    在其對應(yīng)的 StackTrace 里的第二個(下標是1) 棧跟蹤元素 StackTraceElement ,即對應(yīng)子類。
    這樣我們就拿到了子類名稱 CategoryServiceImpl 或者 ProductServiceImpl,具體的在代碼注釋里了,寫的非常清楚。

    這樣 CategoryService 就不需要自己聲明方法了,只需要繼承接口 BaseService 即可

    CategoryServiceImpl 也不需要自己提供實現(xiàn)了,繼承 BaseServiceImpl 并實現(xiàn)接口 CategoryService 即可

    這么做的好處主要在于:后續(xù)新功能開發(fā)的過程中,當需要新增加新的Service類的話,比如 PropertyService,無需從頭開發(fā),
    只需要繼承 BaseServiceImpl 并實現(xiàn) PropertyService,那么其所需要CRUD一套方法都有了。

  • 開發(fā)成本顯著降低
  • 更加不容易出錯(因為方法都被抽象在父類中了,并且被前面的業(yè)務(wù)驗證過了,要出錯早就被糾正過了)
  • Action的問題

    先看代碼

    這樣的CategoryAction代碼完成功能是沒有問題的,但是問題恰恰在于,這樣一個本來是用于充當控制層(Controller)的類,需要集中應(yīng)付太多的需求:

  • 返回頁面的定義
  • 單個對象的getter setter
  • 集合對象的getter setter
  • 分頁對象的getter setter
  • 上傳文件對象的getter setter
  • Service層對象的注入
  • 作為控制層進行的訪問路徑映射
  • 把所有的這些代碼,都放在一個類里面,這個類就會顯得繁雜,不易閱讀,不易維護。 所以這個地方也是很有代碼重構(gòu)價值的。

    Action 層的重構(gòu)

    目前 CategoryAction 存在的問題是一個類需要做太多的事情,顯的繁雜,影響閱讀和維護。 那么重構(gòu)思路就是把不同的事情,放在專門的類進行處理,各司其職。

    • 上傳專用 Action4Upload
      這個類就專門用于處理圖片上傳,其他的事情一概不管
    • 分頁專用 Action4Pagination
      專門用于處理分頁,并且繼承上傳專用 Action4Upload
    • 對象和集合 Action4Pojo
      用于提供實體對象以及實體對象集合的setter和getter.
      setter用于接收注入
      getter用于提供數(shù)據(jù)到JSP(VIEW)上
    • 注入服務(wù)專用 Action4Service
      Action4Service提供服務(wù)的注入

    Action4Service 另外提供了一個方法 t2p() ,專門用于把對象指向?qū)?yīng)的持久對象。

    方法調(diào)用的最后結(jié)果就導(dǎo)致父類 Action4Pojo 中聲明的 pojo 本身是指向瞬時對象的,現(xiàn)在指向了持久對象(從數(shù)據(jù)庫中取出的對象)。

    再定義返回頁面的 Action4Result 繼承 Action4Service ,專門進行返回頁面的定義

    這樣
    CategoryAction 繼承Action4Result, 于是就間接地繼承了 Action4Service,Action4Pojo,Action4Pagination,Action4Upload,
    于是就通過繼承提供了各種相關(guān)的功能,CategoryAction 本身只需要專注于扮演控制器(Controller)本身就行了。這些工作對后面其他 Action 同樣適用,大大簡化了后續(xù)開發(fā)。

    此外,后續(xù)還有針對 Service 的關(guān)系查詢重構(gòu),和Service 多條件查詢重構(gòu),具體的由于篇幅原因,請移步github 項目的地址

    頁面展示

    本篇博客所講不足整個項目的 1/10 ,有興趣的朋友請移步 github 項目的地址 。

    參考

    天貓SSH整站學(xué)習(xí)教程 里面除了本項目,還有 Java 基礎(chǔ),前端,Tomcat 及其他中間件等教程, 可以注冊一個賬戶,能保存學(xué)習(xí)記錄。

    轉(zhuǎn)載于:https://www.cnblogs.com/czwbig/p/9953893.html

    總結(jié)

    以上是生活随笔為你收集整理的JavaWeb入门_模仿天猫整站Tmall_SSH实践项目的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。