面試官你好,我叫XXX,畢業於XXX大學,2013年8月進入XXX科技有限公司。在這兩年中我總共作過三個項目,第一個是個給一家教育培訓公司作信息管理系統,第二個是一個物流公司的項目。第三個就是最近作過的電商項目。咱們這個項目採用了分佈式的架構,使用maven進行項目依賴和jar包的管理,使用中間切分的方式將web,service,mapper,pojo分層開發,好處是讓代碼的重用性更高。整個項目技術用spring,springmvc,mybatis框架進行開發.
咱們這個項目分爲後臺商品管理模塊、會員模塊、訂單模塊、購物車模塊、支付模塊、搜索模塊、評論模塊等。
我在這個項目中主要負責了後臺商品管理模快:主要是實現了商品的錄入、上下架、以及商品類目詳情展現,包括商品規格參數模版設計以及商品實際規格參數錄入功能。其中在商品查詢過程當中沒有使用傳統的mybatis分頁查詢而是使用一個分頁插件PageHelper來實現。對於商品圖片的上傳,在後臺頁面使用了富文本編輯器KindEditor進行批量上傳。後臺使用fileupload組件來接收圖片,在後臺代碼裏面實現圖片校驗功能,圖片校驗包括:1.對圖片的大小進行校驗;2.對圖片的格式進行校驗;3.對文件的內容進行校驗。防止危險腳本經過圖片上傳功能到服務器;文件內容的校驗是經過ImageIO讀取上傳的文件構建BufferedImage對象,經過判斷BufferedImage的寬和高屬性來判別上傳的文件是否爲圖片。關於數據庫優化方面,商品表中價格字段使用long型存儲,避免了開發中處理小數的問題。商品描述做爲表格單獨設計,由於數據量比較大,並且描述通常不輕易改動,單獨做爲一個表在查詢商品的時候不須要查詢,提升了查詢性能。用戶須要的時候讓其查詢。而對於商品規格參數的設計考慮到一個商品對應一張表,存放該商品的規格參數數據,數據表太龐大,因而組內商討設計了一張商品規格參數的模版表,該表中有六個字段,分別是ID、建立時間、更新時間、商品類目ID、商品類目名稱、規格參數模板數據。每個類目對應模板表的一條記錄,規格參數模板數據存放的是商品類目的規格參數。新增商品時,根據模版生成一個規格參數的表單,填寫規格參數數據,保存到數據庫中。
在前臺系統中我實現了商品分類的展現,實現商品分類展現咱們有兩種思路,第一種就是當前臺系統的頁面須要展現須要商品分類信息的時候,前臺頁面向前臺系統發送Ajax請求,由前臺系統經過HttpClient訪問後臺系統獲取商品分類信息,而後前臺系統將商品分類信息數據響應給前臺頁面。
第二種實現方案是前臺頁面直接發送ajax請求訪問後臺系統。由於後臺系統向前臺頁面發送的是json格式的數據,而json數據沒法進行跨域傳送,因此咱們使用了jsonp來包裝json數據,實現跨域數據的傳輸。這種實現方案性能稍高於第一種,最後我採用的就是這用設計思路。
因爲商品首頁分類展現的操做很頻繁,爲了減輕數據庫的壓力,咱們使用了redis做爲緩存數據庫。後臺系統在查詢MySQL數據庫以前,先查看redis裏面是否有商品分類信息,若是有則直接返回結果,若是沒有則查詢MySQL數據庫,將查詢結果保存在redis中並返回該結果。
咱們的項目中關於用戶登陸的這一塊採用的是單點登陸系統,考慮到通常用戶登陸的時候,當用戶登陸成功之後,咱們將用戶信息保存在session中,由於這個咱們採用的是分佈式架構,當用戶要訪問其餘的功能模塊的時候,因爲session是基於web服務器的(session是存在於一次回話 因此不能跨服務器),每個功能模塊都有一個本身的web服務器,各個功能模塊不能共享session數據,因此用戶須要從新登陸。咱們採用了單點登陸系統。當用戶登陸成功後,咱們根據時間戳和用戶id生成惟一的令牌ticket,將ticket和用戶信息做爲鍵值對存放在redis中,並把ticket寫入cookie中,當用戶訪問其餘功能模塊的時候,首先從cookie中拿到ticket,根據ticket在redis裏面查找用戶信息,若是找到則登陸成功。
在首頁的商品搜索模塊中咱們使用了solr實現,咱們提供服務從數據庫中查詢的數據生成索引庫。爲了實現各模塊數據之間的同步,咱們在搜索模塊提 供了服務接口。只要後臺系統數據有增長,刪除,修改就調用搜索模塊的服務進行索引庫的維護。(搜索這一塊是其餘人作的,他們提供了一個接口,經過這個接 口調用搜索模塊的服務進行維護。)
咱們使用RabbitMQ實現商品數據的同步。爲了減輕數據庫的壓力,提升系統性能咱們引入了redis緩存數據庫和solr索引庫,這樣就會涉及一個數據同步的問題。咱們要保證MySQL數據庫、redis緩存數據庫以及索引庫中商品的數據是一致的,原先咱們是這麼作的:當後臺系統商品的數據進行增長,刪除,修改的操做後,經過httpClient調用前臺系統和搜索系統對redis和索引庫中的數據進行維護。這樣雖然能解決數據同步的問題,可是各個模塊之間的耦合性過高,當新增長某個系統之後,要對後臺系統進行維護,這顯然是不合理的,因此咱們引入了RabbitMQ。後臺管理系統做爲消息的生產者,須要發送消息,在後臺系統聲明交換機,肯定交換機的類型爲topic。前端系統和搜索系統都是消息的消費者,在前端系統和搜索系統端聲明隊列,並監聽隊列消息,根據消息內容作出相應的操做。
購物車的實現有多種方式,能夠直接使用數據庫存儲購買的商品信息,可使用session來做爲購物車存儲商品。用數據庫來存儲商品對數據庫形成的負擔特別大,並且對於購物車這種須要實時操做的東西,數據庫的訪問量一旦太大,數據庫容易出現併發錯誤,或者直接崩潰。用session來存儲商品信息效率確實很高, 並且會話是針對各個鏈接的, 因此便於管理, 可是用session也不是完美的, 由於session是有有效期的, 根據服務器的設置不一樣而不同長, 若是你在購物的過程當中session超時了, 那麼購物車中的東西就會全沒了;session是保存在服務器內存中的,佔用了服務器資源。session沒法進行水平擴展,使用集羣。基於這些考慮,咱們使用cookie+MySQL來實現購物車功能。當用戶處於登陸狀態的時候,咱們將購物車信息存放在MySQL數據庫中;當用戶處於未登陸狀態,咱們將購物車信息保存在cookie中,用戶進行登陸操做的時候,判斷cookie中是否有購物車信息,若是有,則把購物車信息與數據庫中的合併。由於咱們使用了數據庫做爲購物車來存放商品數據,考慮到數據庫的壓力大,咱們採用了數據庫的集羣搭建實現數據的讀寫分離。咱們設計了一個主庫負責寫入數據,三個從庫讀取數據,這樣就大大減輕了數據庫的壓力。
訂單系統,購物車系統
在首頁的商品搜索模塊中咱們使用了solr實現,咱們提供服務從數據庫中查詢的數據生成索引庫。爲了實現與數據庫之間的同步,咱們在搜索快提供了服務接口。只要數據有增長,刪除,修改就調用對應的服務。再以後我就實現了商品詳情頁的展現,首先根據商品的id到redis緩存中命中,若是緩存中沒有才會查詢數據庫,而且保存到redis中,考慮到redis是內存稀缺資源。因此咱們在設計的時候爲不須要常常顯示的提供了在redis中的有效時間。咱們設計的是一天。在商品詳情頁中首先將關鍵字段查詢展現,在使用延遲的方法加載商品描述,提升了相應的速度。而且商品規格咱們使用按需加載,只有點擊纔會加載。較輕數據庫壓力。
因爲顧客要建立訂單須要登陸,可是咱們採用的分佈式架構,爲了提升顧客的體驗性。因此咱們採用了單點登陸系統。前端