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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

电商项目介绍

發(fā)布時(shí)間:2023/12/9 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 电商项目介绍 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

電商項(xiàng)目介紹

2.電商行業(yè)技術(shù)特點(diǎn)

技術(shù)新(NoSql推廣首在社區(qū)網(wǎng)站和電商項(xiàng)目),發(fā)展快,需求推動(dòng)技術(shù)的革新。

技術(shù)范圍廣:除了java,像淘寶前端還使用了PHP,數(shù)據(jù)庫(kù)MySQL或者oraclenosql,服務(wù)器端使用Linux,服務(wù)器安全、系統(tǒng)安全

分布式:以前是在一臺(tái)機(jī)器上做運(yùn)算,現(xiàn)在是分散到很多機(jī)器上,最后匯總起來(lái)。(集中式向分布式進(jìn)行考慮)由需求來(lái)推動(dòng)

高并發(fā)、集群、負(fù)載均衡、高可用:由并發(fā)問(wèn)題采用集群進(jìn)行處理,其中,集群會(huì)涉及服務(wù)器的主從以及分布問(wèn)題,使用負(fù)載均衡。(權(quán)重高低)高可用是對(duì)用戶(hù)而言,用戶(hù)的服務(wù)不中斷(系統(tǒng)升級(jí),服務(wù)不中斷,淘寶每周更新2)。

海量數(shù)據(jù):雙11,570億的背后,訂單有多少?瀏覽次數(shù)有多少?商品會(huì)有多少?活動(dòng)相關(guān)數(shù)據(jù)?

業(yè)務(wù)復(fù)雜:不要簡(jiǎn)單的認(rèn)為是:商品展示出來(lái)后,加入購(gòu)物車(chē)后購(gòu)買(mǎi)就完成了。后臺(tái)特別復(fù)雜,比如優(yōu)惠(包郵、滿減)

系統(tǒng)安全:系統(tǒng)上線必須通過(guò)系統(tǒng)安全部門(mén)審核通過(guò)。前年CSDN數(shù)據(jù)泄露。快捷酒店數(shù)據(jù)泄露(通過(guò)身份證就可以查看你的開(kāi)房記錄)。近幾年,安全意識(shí)逐步在提高。

電商行業(yè)的一些概念

? ??1、?B2C商家對(duì)客戶(hù)京東、當(dāng)當(dāng)發(fā)展B2C平臺(tái),天貓(B2C平臺(tái)?淘寶商城由馬云提出,率先發(fā)展為平臺(tái)),1號(hào)店也是(在上海)

? ??? ????2、?B2B商家對(duì)商家阿里巴巴(不零售,只批發(fā),淘寶很多商家都會(huì)去阿里巴巴進(jìn)貨);

? ??? ????3、?C2C個(gè)人對(duì)個(gè)人淘寶市場(chǎng),淘寶QQ商城;

系統(tǒng)功能

? ?本商城系統(tǒng)是一個(gè)綜合性的B2C平臺(tái),類(lèi)似京東商城、天貓商城。

會(huì)員可以在商城瀏覽商品、下訂單,以及參加各種活動(dòng)。

商家可以在入住淘淘商城,在該平臺(tái)上開(kāi)店出售自己的商品,并且得到淘淘商城提供的可靠的服務(wù)。

管理員、運(yùn)營(yíng)可以在平臺(tái)后臺(tái)管理系統(tǒng)中管理商品、訂單、會(huì)員等。

客服可以在后臺(tái)管理系統(tǒng)中處理用戶(hù)的詢(xún)問(wèn)以及投訴。

??

?

? ??首先我們要有商品,管理員可以在系統(tǒng)中管理商品,用戶(hù)可以查看商品。
? ??商品多了之后要有類(lèi)目模塊,管理員可以管理類(lèi)目信息,用戶(hù)可以根據(jù)類(lèi)目檢索商品。
? ??有了商品之后,要有人(會(huì)員)買(mǎi)東西,普通用戶(hù)注冊(cè)為會(huì)員,會(huì)員可以登錄到系統(tǒng)管理自己的信息(密碼)
? ??買(mǎi)了之后會(huì)生成訂單會(huì)員可以購(gòu)買(mǎi)商品并且可以下單,管理員可以管理訂單。
? ??有了訂單之后需要支付(在線支付/貨到付款)
? ??……

這樣,我們就可以把整個(gè)電商項(xiàng)目的功能記清楚了!

分布式系統(tǒng)架構(gòu)

左圖為分布式系統(tǒng)架構(gòu),右圖為傳統(tǒng)架構(gòu)!

? ?

各個(gè)系統(tǒng)說(shuō)明:

后臺(tái)管理系統(tǒng):管理商品、訂單、類(lèi)目、商品規(guī)格屬性、用戶(hù)管理以及內(nèi)容發(fā)布等功能。

前臺(tái)系統(tǒng):用戶(hù)可以在前臺(tái)系統(tǒng)中進(jìn)行注冊(cè)、登錄、瀏覽商品、首頁(yè)、下單等操作。

會(huì)員系統(tǒng):用戶(hù)可以在該系統(tǒng)中查詢(xún)已下的訂單、收藏的商品、我的優(yōu)惠券、團(tuán)購(gòu)等信息。

訂單系統(tǒng):提供下單、查詢(xún)訂單、修改訂單狀態(tài)、定時(shí)處理訂單。

搜索系統(tǒng):提供商品的搜索功能。

單點(diǎn)登錄系統(tǒng):為多個(gè)系統(tǒng)之間提供用戶(hù)登錄憑證以及查詢(xún)登錄用戶(hù)的信息。

談到分布式架構(gòu),我們必須對(duì)比傳統(tǒng)架構(gòu)才能彰顯其優(yōu)勢(shì)。

? ??最為明顯的一點(diǎn),在傳統(tǒng)的架構(gòu)中,如果某個(gè)功能需要進(jìn)行維護(hù),那么我們必須停掉整個(gè)服務(wù),這對(duì)于公司的運(yùn)營(yíng)會(huì)造成損失。分布式系統(tǒng)在核心功能模塊使用單獨(dú)服務(wù)器,維護(hù)部分模塊不影響用戶(hù)的其他操作。

? ??在海量數(shù)據(jù)處理方面,傳統(tǒng)架構(gòu)顯得比較乏力;分布式系統(tǒng)架構(gòu)采用服務(wù)器集群,使用負(fù)載均衡,海量數(shù)據(jù)處理游刃有余!

? ??在性能(檢索)以及維護(hù)方面,分布式系統(tǒng)架構(gòu)也有較為明顯的優(yōu)勢(shì)。

6.本系統(tǒng)人員配置情況

l?產(chǎn)品經(jīng)理:3人,確定需求以及給出產(chǎn)品原型圖。

l?項(xiàng)目經(jīng)理:1人,項(xiàng)目管理。

l?前端團(tuán)隊(duì):3人,根據(jù)產(chǎn)品經(jīng)理給出的原型制作靜態(tài)頁(yè)面。

l?后端團(tuán)隊(duì):20人,實(shí)現(xiàn)產(chǎn)品功能。

l?測(cè)試團(tuán)隊(duì):3人,測(cè)試所有的功能。

l?運(yùn)維團(tuán)隊(duì):2人,項(xiàng)目的發(fā)布以及維護(hù)。

?

7.開(kāi)發(fā)流程

? ??

?

此圖不做詳細(xì)解釋(就業(yè)指導(dǎo)課已進(jìn)行詳細(xì)說(shuō)明,注意整個(gè)流程中容易被問(wèn)到的問(wèn)題)

?

8.后臺(tái)開(kāi)發(fā)環(huán)境

? ??

需要注意,在幾個(gè)環(huán)境中,預(yù)發(fā)布環(huán)境和生產(chǎn)環(huán)境幾乎一樣,開(kāi)發(fā)環(huán)境和測(cè)試環(huán)境是獨(dú)立存在的,每一個(gè)階段的活是由對(duì)應(yīng)的工作人員來(lái)負(fù)責(zé)的。
此外,我們還需要熟悉?SVN主干、分支、標(biāo)簽開(kāi)發(fā)過(guò)程流程

? ??

? ??整個(gè)開(kāi)發(fā)沿著主線進(jìn)行,在一個(gè)版本定型后,前一個(gè)版本出現(xiàn)bug,那么此時(shí)會(huì)對(duì)bug進(jìn)行修復(fù),投入使用的依舊是之前定型的那個(gè)版本,待前一個(gè)版本的bug修復(fù)好了之后,會(huì)定義一個(gè)新的版本,主線不會(huì)改變,如果改動(dòng)不大,那么只需修訂問(wèn)題,繼續(xù)沿用此版本(1.0.x),只有出現(xiàn)較大改動(dòng)時(shí),才會(huì)升級(jí)一個(gè)新的版本號(hào)(1.1.x)。所有動(dòng)作,交替進(jìn)行,沿主線向前推進(jìn)!

9.涉及技術(shù)

l?Spring、SpringMVCMybatis

l?JSP、JSTL、jQuery、jQuery?pluginEasyUI、KindEditor(富文本編輯器)、CSS+DIV

l?Redis(緩存服務(wù)器)

l?LuceneSolr(搜索)

l?httpclient(調(diào)用系統(tǒng)服務(wù))

l?Mysql

l?Nginxweb服務(wù)器)

l?Quartz(定時(shí)任務(wù))

l?RabbitMQ(消息隊(duì)列)

?

技術(shù)詳解見(jiàn)其它章節(jié),未接觸技術(shù)點(diǎn)(標(biāo)背景色技術(shù)點(diǎn))將在本項(xiàng)目后續(xù)內(nèi)容中進(jìn)行介紹。

10.開(kāi)發(fā)工具和環(huán)境

l?Eclipse?4.4.1?

l?Maven?3.2.3

l?Tomcat?7.0.47Maven?Tomcat?Plugin

l?JDK?1.7

l?Mysql?5.6

l?Nginx?1.5.1

l?Redis?2.8.9

l?Win7?操作系統(tǒng)

l?SVN(版本管理)?

?

此章節(jié),需要注意所有開(kāi)發(fā)工具的版本號(hào)要對(duì)應(yīng)(一致),否則會(huì)出現(xiàn)沖突問(wèn)題,面試大忌!(常識(shí):電商項(xiàng)目火起來(lái)的時(shí)間不是很久,在開(kāi)發(fā)的時(shí)候,很多開(kāi)發(fā)工具和環(huán)境不像之前那些傳統(tǒng)系統(tǒng)那么老舊,這點(diǎn)一定要引起注意!)

?

電商項(xiàng)目面試問(wèn)題

?

項(xiàng)目介紹

屬于B2C平臺(tái)----商家對(duì)客戶(hù)

系統(tǒng)的用途,主要是提供B2C的平臺(tái),其中自營(yíng)商品也有商家入住,類(lèi)似天貓。

系統(tǒng)架構(gòu),采用分布式的系統(tǒng)架構(gòu),其中前臺(tái)系統(tǒng)和單點(diǎn)登錄系統(tǒng)采用了集群的方式部署,在后臺(tái)管理系統(tǒng)中采用了Maven的多模塊化的管理,其中采用了水平切分的方式,將pojo、dao、service、web分層開(kāi)發(fā),這樣做的好處就是可以重用性更高。

系統(tǒng)內(nèi)部接口調(diào)用采用Httpclient,并且使用Httpclient的連接池技術(shù),接口提供端采用RESTful方式的接口定義;

系統(tǒng)之間的通知機(jī)制采用MQ的方式,使用RabbitMQ的實(shí)現(xiàn),使用了RabbitMQ的消息訂閱模式的消息機(jī)制;

系統(tǒng)的接口還對(duì)JS的跨域做了支持,采用了jsonp的解決方法,在后臺(tái)接口中擴(kuò)展了spirng提供的jackson數(shù)據(jù)轉(zhuǎn)化器實(shí)現(xiàn);

? ??④部署方面,采用了Nginx+tomcat的模式,其中nginx的作用一方面是做反向代理、負(fù)載均衡、另一方面是做圖片等靜態(tài)資源的服務(wù)器。

項(xiàng)目介紹應(yīng)該從這個(gè)項(xiàng)目的模式、功能、架構(gòu)、解決了什么問(wèn)題、部署以及投入使用情況來(lái)說(shuō)。

2.整個(gè)項(xiàng)目的架構(gòu)如何?

一般情況這個(gè)問(wèn)題要從兩個(gè)方面去回答,從技術(shù)架構(gòu)和功能架構(gòu)去談。

技術(shù)架構(gòu):本項(xiàng)目使用主流框架spring+springmvc+mybatis進(jìn)行開(kāi)發(fā),采用分布式的系統(tǒng)架構(gòu),前臺(tái)系統(tǒng)和單點(diǎn)登錄系統(tǒng)采用了集群的方式部署,后臺(tái)管理系統(tǒng)中采用了Maven的多模塊化的管理,其中采用了水平切分的方式,將pojo、dao、service、web分層開(kāi)發(fā),這樣做的好處就是可以重用性更高。系統(tǒng)內(nèi)部接口調(diào)用采用Httpclient,并且使用Httpclient的連接池技術(shù),接口提供端采用RESTful方式的接口定義;系統(tǒng)之間的通知機(jī)制采用MQ的方式,使用RabbitMQ的實(shí)現(xiàn),使用了RabbitMQ的消息訂閱模式的消息機(jī)制;系統(tǒng)的接口還對(duì)JS的跨域做了支持,采用了jsonp的解決方法,在后臺(tái)接口中擴(kuò)展了spirng提供的jackson數(shù)據(jù)轉(zhuǎn)化器實(shí)現(xiàn);搜索系統(tǒng)使用了solr實(shí)現(xiàn),在保證系統(tǒng)高性能的前提下,盡可能為公司節(jié)約成本,我們使用MySQL數(shù)據(jù)庫(kù)進(jìn)行集群(oracle收費(fèi))。在部署方面,采用了Nginx+tomcat的模式,其中nginx的作用一方面是做反向代理、負(fù)載均衡、另一方面是做圖片等靜態(tài)資源的服務(wù)器。

功能架構(gòu):分布式系統(tǒng)架構(gòu)

各個(gè)系統(tǒng)說(shuō)明:

后臺(tái)管理系統(tǒng):管理商品、訂單、類(lèi)目、商品規(guī)格屬性、用戶(hù)管理以及內(nèi)容發(fā)布等功能。

前臺(tái)系統(tǒng):用戶(hù)可以在前臺(tái)系統(tǒng)中進(jìn)行注冊(cè)、登錄、瀏覽商品、首頁(yè)、下單等操作。

會(huì)員系統(tǒng):用戶(hù)可以在該系統(tǒng)中查詢(xún)已下的訂單、收藏的商品、我的優(yōu)惠券、團(tuán)購(gòu)等信息。

訂單系統(tǒng):提供下單、查詢(xún)訂單、修改訂單狀態(tài)、定時(shí)處理訂單。

搜索系統(tǒng):提供商品的搜索功能。

單點(diǎn)登錄系統(tǒng):為多個(gè)系統(tǒng)之間提供用戶(hù)登錄憑證以及查詢(xún)登錄用戶(hù)的信息。

談到分布式架構(gòu),我們必須對(duì)比傳統(tǒng)架構(gòu)才能彰顯其優(yōu)勢(shì)。

? ??①最為明顯的一點(diǎn),在傳統(tǒng)的架構(gòu)中,如果某個(gè)功能需要進(jìn)行維護(hù),那么我們必須停掉整個(gè)服務(wù),這對(duì)于公司的運(yùn)營(yíng)會(huì)造成損失。分布式系統(tǒng)在核心功能模塊使用單獨(dú)服務(wù)器,維護(hù)部分模塊不影響用戶(hù)的其他操作。

? ??②在海量數(shù)據(jù)處理方面,傳統(tǒng)架構(gòu)顯得比較乏力;分布式系統(tǒng)架構(gòu)采用服務(wù)器集群,使用負(fù)載均衡,海量數(shù)據(jù)處理游刃有余!

? ??③在性能(檢索)以及維護(hù)方面,分布式系統(tǒng)架構(gòu)也有較為明顯的優(yōu)勢(shì)。

傳統(tǒng)架構(gòu)

3.這個(gè)項(xiàng)目為用戶(hù)提供了哪些服務(wù)?包括哪些功能?

u?商品管理模塊:其中包括品牌管理,屬性管理商品錄入/上下架管理,商品添加審核,靜態(tài)頁(yè)面發(fā)布
u?訂單模塊:其中包括使用activiti工作流訂單的查詢(xún)和訂單的流轉(zhuǎn),定時(shí)作廢
u?商品前臺(tái)首頁(yè):其中主要負(fù)責(zé)首頁(yè)商品列表篩選,首頁(yè)上動(dòng)態(tài)展示篩選條件,點(diǎn)擊每一個(gè)篩選條件下面的商品列表要做聯(lián)動(dòng)
u?單品頁(yè)面:采用freemarker來(lái)實(shí)現(xiàn)頁(yè)面靜態(tài)化,展示商品詳情信息和商品購(gòu)買(mǎi),該頁(yè)面采用靜態(tài)化以減輕系統(tǒng)壓力,使用了cxf框架發(fā)布服務(wù)
u?提交訂單頁(yè)面:提交用戶(hù)的訂單信息,?處理并發(fā)問(wèn)題。
u?個(gè)人中心,包括用戶(hù)的登錄,個(gè)人信息的管理,收貨地址的管理,用戶(hù)所下的訂單的管理
u?購(gòu)物車(chē):把購(gòu)物車(chē)的信息存在cookie里面管理

4.你承擔(dān)這個(gè)項(xiàng)目的哪些核心模塊?

在項(xiàng)目中主要負(fù)責(zé)相關(guān)系統(tǒng)的開(kāi)發(fā),主要有:

? ??1)?后臺(tái)管理系統(tǒng),主要實(shí)現(xiàn)商品管理、商品規(guī)格參數(shù)管理、訂單管理、會(huì)員管理等、CMS(內(nèi)容管理系統(tǒng))等,并且提供了跨域支持;

? ??2)?前臺(tái)系統(tǒng),主要是面向用戶(hù)訪問(wèn),使用Httpclient和后臺(tái)系統(tǒng)接口做交互,并且該系統(tǒng)在部署上采用集群的方式;

? ??3)?單點(diǎn)登錄系統(tǒng),主要是提供集中用戶(hù)登錄憑證的集中解決方案,提供和用戶(hù)信息相關(guān)的接口,比如說(shuō)用戶(hù)注冊(cè)、查詢(xún)等接口。

? ??4)?訂單系統(tǒng),主要是提供和訂單相關(guān)的業(yè)務(wù)接口,在訂單系統(tǒng)了做了嚴(yán)格的數(shù)據(jù)校驗(yàn)以及高并發(fā)寫(xiě)的支持(這里可以說(shuō)使用隊(duì)列實(shí)現(xiàn)),并且使用了Quartz定時(shí)任務(wù)實(shí)現(xiàn)對(duì)訂單的定時(shí)掃描,比如說(shuō)關(guān)閉超時(shí)未付款的訂單;

? ??5)?搜索系統(tǒng),主要是提供商品的搜索,采用開(kāi)源企業(yè)級(jí)系統(tǒng)Solr實(shí)現(xiàn),采用了MQ機(jī)制保證了商品數(shù)據(jù)可以及時(shí)同步到solr中;

? ??6)?會(huì)員系統(tǒng),主要是維護(hù)用戶(hù)的信息,已購(gòu)買(mǎi)訂單、優(yōu)惠券、系統(tǒng)消息、修改密碼、綁定手機(jī)等功能;

? ??7)?緩存,主要是用Redis實(shí)現(xiàn),并且對(duì)Redis做了集群來(lái)保證Redis服務(wù)的高可用。8)?支付系統(tǒng),主要是負(fù)責(zé)訂單的支付、對(duì)賬等功能,主要是對(duì)接了支付寶的接口;

5.這些模塊的實(shí)現(xiàn)思路說(shuō)一下?

①商品管理模塊

品牌管理:
主要掌握的核心是品牌的添加
l?圖片服務(wù)器的搭建,
l?上傳圖片到圖片服務(wù)器
l?表單的驗(yàn)證,離開(kāi)焦點(diǎn)的驗(yàn)證,點(diǎn)擊完成時(shí)的驗(yàn)證,后臺(tái)服務(wù)器的ajax驗(yàn)證,表單規(guī)范
l?防止表單的二次提交
l?編輯時(shí)不需要修改品牌名,區(qū)別readOnly和disabled

l?刪除時(shí)的二次確認(rèn)
注意:
自定義屬性必須掌握:html中自定義的屬性可以幫助索引元素
圖片服務(wù)器的搭建
1.?創(chuàng)建一個(gè)maven的web工程,在工程中創(chuàng)建一個(gè)存放資源的目錄
2.?把tomcat的web.xml中DefaultServlet的只讀屬性改成false
?
3.?編寫(xiě)上傳到圖片服務(wù)器的代碼
由于應(yīng)用服務(wù)器與圖片服務(wù)器出于不同的兩臺(tái)機(jī)器之中,所以可以提高系統(tǒng)的性能,能起到負(fù)載均衡的作用。上傳圖片時(shí)使用Jersey客戶(hù)端API調(diào)用REST風(fēng)格的Web服務(wù),Jersey1是一個(gè)開(kāi)源的、可以用于生產(chǎn)環(huán)境的JAX-RS(RESTful?Web?Services?的Java?API?規(guī)范,JSR-311)實(shí)現(xiàn)。通Jersey?可以很方便的使用Java來(lái)創(chuàng)建一個(gè)RESTful?Web?Services。

byte[]?fileByte?=?commFile.getBytes();

//創(chuàng)建客服端,基于webservice

Client?client?=?Client.create();

?

//指定資源路徑

WebResource?webResource?=?client.resource(Constants.picPath+fileName);

?

//使用put的請(qǐng)求方式把資源文件放到資源服務(wù)器上

webResource.put(String.class,?fileByte);

前臺(tái)使用ajax提交表單,需要使用jquery的jquery.form.js插件

$("#form").ajaxSubmit({

url:url,

type:"post",

dataType:"text",

data:{

...

},

//beforeSubmit:validate,

success:function(responseText){

var?obj?=?$.parseJSON(responseText);

},

error:function(){

}

});

?

4.?圖片服務(wù)器中Upload文件夾中隨便建立一個(gè)文件,防止空文件夾的情況下發(fā)布后upload消失

表單驗(yàn)證

1.?提交時(shí)做驗(yàn)證
????做好約定,每個(gè)文本中設(shè)置reg屬性和tip自定義的屬性,reg存放正則表達(dá)式,tip中存放不合法時(shí)的提示信息,還有品牌名稱(chēng)重復(fù)的驗(yàn)證。
reg2,tip屬于自定義的屬性,這種定義方式方便使用jquery的屬性選擇器

<p>

????<label><samp>*</samp>品牌名稱(chēng):</label>

????<input?type="text"?id="brandName"?name="brandName"?class="text?state"?reg2="^[a-zA-Z0-9\u4e00-\u9fa5]{1,20}$"?tip="必須是中英文或數(shù)字字符,長(zhǎng)度1-20"/>

????<span></span>

</p>

2.?在表單提交時(shí)做驗(yàn)證使用$(“form”).submit(function(){?return?false?});,必填字段和非必填的字段需要區(qū)別對(duì)待

$("#form111").submit(function(){

????var?isSubmit?=?true;

????$(this).find("[reg2]").each(function(){

????????var?regStr?=?$(this).attr("reg2");

????????//剪掉值中的兩側(cè)的字符串

????????var?value?=?$.trim($(this).val());

????????var?tip?=?$(this).attr("tip");

????????//創(chuàng)建正則表達(dá)式的對(duì)象

????????var?reg?=?new?RegExp(regStr);

????????if(!reg.test(value)){

????????????$(this).next("span").html(tip);

????????????isSubmit?=?false;

????????????//跳出循環(huán),在jquery的each語(yǔ)句之中跳出循環(huán)使用return?false;?如果在原生js里面可使用break;,?return;:代表終止執(zhí)行程序

????????????return?false;

????????}

????});

????$(this).find("[reg1]").each(function(){

????????var?regStr?=?$(this).attr("reg1");

????????var?value?=?$.trim($(this).val());

????????var?tip?=?$(this).attr("tip");

????????var?reg?=?new?RegExp(regStr);

????????if(value?!=?null?&&?value?!=?""){

????????????if(!reg.test(value)){

????????????????$(this).next("span").html(tip);

????????????????isSubmit?=?false;

????????????????return?false;

????????????}

????????}

????});?

????return?isSubmit;

});

?

3.?使用離焦事件做友好的提示

$("input[reg2]").blur(function(){

????var?regStr?=?$(this).attr("reg2");

????var?value?=?$.trim($(this).val());

????var?tip?=?$(this).attr("tip");

????var?reg?=?new?RegExp(regStr);

????if(!reg.test(value)){

????????$(this).next("span").html(tip);

????}else{

????????$(this).next("span").html("");

????}

});

4.?表單的二次提交處理

l?鎖屏
l?鎖按鈕

②商品的查詢(xún)

商品查詢(xún)需要組合條件加分頁(yè)查詢(xún)
l?組合條件:品牌,審核狀態(tài),商品名稱(chēng),需要?jiǎng)討B(tài)sql

<select?id="queryItemByCondtion"?resultMap="BaseResultMap"?parameterType="map">

????select?*

????from?(select?a.*,?rownum?rm

????????from?(

????????????select?*

????????????????from?eb_item?ei

????????????????????<where>

????????????????????????<if?test="brandId?!=?null">

?????????????????? ???????ei.brand_id?=?#{brandId}??

?????????????????? ????</if>

?????????????????? ????<if?test="auditStatus?!=?null">

?????????????????? ???????and?ei.audit_status?=?#{auditStatus}??

?????????????????? ????</if>

?????????????????? ????<if?test="showStatus?!=?null">

?????????????????? ????????and?ei.show_status?=?#{showStatus}??

????????????????????????</if>

?????????????????? ????<if?test="itemName?!=?null">

?????????????????? ??? ????and?ei.item_name?like?'%${itemName}%'

?????????????????? ????</if>

????????????????????</where>

????????????????order?by?ei.item_id?desc)?a

?????????????<![CDATA[

?????????????where?rownum?<?#{endNum})?b

????????where?b.rm?>?#{startNum}

?????????????]]>

</select>

--查詢(xún)大于當(dāng)前頁(yè)首行號(hào),主要解決oraclerownum不支持大于號(hào)的問(wèn)題

select?*

from?(

????--查詢(xún)小于當(dāng)前最大行號(hào)的數(shù)據(jù)

????select?rownum?rm,a.*

????from?(

????????--第一個(gè)select查詢(xún)所有的業(yè)務(wù)數(shù)據(jù)

???????select?*?from?eb_item

???????)?a

????where?rownum?<?21)?b

where?b.rm?>?10

?

l?分頁(yè)查詢(xún)
1.?查詢(xún)結(jié)果集的sql,傳入開(kāi)始行數(shù)和結(jié)束的行數(shù)

select?*

from?(select?a.*,?rownum?rm

???? ?from?(

??????????...

??????? ?內(nèi)部sql

?????????...

??????)?a?where?rownum?<?#{endNum})?b

where?b.rm?>?#{startNum}

2.?使用內(nèi)部sql查詢(xún)結(jié)果集的總條數(shù)

3.?使用分頁(yè)工具類(lèi),創(chuàng)建page對(duì)象更換每次的數(shù)據(jù)總條數(shù)和當(dāng)前頁(yè)數(shù)和每頁(yè)的條數(shù),查詢(xún)出結(jié)果集后把結(jié)果集注入到page對(duì)象之中

public?class?Page?{

????int?totalCount?=?0;

????int?pageSize?=?10;

????int?currentPageNo?=?1;

????int?startNum?=?0;

????int?endNum?=?11;

????public?Page(int?totalCount,?int?pageSize,?int?currentPageNo)?{

????????super();

????????this.totalCount?=?totalCount;

????????this.pageSize?=?pageSize;

????????this.currentPageNo?=?currentPageNo;

????}

????public?int?getStartNum(){

????????return?(currentPageNo?-?1)?*?pageSize;

????}

?

????public?int?getEndNum(){

????????return?currentPageNo?*?pageSize?+?1;

????}

????public?int?getTotalPage(){

????????int?totalPage?=?totalCount/pageSize;

????????if(totalPage?==?0?||?totalCount%pageSize?!=?0){

????????????totalPage?++;

????????}

????????return?totalPage;

????}

????public?int?getNextPage(){

????????if(currentPageNo?>=?getTotalPage()){

????????????return?currentPageNo;

????????}else{

????????????return?currentPageNo?+?1;

????????}

????}

????public?int?getPrePage(){

????????if(currentPageNo?<=?1){

????????????return?currentPageNo;

????????}else{

????????????return?currentPageNo?-?1;

????????}

????}

????List<?>?list;

?

????public?List<?>?getList()?{

????????return?list;

????}

?

????public?void?setList(List<?>?list)?{

????????this.list?=?list;

????}

?

????public?int?getTotalCount()?{

????????return?totalCount;

????}

?

????public?void?setTotalCount(int?totalCount)?{

????????this.totalCount?=?totalCount;

????}

?

????public?int?getPageSize()?{

????????return?pageSize;

????}

?

????public?void?setPageSize(int?pageSize)?{

????????this.pageSize?=?pageSize;

????}

?

????public?int?getCurrentPageNo()?{

????????return?currentPageNo;

????}

?

????public?void?setCurrentPageNo(int?currentPageNo)?{

????????this.currentPageNo?=?currentPageNo;

????}

?

????public?void?setStartNum(int?startNum)?{

????????this.startNum?=?startNum;

????}

?

????public?void?setEndNum(int?endNum)?{

????????this.endNum?=?endNum;

????}

}

4.?制作前端樣式

var?currentPageNo?=?parseInt($("#currentPageNo").val());

var?totalCount?=?parseInt($("#totalCount").val());

var?totalPage?=?parseInt($("#totalPage").val());

$("#pagePiece").html(totalCount);

$("#pageTotal").html(currentPageNo+"/"+totalPage);

if(currentPageNo?<=?1){

????$("#previous").hide();

}else{

????$("#previous").show();

}

if(currentPageNo?>=?totalPage){

????$("#next").hide();

}else{

????$("#next").show();

}?

$("#next").click(function(){

????$("#pageNo").val(parseInt(currentPageNo)+1);

????$("#form1").submit();

});

$("#previous").click(function(){

????$("#pageNo").val(parseInt(currentPageNo)-1);

????$("#form1").submit();

});

?

Oracle??分頁(yè)sql的描述:
??1.最內(nèi)層的寫(xiě)查詢(xún)當(dāng)前表的全量即可
??2.對(duì)于oracle數(shù)據(jù)庫(kù)分頁(yè)需要依賴(lài)于rownum,但是rownum不支持大于號(hào),但是支持小于號(hào),可以rownum小于結(jié)束行號(hào)查詢(xún)出來(lái)一個(gè)結(jié)果集(在全量的外層套一個(gè)select,它的結(jié)果集需要把rownum作為結(jié)果返回)
??3.在第二步的結(jié)果集基礎(chǔ)上再做一次查詢(xún),查詢(xún)條件以第二步查詢(xún)出來(lái)的rownum的值作為條件大于開(kāi)始行號(hào)即可

③商品發(fā)布

Console和portal是分開(kāi)部署在兩臺(tái)服務(wù)器上,發(fā)布需要在console端去控制,但是生成的靜態(tài)化的文件要發(fā)布到portal的工程之中,所以發(fā)布的服務(wù)要在portal上,但是要在console中來(lái)調(diào)用,異構(gòu)之間的調(diào)用要使用webservice。
1.?采用cxf的webservice框架來(lái)整合spring
2.?在web.xml中來(lái)配置cxf的核心servlet

<servlet>

????<servlet-name>cxfServlet</servlet-name>

????<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>

</servlet>

<servlet-mapping>

????<servlet-name>cxfServlet</servlet-name>

????<url-pattern>/services/*</url-pattern>

</servlet-mapping>

3.?創(chuàng)建服務(wù)的接口和接口的實(shí)現(xiàn)類(lèi),注意接口上加上@WebService注解

4.?創(chuàng)建cxf的核心配置文件cxf-servlet.xml,配置帶有接口的webservice服務(wù)使用<jaxws:server>標(biāo)簽

<?xml?version="1.0"?encoding="UTF-8"?>

<beans?xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"?xmlns:jaxws="http://cxf.apache.org/jaxws"

xmlns:jaxrs="http://cxf.apache.org/jaxrs"?xmlns:cxf="http://cxf.apache.org/core"

xsi:schemaLocation="http://www.springframework.org/schema/beans?

??????????http://www.springframework.org/schema/beans/spring-beans.xsd

????????????http://cxf.apache.org/jaxrs?http://cxf.apache.org/schemas/jaxrs.xsd

????????????http://cxf.apache.org/jaxws?http://cxf.apache.org/schemas/jaxws.xsd

????????????http://cxf.apache.org/core?http://cxf.apache.org/schemas/core.xsd">

????<!--?引入CXF?Bean定義如下,早期的版本中使用?-->

????<import?resource="classpath:META-INF/cxf/cxf.xml"?/>

????<import?resource="classpath:META-INF/cxf/cxf-extension-soap.xml"?/>

????<import?resource="classpath:META-INF/cxf/cxf-servlet.xml"?/>

?

????<jaxws:server?id="publish"?address="/publish"?serviceClass="cn.itcast.ecps.ws.service.EbItemWSService">

????????<jaxws:serviceBean>

????????????<bean?class="cn.itcast.ecps.ws.service.impl.EbItemWSServiceImpl"></bean>

????????</jaxws:serviceBean>

????<!--?輸入輸出的攔截器?-->

?

????????<jaxws:inInterceptors>

????????????<bean?class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>

????????</jaxws:inInterceptors>

?

????????<jaxws:outInterceptors>

????????????<bean?class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>

????????</jaxws:outInterceptors>

????</jaxws:server>

</beans>

5.?修改cxf-servlet.xml的位置,在spring的listener中加載

<listener>

????<listener-class>

????????org.springframework.web.context.ContextLoaderListener

????</listener-class>

</listener>

<context-param>

????<param-name>contextConfigLocation</param-name>

????<param-value>

????????classpath*:beans.xml,classpath*:cxf-servlet.xml

????</param-value>

</context-param>?

6.?啟動(dòng)服務(wù)器發(fā)布webservice的服務(wù),使用wsdl2java生成客戶(hù)端的代碼

Wsdl2java?–d?.?–p?cn.itcast.ecps.ws.stub?http://.........wsdl?
7.?在客戶(hù)端調(diào)用。

④訂單管理模塊

1)?流程設(shè)計(jì)

?

2)?訂單整合activiti工作流

1.activiti流程和spring整合
創(chuàng)建activiti-context.xml文件

<beans?xmlns="http://www.springframework.org/schema/beans"

xmlns:context="http://www.springframework.org/schema/context"?xmlns:tx="http://www.springframework.org/schema/tx"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans?http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/context?http://www.springframework.org/schema/context/spring-context-2.5.xsd

http://www.springframework.org/schema/tx?http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">?

????

????<bean?id="processEngineConfiguration"?class="org.activiti.spring.SpringProcessEngineConfiguration">

????????<!--?數(shù)據(jù)源?-->

????????<property?name="dataSource"?ref="dataSource"?/>

????????<!--?配置事務(wù)管理器,統(tǒng)一事務(wù)?-->

????????<property?name="transactionManager"?ref="txManager"?/>

????????<!--?設(shè)置建表策略?-->

????????<property?name="databaseSchemaUpdate"?value="true"?/>

????</bean>

?

????<bean?id="processEngine"?class="org.activiti.spring.ProcessEngineFactoryBean">

????????<property?name="processEngineConfiguration"?ref="processEngineConfiguration"?/>

????</bean>

????<bean?id="repositoryService"?factory-bean="processEngine"?factory-method="getRepositoryService"?/>

????<bean?id="runtimeService"?factory-bean="processEngine"?factory-method="getRuntimeService"?/>

????<bean?id="taskService"?factory-bean="processEngine"?factory-method="getTaskService"?/>

????<bean?id="historyService"?factory-bean="processEngine"?factory-method="getHistoryService"?/>

</beans>

?

1.?畫(huà)流程圖
2.?創(chuàng)建流程服務(wù)類(lèi)

package?cn.itcast.service.impl;

import?java.io.File;

import?org.activiti.engine.RepositoryService;

import?org.activiti.engine.repository.DeploymentBuilder;

import?org.springframework.beans.factory.annotation.Autowired;

import?org.springframework.stereotype.Service;

import?cn.itcast.service.IWorkFlowService;

?

//@Service

public?class?WorkflowServiceImpl?implements?IWorkFlowService?{

?

????@Autowired

????RepositoryService?repositoryService;

?

????/*public?RepositoryService?getRepositoryService()?{

????????return?repositoryService;

????}

?

????public?void?setRepositoryService(RepositoryService?repositoryService)?{

????????this.repositoryService?=?repositoryService;

????}*/

?

????public?void?deployFlow()?{

????????//創(chuàng)建發(fā)布流程配置對(duì)象

????????DeploymentBuilder?builder?=?repositoryService.createDeployment();

????????//指定流程資源路徑

????????builder.addClasspathResource("activit-orderflow.bpmn").addClasspathResource("activit-orderflow.png");

????????builder.deploy();

????}

}

1.?部署流程

2.?查詢(xún)業(yè)務(wù)任務(wù)
3.?辦理任務(wù)

6.項(xiàng)目中哪些功能模塊涉及了大數(shù)據(jù)量訪問(wèn)?你是如何解決的?

系統(tǒng)前臺(tái)是互聯(lián)網(wǎng)上的用戶(hù)訪問(wèn)的,會(huì)有大量用戶(hù)來(lái)訪問(wèn)。
假定有1w個(gè)人打開(kāi)你的網(wǎng)站來(lái)訂商品,問(wèn)你如何解決并發(fā)問(wèn)題(可擴(kuò)展到任何高并發(fā)網(wǎng)站要考慮的并發(fā)讀寫(xiě)問(wèn)題)
問(wèn)題,1w個(gè)人來(lái)訪問(wèn),商品沒(méi)出去前要保證大家都能看到有商品,不可能一個(gè)人在看到商品的時(shí)候別人就不能看了。到底誰(shuí)能搶到,那得看這個(gè)人的運(yùn)氣(網(wǎng)絡(luò)快慢等)
其次考慮的問(wèn)題,并發(fā),1w個(gè)人同時(shí)點(diǎn)擊購(gòu)買(mǎi),到底誰(shuí)能成交?總共只有一張商品。

Update?eb_sku?t?sett.stock?=?t.stock??1?where?t.sku_id?=?#{skuId}?and?t.stock?>?0

Update?eb_sku?t?set?t.sale?=?t.sale?+1?where?t.sku_id?=?#{skuId}?

首先我們?nèi)菀紫氲胶筒l(fā)相關(guān)的幾個(gè)方案?:?鎖同步

? ??同步更多指的是應(yīng)用程序的層面,多個(gè)線程進(jìn)來(lái),只能一個(gè)一個(gè)的訪問(wèn),java中指的是syncrinized關(guān)鍵字。鎖也有2個(gè)層面,一個(gè)是java中談到的對(duì)象鎖,用于線程同步;另外一個(gè)層面是數(shù)據(jù)庫(kù)的鎖;如果是分布式的系統(tǒng),顯然只能利用數(shù)據(jù)庫(kù)端的鎖來(lái)實(shí)現(xiàn)。

? ??假定我們采用了同步機(jī)制或者數(shù)據(jù)庫(kù)物理鎖機(jī)制,如何保證1w個(gè)人還能同時(shí)看到有商品,顯然會(huì)犧牲性能,在高并發(fā)網(wǎng)站中是不可取的。使用hibernate后我們提出了另外一個(gè)概念:樂(lè)觀鎖(一定要用)、悲觀鎖(即傳統(tǒng)的物理鎖);采用樂(lè)觀鎖即可解決此問(wèn)題。樂(lè)觀鎖意思是不鎖定表的情況下,利用業(yè)務(wù)的控制來(lái)解決并發(fā)問(wèn)題,這樣即保證數(shù)據(jù)的并發(fā)可讀性又保證保存數(shù)據(jù)的排他性,保證性能的同時(shí)解決了并發(fā)帶來(lái)的臟數(shù)據(jù)問(wèn)題。
hibernate中如何實(shí)現(xiàn)樂(lè)觀鎖:

前提:在現(xiàn)有表當(dāng)中增加一個(gè)冗余字段,version版本號(hào),?long類(lèi)型

原理:

1)只有當(dāng)前版本號(hào)》=數(shù)據(jù)庫(kù)表版本號(hào),才能提交

2)提交成功后,版本號(hào)version?++

實(shí)現(xiàn)很簡(jiǎn)單:在ormapping增加一屬性-lock="version"即可,以下是樣例片段optimistic

<hibernate-mapping>

? ??<class?name="com.insigma.stock.ABC"?optimistic-lock="version"?table="T_Stock"?schema="STOCK">

</hibernate-mapping>

更新的時(shí)候給版本號(hào)字段加上?1,然后?UPDATE?會(huì)返回一個(gè)更新結(jié)果的行數(shù),通過(guò)這個(gè)行數(shù)去判斷。

Sku_id

sale

Version(樂(lè)觀鎖的標(biāo)志字段)

1

100

1

UPDATE?必須這樣寫(xiě):

Sale = 100

UPDATE EB_SKU u

???SET u.SALES = #SALES#,

???????u.version = u.version + 1

?WHERE u.SKU_ID = #SKUID#

???AND u.version = #version#

Update?user?t?set?t.address?=?#{address}?where?t.user_id?=?#{userId}

如果更新執(zhí)行返回的數(shù)量是?0?表示產(chǎn)生并發(fā)修改了,需要重新獲得最新的數(shù)據(jù)后再進(jìn)行更新操作。

HibernateJPA??ORM?框架或者實(shí)現(xiàn),是使用版本號(hào),再判斷?UPDATE?后返回的數(shù)值,如果這個(gè)值小于?1?時(shí)則拋出樂(lè)觀鎖并發(fā)修改異常。

?

解決大量用戶(hù)訪問(wèn)量問(wèn)題方案是集群部署,防止宕機(jī),負(fù)載均衡

1.我們采用4臺(tái)portal服務(wù)器來(lái)集群,使用2臺(tái)nginx代理服務(wù)器,

? ??1)反向代理,把4臺(tái)portal的服務(wù)(host)集中起來(lái),訪問(wèn)動(dòng)態(tài)鏈接代理地址(代理IP:192.168.1.100)時(shí)候會(huì)把請(qǐng)求轉(zhuǎn)發(fā)到4太portal上,如果訪問(wèn)靜態(tài)頁(yè)面直接訪問(wèn)nginx上的資源文件就可以了,靜態(tài)html中有ajax的請(qǐng)求由nginx的反向代理功能來(lái)轉(zhuǎn)發(fā)。

? ??2)部署靜態(tài)資源(html和圖片)

2.Rsync用作資源同步

? ??當(dāng)console上傳的圖片,由于rsync的部署,會(huì)指定一個(gè)具體的同步目錄(上傳圖片的目錄),一旦發(fā)現(xiàn)目錄中有文件就立刻同步到nginx上

3.Redis負(fù)責(zé)管理session和緩存搜索的數(shù)據(jù)

? ??管理session的原因:用于多臺(tái)服務(wù)器之間需要有相同的session,同享策略耗費(fèi)資源,所以采用redis來(lái)存儲(chǔ)session。緩存頻繁被搜索的數(shù)據(jù)。

7.在做這個(gè)項(xiàng)目的時(shí)候你碰到了哪些問(wèn)題?你是怎么解決的?

①.開(kāi)發(fā)webservice接口出現(xiàn)客戶(hù)端和服務(wù)端不同步,導(dǎo)致接口無(wú)法測(cè)試,產(chǎn)生的原因溝通不暢。

②.訂單提交時(shí)由于本地bug或者意外故障導(dǎo)致用戶(hù)錢(qián)支付了但是訂單不成功,采用對(duì)賬方式來(lái)解決。

③.上線的時(shí)候一定要把支付的假接口換成真接口。

④.項(xiàng)目中用到了曾經(jīng)沒(méi)有用過(guò)的技術(shù),解決方式:用自己的私人時(shí)間主動(dòng)學(xué)習(xí)

⑤.在開(kāi)發(fā)過(guò)程中與測(cè)試人員產(chǎn)生一些問(wèn)題,本地環(huán)境ok但是測(cè)試環(huán)境有問(wèn)題,環(huán)境的問(wèn)題產(chǎn)生的,瀏覽器環(huán)境差異,服務(wù)器之間的差異

⑥.系統(tǒng)運(yùn)行環(huán)境問(wèn)題,有些問(wèn)題是在開(kāi)發(fā)環(huán)境下OK,但是到了測(cè)試環(huán)境就問(wèn)題,比如說(shuō)系統(tǒng)文件路徑問(wèn)題、導(dǎo)出報(bào)表中的中文問(wèn)題(報(bào)表采用highcharts),需要在系統(tǒng)jdk中添加相應(yīng)的中文字體才能解決;

8.你做完這個(gè)項(xiàng)目后有什么收獲?

? ??首先,在數(shù)據(jù)庫(kù)方面,我現(xiàn)在是真正地體會(huì)到數(shù)據(jù)庫(kù)的設(shè)計(jì)真的是一個(gè)程序或軟件設(shè)計(jì)的重要和根基。因?yàn)閿?shù)據(jù)庫(kù)怎么設(shè)計(jì),直接影響到一個(gè)程序或軟件的功能的實(shí)現(xiàn)方法、性能和維護(hù)。由于我做的模塊是要對(duì)數(shù)據(jù)庫(kù)的數(shù)據(jù)進(jìn)行計(jì)算和操作的,所以我對(duì)數(shù)據(jù)庫(kù)的設(shè)計(jì)對(duì)程序的影響是深有體會(huì),就是因?yàn)槲覀兊臄?shù)據(jù)庫(kù)設(shè)計(jì)得不好,搞得我在對(duì)數(shù)據(jù)庫(kù)中的數(shù)據(jù)進(jìn)行獲取和計(jì)算利潤(rùn)、總金時(shí),非常困難,而且運(yùn)行效率低,時(shí)間和空間的復(fù)雜也高,而且維護(hù)起來(lái)很困難,過(guò)了不久,即使自己有注釋,但是也要認(rèn)真地看自己的代碼才能明白自己當(dāng)初的想法和做法。加上師兄的解說(shuō),讓我對(duì)數(shù)據(jù)庫(kù)的重要的認(rèn)識(shí)更深一層,數(shù)據(jù)庫(kù)的設(shè)計(jì)真的是重中之重。

?

? ??其次,就是分工的問(wèn)題。雖然這次的項(xiàng)目我們沒(méi)有在四人選出一個(gè)組長(zhǎng),但是,由于我跟其他人都比較熟,也有他們的號(hào)碼,然后我就像一個(gè)小組長(zhǎng)一樣,也是我對(duì)他們進(jìn)行了分工。俗話也說(shuō),分工合作,分好了工,才能合作。但是這次項(xiàng)目,我們的分工卻非常糟糕,我們?cè)诜止ぶ胺趾昧四K,每個(gè)模塊實(shí)現(xiàn)什么功能,每個(gè)人負(fù)責(zé)哪些模塊。本以為我們的分工是明確的,后來(lái)才發(fā)現(xiàn),我們的分工是那么的一踏糊涂,一些功能上緊密相連的模塊分給了兩個(gè)人來(lái)完成,使兩個(gè)人都感到迷惘,不知道自己要做什么,因?yàn)閮蓚€(gè)人做的東西差不多。我做的,他也在做,那我是否要繼續(xù)做下去?總是有這樣的疑問(wèn)。從而導(dǎo)致了重復(fù)工作,浪費(fèi)時(shí)間和精力,并打擊了隊(duì)員的激情,因?yàn)樽约盒列量嗫鄬?xiě)的代碼,最后可能沒(méi)有派上用場(chǎng)。我也知道,沒(méi)有一點(diǎn)經(jīng)驗(yàn)的我犯這樣的錯(cuò)是在所難免,我也不過(guò)多地怪責(zé)自己,吸取這次的教訓(xùn)就好。分工也是一門(mén)學(xué)問(wèn)。

?

? ??再者,就是命名規(guī)范的問(wèn)題??赡芪覀円郧岸际亲约阂粋€(gè)人在寫(xiě)代碼,寫(xiě)的代碼都是給自己看的,所以我們都沒(méi)有注意到這個(gè)問(wèn)題。就像師兄說(shuō)的那樣,我們的代碼看上去很上難看很不舒服,也不知道我們的變量是什么類(lèi)型的,也不知道是要來(lái)做什么的。但是我覺(jué)得我們這一組人的代碼都寫(xiě)得比較好看,每個(gè)人的代碼都有注釋和分隔,就是沒(méi)有一個(gè)統(tǒng)一的規(guī)范,每個(gè)人都人自己的一個(gè)命名規(guī)則和習(xí)慣,也不能見(jiàn)名知義。還有就是沒(méi)有定義好一些公共的部分,使每個(gè)人都有一個(gè)自己的“公共部分”,從而在拼起來(lái)時(shí),第一件事,就是改名字。而這些都應(yīng)該是在項(xiàng)目一開(kāi)始,還沒(méi)開(kāi)始寫(xiě)代碼時(shí)應(yīng)該做的。

?

? ??然后,我自己在計(jì)算時(shí),竟然太大意算錯(cuò)了利潤(rùn),這不能只一句我不小心就敷衍過(guò)去,也是我的責(zé)任,而且這也是我們的項(xiàng)目的核心部分,以后在做完一個(gè)模塊后,一定要測(cè)試多次,不能過(guò)于隨便地用一個(gè)數(shù)據(jù)測(cè)試一下,能成功就算了,要用可能出現(xiàn)的所有情況去測(cè)試程序,讓所有的代碼都有運(yùn)行過(guò)一次,確認(rèn)無(wú)誤。

?

? ??最后,也是我比較喜歡的東西,就是大家一起為了一個(gè)問(wèn)題去討論和去交流。因?yàn)槲矣X(jué)得,無(wú)論是誰(shuí),他能想的東西都是有限的,別人總會(huì)想到一些自己想不到的地方。跟他人討論和交流能知道別人的想法、了解別人是怎樣想一個(gè)問(wèn)題的,對(duì)于同樣的問(wèn)題自己又是怎樣想的,是別人的想法好,還是自己的想法好,好在什么地方。因?yàn)槲野l(fā)現(xiàn)問(wèn)題的能力比較欠缺,所以我也總是喜歡別人問(wèn)我問(wèn)題,也喜歡跟別人去討論一個(gè)問(wèn)題,因?yàn)樗麄儙臀野l(fā)現(xiàn)了我自己沒(méi)有發(fā)現(xiàn)的問(wèn)題。在這次項(xiàng)目中,我跟植榮的討論就最多了,很多時(shí)候都是不可開(kāi)交的那種,不過(guò)我覺(jué)得他總是能夠想到很多我想不到的東西,他想的東西也比我深入很多,雖然很多時(shí)候我們好像鬧得很僵,但是我們還是很要好的! 嘻嘻!而且在以后的學(xué)習(xí)和做項(xiàng)目的過(guò)程中,我們遇到的問(wèn)題可能會(huì)多很多,復(fù)雜很多,我們一個(gè)人也不能解決,或者是沒(méi)有想法,但是懂得與他人討論與交流就不怕這個(gè)問(wèn)題,總有人的想法會(huì)給我們帶來(lái)一片新天地。相信我能做得更好。

?

? ??還有就是做項(xiàng)目時(shí)要抓準(zhǔn)客戶(hù)的要求,不要自以為是,自己覺(jué)得這樣好,那樣好就把客戶(hù)的需求改變,項(xiàng)目就是項(xiàng)目,就要根據(jù)客戶(hù)的要求來(lái)完成。

9.你這個(gè)項(xiàng)目中使用什么構(gòu)建的?多模塊開(kāi)發(fā)是如何劃分的呢?為什么要這么做?

我們這個(gè)項(xiàng)目使用Maven進(jìn)行構(gòu)建,并使用了水平劃分,這樣劃分層次清晰,代碼重用性高,易于獨(dú)立維護(hù)。

①垂直劃分

?

②水平劃分

?

優(yōu)缺點(diǎn):

? ? 垂直:功能模塊明確,層次不夠清晰,代碼重用性差。

? ? 水平:層次清晰,代碼重用性高,獨(dú)立維護(hù)。

?

淘淘商城后臺(tái)管理系統(tǒng)采取水平劃分。

10.你覺(jué)得在文件上傳功能上面需要注意什么?

對(duì)上傳的文件做校驗(yàn)!

11.在你這個(gè)項(xiàng)目中,是如何設(shè)計(jì)商品規(guī)格的?

實(shí)現(xiàn)思路很重要!

12.在這個(gè)項(xiàng)目中你是如何實(shí)現(xiàn)跨系統(tǒng)調(diào)用的?

?

有兩種調(diào)用方式:
1、?Ajax,走前臺(tái)js,通過(guò)jsonp來(lái)跨域,關(guān)于jsonp請(qǐng)參考:http://www.cnblogs.com/yuzhongwusan/archive/2012/12/11/2812849.html

a)?效率

b)?帶寬

document.domain="taotao.com"
jsonp,部署子域名的情況?
需要在SpringMVC中擴(kuò)展MappingJackson2HttpMessageConverter,支持jsonp??缬騿?wèn)題,因?yàn)槲覀兪亲佑蛎L問(wèn)子系統(tǒng)接口的,采用jsonp解決;

2、?后臺(tái)轉(zhuǎn)發(fā)請(qǐng)求,走后臺(tái),通過(guò)httpclient來(lái)調(diào)。

a)?可以加邏輯(加緩存只能這條路走)

b)?安全,接口不在公網(wǎng)公開(kāi)

重點(diǎn)學(xué)習(xí)httpclient中的示例
掌握spring和Httpclient的集成

我們這個(gè)項(xiàng)目2種方式都使用到了。

13.你這個(gè)項(xiàng)目中CMS系統(tǒng)是如何設(shè)計(jì)的,簡(jiǎn)單的說(shuō)一下其設(shè)計(jì)思想?

隱藏在內(nèi)容管理系統(tǒng)(CMS)之后的基本思想是分離內(nèi)容的管理和設(shè)計(jì)。頁(yè)面設(shè)計(jì)存儲(chǔ)在模板里,而內(nèi)容存儲(chǔ)在數(shù)據(jù)庫(kù)或獨(dú)立的文件中。 當(dāng)一個(gè)用戶(hù)請(qǐng)求頁(yè)面時(shí),各部分聯(lián)合生成一個(gè)標(biāo)準(zhǔn)的HTML(標(biāo)準(zhǔn)通用標(biāo)記語(yǔ)言下的一個(gè)應(yīng)用)頁(yè)面。

內(nèi)容管理系統(tǒng)被分離成以下幾個(gè)層面:各個(gè)層面優(yōu)先考慮的需求不同

? ??1,后臺(tái)業(yè)務(wù)子系統(tǒng)管理(管理優(yōu)先:內(nèi)容管理):新聞錄入系統(tǒng),BBS論壇子系統(tǒng),全文檢索子系統(tǒng)等,針對(duì)不同系統(tǒng)的方便管理者的內(nèi)容錄入:所見(jiàn)即所得的編輯管理界面等,清晰的業(yè)務(wù)邏輯:各種子系統(tǒng)的權(quán)限控制機(jī)制等;

? ??2,Portal系統(tǒng)(表現(xiàn)優(yōu)先:模板管理):大部分最終的輸出頁(yè)面:網(wǎng)站首頁(yè),子頻道/專(zhuān)題頁(yè),新聞詳情頁(yè)一般就是各種后臺(tái)子系統(tǒng)模塊的各種組合,這種發(fā)布組合邏輯是非常豐富的,Portal系統(tǒng)就是負(fù)責(zé)以上這些后臺(tái)子系統(tǒng)的組合表現(xiàn)管理;

? ??3,前臺(tái)發(fā)布(效率優(yōu)先:發(fā)布管理):面向最終用戶(hù)的緩存發(fā)布,和搜索引擎spider的URL設(shè)計(jì)等……

? ??內(nèi)容管理和表現(xiàn)的分離:很多成套的CMS系統(tǒng)沒(méi)有把后臺(tái)各種子系統(tǒng)和Portal分離開(kāi)設(shè)計(jì),以至于在Portal層的模板表現(xiàn)管理和新聞子系統(tǒng)的內(nèi)容管理邏輯混合在一起,甚至和BBS等子系統(tǒng)的管理都耦合的非常高,整個(gè)系統(tǒng)會(huì)顯得非常龐雜。而且這樣的系統(tǒng)各個(gè)子系統(tǒng)捆綁的比較死,如果后臺(tái)的模塊很難改變。但是如果把后臺(tái)各種子系統(tǒng)內(nèi)容管理邏輯和前臺(tái)的表現(xiàn)/發(fā)布分離后,Portal和后臺(tái)各個(gè)子系統(tǒng)之間只是數(shù)據(jù)傳遞的關(guān)系:Portal只決定后臺(tái)各個(gè)子系統(tǒng)數(shù)據(jù)的取舍和表現(xiàn),而后臺(tái)的各個(gè)子系統(tǒng)也都非常容易插拔。

? ??內(nèi)容管理和數(shù)據(jù)分發(fā)的分離:需要要Portal系統(tǒng)設(shè)計(jì)的時(shí)候注意可緩存性(Cache Friendly)性設(shè)計(jì):CMS后臺(tái)管理和發(fā)布機(jī)制,本身不要過(guò)多考慮"效率"問(wèn)題,只要最終頁(yè)面輸出設(shè)計(jì)的比較Cacheable,效率問(wèn)題可通過(guò)更前端專(zhuān)門(mén)的緩存服務(wù)器解決。

? ??此外,就是除了面向最終瀏覽器用戶(hù)外,還要注意面向搜索引擎友好(Search engine Friendly)的URL設(shè)計(jì):通過(guò) URL REWRITE轉(zhuǎn)向或基于PATH_INFO的參數(shù)解析使得動(dòng)態(tài)網(wǎng)頁(yè)在鏈接(URI)形式上更像靜態(tài)的目錄結(jié)構(gòu),方便網(wǎng)站內(nèi)容被搜索引擎收錄;

14.在這個(gè)項(xiàng)目中,你們主要使用什么樣的數(shù)據(jù)格式來(lái)進(jìn)行數(shù)據(jù)的傳輸?shù)?#xff1f;你對(duì)JSON了解么?能說(shuō)說(shuō)JSON對(duì)象如何轉(zhuǎn)換成Java對(duì)象的?

?

15.單點(diǎn)系統(tǒng)的設(shè)計(jì)思想你了解嗎?他在系統(tǒng)架構(gòu)中的作用是什么?位置如何?

單點(diǎn)登錄SSO(Single Sign On)說(shuō)得簡(jiǎn)單點(diǎn)就是在一個(gè)多系統(tǒng)共存的環(huán)境下,用戶(hù)在一處登錄后,就不用在其他系統(tǒng)中登錄,也就是用戶(hù)的一次登錄能得到其他所有系統(tǒng)的信任。單點(diǎn)登錄在大型網(wǎng)站里使用得非常頻繁,例如像阿里巴巴這樣的網(wǎng)站,在網(wǎng)站的背后是成百上千的子系統(tǒng),用戶(hù)一次操作或交易可能涉及到幾十個(gè)子系統(tǒng)的協(xié)作,如果每個(gè)子系統(tǒng)都需要用戶(hù)認(rèn)證,不僅用戶(hù)會(huì)瘋掉,各子系統(tǒng)也會(huì)為這種重復(fù)認(rèn)證授權(quán)的邏輯搞瘋掉。實(shí)現(xiàn)單點(diǎn)登錄說(shuō)到底就是要解決如何產(chǎn)生和存儲(chǔ)那個(gè)信任,再就是其他系統(tǒng)如何驗(yàn)證這個(gè)信任的有效性,因此要點(diǎn)也就以下幾個(gè):

存儲(chǔ)信任

驗(yàn)證信任

只要解決了以上的問(wèn)題,達(dá)到了開(kāi)頭講得效果就可以說(shuō)是SSO。最簡(jiǎn)單實(shí)現(xiàn)SSO的方法就是用Cookie,實(shí)現(xiàn)流程如下所示:

不難發(fā)現(xiàn)以上的方案是把信任存儲(chǔ)在客戶(hù)端的Cookie里,這種方法雖然實(shí)現(xiàn)方便但立馬會(huì)讓人質(zhì)疑兩個(gè)問(wèn)題:

Cookie不安全

不能跨域免登

對(duì)于第一個(gè)問(wèn)題一般都是通過(guò)加密Cookie來(lái)處理,第二個(gè)問(wèn)題是硬傷,其實(shí)這種方案的思路的就是要把這個(gè)信任關(guān)系存儲(chǔ)在客戶(hù)端,要實(shí)現(xiàn)這個(gè)也不一定只能用Cookie,用flash也能解決,flash的Shared Object API就提供了存儲(chǔ)能力。

一般說(shuō)來(lái),大型系統(tǒng)會(huì)采取在服務(wù)端存儲(chǔ)信任關(guān)系的做法,實(shí)現(xiàn)流程如下所示:

以上方案就是要把信任關(guān)系存儲(chǔ)在單獨(dú)的SSO系統(tǒng)(暫且這么稱(chēng)呼它)里,說(shuō)起來(lái)只是簡(jiǎn)單地從客戶(hù)端移到了服務(wù)端,但其中幾個(gè)問(wèn)題需要重點(diǎn)解決:

如何高效存儲(chǔ)大量臨時(shí)性的信任數(shù)據(jù)

如何防止信息傳遞過(guò)程被篡改

如何讓SSO系統(tǒng)信任登錄系統(tǒng)和免登系統(tǒng)

對(duì)于第一個(gè)問(wèn)題,一般可以采用類(lèi)似與memcached的分布式緩存的方案,既能提供可擴(kuò)展數(shù)據(jù)量的機(jī)制,也能提供高效訪問(wèn)。對(duì)于第二個(gè)問(wèn)題,一般采取數(shù)字簽名的方法,要么通過(guò)數(shù)字證書(shū)簽名,要么通過(guò)像md5的方式,這就需要SSO系統(tǒng)返回免登URL的時(shí)候?qū)π栩?yàn)證的參數(shù)進(jìn)行md5加密,并帶上token一起返回,最后需免登的系統(tǒng)進(jìn)行驗(yàn)證信任關(guān)系的時(shí)候,需把這個(gè)token傳給SSO系統(tǒng),SSO系統(tǒng)通過(guò)對(duì)token的驗(yàn)證就可以辨別信息是否被改過(guò)。對(duì)于最后一個(gè)問(wèn)題,可以通過(guò)白名單來(lái)處理,說(shuō)簡(jiǎn)單點(diǎn)只有在白名單上的系統(tǒng)才能請(qǐng)求生產(chǎn)信任關(guān)系,同理只有在白名單上的系統(tǒng)才能被免登錄。

16.你們這個(gè)項(xiàng)目中訂單ID是怎么生成的?我們公司最近打算做一個(gè)電商項(xiàng)目,如果讓你設(shè)計(jì)這塊,你會(huì)考慮哪些問(wèn)題?

生成訂單ID的目的是為了使訂單不重復(fù),本系統(tǒng)訂單ID生成規(guī)則:

? ??用戶(hù)ID+當(dāng)前系統(tǒng)的時(shí)間戳

String?orderId?=?order.getUserId()?+?""?+?System.currentTimeMillis();

設(shè)計(jì)的時(shí)候我會(huì)考慮:

訂單ID不能重復(fù)

訂單ID盡可能的短(占用存儲(chǔ)空間少,實(shí)際使用方便,客服相關(guān))

訂單ID要求是全數(shù)字(客服)

17.各個(gè)服務(wù)器的時(shí)間不統(tǒng)一怎么辦?

在各個(gè)服務(wù)器上做時(shí)間的統(tǒng)一;(運(yùn)維)

18.在問(wèn)題17的基礎(chǔ)上,可能存在毫秒級(jí)的偏差情況,怎么辦?

修改訂單生成規(guī)則:
? ??用戶(hù)ID+當(dāng)前系統(tǒng)的時(shí)間戳+隨機(jī)數(shù)(3~4位)?問(wèn)題:太長(zhǎng)??把時(shí)間戳中的2014中的20拿掉;

19.你們線上部署時(shí)什么樣的,能畫(huà)一下嗎?

20.多臺(tái)tomcat之間的session是怎么同步的?

不用session,我們使用單點(diǎn)登陸,使用redis,存在redis,生成,A同步到B,B同步到C。

21.如何解決并發(fā)問(wèn)題的?

集群,負(fù)載均衡,nginx(主備,一般主在工作,備閑置;資源浪費(fèi)),lvs(在2個(gè)Nginx前做一個(gè)攔截,接收后進(jìn)行分工)。有問(wèn)題,如果nginx掛掉,整個(gè)系統(tǒng)就掛了。可以主備解決,可以前面搭一個(gè)lvs。這塊不是你做的,但是你知道怎么解決(非常復(fù)雜,但是必須了解。針對(duì)具體的情況去具體對(duì)待,CPU,內(nèi)存,不要一刀切。)

22.你們生產(chǎn)環(huán)境的服務(wù)器有多少臺(tái)?

面試前要數(shù)好,一般是十幾到二十臺(tái)。(用在哪里?這是重點(diǎn))

Nginx至少2臺(tái)

Tomcat至少3臺(tái)以上

數(shù)據(jù)庫(kù)至少2臺(tái)

Redis至少一臺(tái)

可參考17問(wèn)圖

23.數(shù)據(jù)備份是怎么做的?有沒(méi)有做讀寫(xiě)分離?

主從(一主多從,主要是備份主),每天備份,備份的文件不要放到數(shù)據(jù)庫(kù)服務(wù)器上,可以FTP。要檢查有效否。讀寫(xiě)分離自己查一下,分庫(kù)分表做過(guò)。

24.你們服務(wù)器不止一臺(tái)吧,那么你們的session是怎么同步的?

此問(wèn)題與18相同,如果購(gòu)物車(chē)使用session做的話,此問(wèn)題極易被問(wèn)到。

Session放到redis里面,使用單點(diǎn)登錄系統(tǒng)。購(gòu)物車(chē)設(shè)計(jì)思路:未登錄(先寫(xiě)到cookie中,登錄后寫(xiě)到數(shù)據(jù)庫(kù)表中);已登錄(直接寫(xiě)到數(shù)據(jù)庫(kù),而不會(huì)寫(xiě)到cookie)實(shí)際項(xiàng)目是不使用session的,使用redis集中處理處理數(shù)據(jù),取代session的作用,應(yīng)用在單點(diǎn)登錄、購(gòu)物車(chē)等。

25.你們使用什么做支付的?如果使用易寶做支付,請(qǐng)求超時(shí)了怎么處理?

①重試,一般三次,每次重試都要停頓一會(huì),比如,以第一次停頓1秒,第二次停頓2秒,第三次停頓3秒;
②給訂單標(biāo)識(shí)付款異常狀態(tài),并且發(fā)出警告(郵件、短信)給相關(guān)人員。

③寫(xiě)個(gè)定時(shí)任務(wù),定時(shí)處理異常狀態(tài)的訂單。

26.你剛才不是說(shuō)付款成功后易寶會(huì)有數(shù)據(jù)返回嗎?如果付款后易寶沒(méi)有返回,或者返回超時(shí)了,但是錢(qián)又已經(jīng)扣了,你怎么辦?

①我們請(qǐng)求了易寶,但是沒(méi)有接受到響應(yīng),我們就認(rèn)為該訂單沒(méi)有支付成功,并且將訂單標(biāo)識(shí)為異常狀態(tài);
②使用定時(shí)任務(wù)處理;

③做一個(gè)對(duì)賬的任務(wù),實(shí)時(shí)處理異常狀態(tài)的訂單。

27.你們?cè)趺醋鐾丝罟δ艿?#xff0c;要多長(zhǎng)時(shí)間才能把錢(qián)退回給用戶(hù)?

用戶(hù)申請(qǐng)退款后,經(jīng)過(guò)客服審核通過(guò)會(huì)將退款請(qǐng)求提交到易寶,具體到賬時(shí)間要看易寶的處理。

28.你前臺(tái)portal采用4臺(tái)服務(wù)器集群部署?那你數(shù)據(jù)庫(kù)有幾臺(tái)服務(wù)器?如果前臺(tái)高并發(fā)訪問(wèn)性能提上去了,那數(shù)據(jù)庫(kù)會(huì)不會(huì)造成一個(gè)瓶頸,這一塊你是怎么處理的?

?

29.你購(gòu)物車(chē)存cookie里邊可以實(shí)現(xiàn)不登錄就可以使用購(gòu)物車(chē),那么我現(xiàn)在沒(méi)有登錄把商品存購(gòu)物車(chē)了,然后登錄了, 然后我換臺(tái)電腦并且登錄了還能不能看見(jiàn)我購(gòu)物車(chē)的信息?如果看不到怎么做到cookie同步,就是在另外一臺(tái)電腦上可以看到購(gòu)物車(chē)信息

更換電腦,必須登錄才能看到之前購(gòu)物車(chē)的商品。

跨域cookie同步方案:

場(chǎng)景:有時(shí)一個(gè)公司可能有多個(gè)不同域名的網(wǎng)站,比如sina.com和weibo.cn,比如taobao.com和tmall.com。

這些網(wǎng)站背后很多是同一套會(huì)員體系。由于http協(xié)議規(guī)定cookie是跟著域名走的,這時(shí)就需要在不同的域名下同步登陸狀態(tài),避免出現(xiàn)用戶(hù)體驗(yàn)上出現(xiàn)需要二次登陸驗(yàn)證的情況。

假設(shè)下面這樣一個(gè)場(chǎng)景:

? ??用戶(hù)在 bbb.com上已經(jīng)登陸,現(xiàn)在要去aaa.com上玩,在aaa.com域名下暫未登錄。需要訪問(wèn)的aaa.com/resource.html資源需 要登錄才能訪問(wèn)。兩個(gè)網(wǎng)站是同一套會(huì)員體系,同一個(gè)公司的。這是要讓用戶(hù)體驗(yàn)上做到用戶(hù)在aaa.com上玩也能識(shí)別出登錄狀態(tài)。

以上面場(chǎng)景為例,下面畫(huà)了個(gè)實(shí)現(xiàn)跨域同步簡(jiǎn)單流程圖:

解釋如下:

第一步 :用戶(hù)向aaa.com發(fā)起get請(qǐng)求,獲取resource.html資源,aaa.com發(fā)現(xiàn)用戶(hù)未登錄,返回302狀態(tài)和外部重定向url:

Java代碼 ?收藏代碼

j.bbb.com?target=www.aaa.com/resource.html ?

注意j.bbb.com子域名上部署的應(yīng)用可以認(rèn)為是專(zhuān)門(mén)用了跨域同步。

?

第二步 :用戶(hù)根據(jù)重定向url,訪問(wèn)j.bbb.com?target=www.aaa.com/resource.html,由于在bbb.com上已經(jīng)登 錄,所以bbb.com上能拿到從client端傳遞過(guò)來(lái)cookie信息。子域j.bbb.com上的應(yīng)用負(fù)責(zé)將cookie讀取出來(lái),并作為參數(shù)再次 重定向到

Java代碼 ?收藏代碼?

p.aaa.com?tartet=www.aaa.com/resource.html&sessionid=xxx&loginId=xxx&……??

第三步 :用戶(hù)根據(jù)第二步重定向url,訪問(wèn)p.aaa.com。p.aaa.com子域名上的應(yīng)用專(zhuān)門(mén)負(fù)責(zé)根據(jù)請(qǐng)求參數(shù)里的參數(shù)對(duì),往aaa.com域?qū)懭隿ookie,并重定向到用戶(hù)第一步請(qǐng)求的url。

第四步 :經(jīng)過(guò)前三步,已經(jīng)完成了再aaa.com域名下同步bbb.com的登錄狀態(tài),用戶(hù)再次請(qǐng)求aaa.com/resource.html,這是就能成功訪問(wèn)了。

30.點(diǎn)一個(gè)鏈接訪問(wèn)到一個(gè)頁(yè)面,這個(gè)頁(yè)面上既有靜態(tài)數(shù)據(jù),又有動(dòng)態(tài)數(shù)據(jù)(需要查數(shù)據(jù)庫(kù)的),打開(kāi)這個(gè)頁(yè)面的時(shí)候就是很慢但是也能打開(kāi)。怎么解決這個(gè)問(wèn)題,怎么優(yōu)化?

如果要靜態(tài)頁(yè)面的話 那就得用freemarker或者通過(guò)ajax異步,通過(guò)js操作異步刷新表單,通過(guò)js對(duì)返回結(jié)果組裝成html。

緩存、動(dòng)態(tài)頁(yè)面靜態(tài)化:

所謂緩存, 是指將那些經(jīng)常重復(fù)的操作結(jié)果暫時(shí)存放起來(lái), 在以后的執(zhí)行過(guò)程中, 只要使用前面的暫存結(jié)果即可.

那么在我們開(kāi)發(fā)Web網(wǎng)站的過(guò)程中, 到底有多少工作可以采用用緩存呢? 或者說(shuō), 我們可以在哪些地方使用緩存呢? 見(jiàn)下圖: 下圖是客戶(hù)端瀏覽器和Web服務(wù)器之間的一次完整的通信過(guò)程, 紅色圓圈標(biāo)示了可以采用緩存的地方.

首先, 最好的情況是客戶(hù)端不發(fā)送任何請(qǐng)求直接就能獲得數(shù)據(jù), 這種情況下, 用于緩存的數(shù)據(jù)保存在客戶(hù)端瀏覽器的緩存中.

其次, 在具有代理服務(wù)器的網(wǎng)絡(luò)環(huán)境中, 代理服務(wù)器可以針對(duì)那些經(jīng)常訪問(wèn)的網(wǎng)頁(yè)制作緩存, 當(dāng)局域網(wǎng)中第一臺(tái)主機(jī)請(qǐng)求了某個(gè)網(wǎng)頁(yè)并返回結(jié)果后, 局域網(wǎng)中的第二臺(tái)主機(jī)再請(qǐng)求同一個(gè)網(wǎng)頁(yè), 這時(shí)代理服務(wù)器會(huì)直接返回上一次緩存的結(jié)果, 并不會(huì)向網(wǎng)絡(luò)中的IIS服務(wù)器發(fā)送請(qǐng)求, 例如: 現(xiàn)在的連接電信和網(wǎng)通線路的加速器等. 但是代理服務(wù)器通常有自己專(zhuān)門(mén)的管理軟件和管理系統(tǒng), 作為網(wǎng)站開(kāi)發(fā)人員對(duì)代理服務(wù)器的控制能力有限.

再次, 前面也說(shuō)過(guò), 當(dāng)用戶(hù)將請(qǐng)求地址發(fā)送到IIS服務(wù)器時(shí), IIS服務(wù)器會(huì)根據(jù)請(qǐng)求地址選擇不同的行為, 如: 對(duì)于*.aspx頁(yè)面會(huì)走應(yīng)用程序管道, 而對(duì)*.html、*.jpg等資源會(huì)直接返回資源, 那么我們可以把那些頻繁訪問(wèn)的頁(yè)面做成*.html文件, 這樣用戶(hù)請(qǐng)求*.html, 將不用再走應(yīng)用程序管道, 因此會(huì)提升效率. 例如: 網(wǎng)站首頁(yè)、或某些突發(fā)新聞或突發(fā)事件等, 可以考慮做成靜態(tài)網(wǎng)頁(yè). 就拿”天氣預(yù)報(bào)的發(fā)布頁(yè)面”打比方: 天氣預(yù)報(bào)的發(fā)布頁(yè)面的訪問(wèn)用戶(hù)非常多, 我們可以考慮將發(fā)布頁(yè)做成靜態(tài)的*.html網(wǎng)頁(yè), 之后在整個(gè)網(wǎng)站程序啟動(dòng)時(shí), 在Gboabl.asax的Application_Start事件處理器中, 創(chuàng)建子線程以實(shí)現(xiàn)每3個(gè)小時(shí)重新獲取數(shù)據(jù)生成新的天氣發(fā)布頁(yè)面內(nèi)容.

之后的asp.net的處理流程, 作為程序員我們是無(wú)法干涉的. 直到啟動(dòng)HttpApplication管道后, 我們才可以通過(guò)Global.asax或IHttpModule來(lái)控制請(qǐng)求處理過(guò)程, 在應(yīng)用程序管道中適合做整頁(yè)或用戶(hù)控件的緩存. 如: 緩存熱門(mén)頁(yè)面, 我們可以自動(dòng)緩存整個(gè)網(wǎng)站中訪問(wèn)量超過(guò)一定數(shù)值(閥值)的頁(yè)面, 其中為了減小IO操作, 將緩存的頁(yè)面放在內(nèi)容中.

31.如果用戶(hù)一直向購(gòu)物車(chē)添加商品怎么辦?并且他添加一次你查詢(xún)一次數(shù)據(jù)庫(kù)?互聯(lián)網(wǎng)上用戶(hù)那么多,這樣會(huì)對(duì)數(shù)據(jù)庫(kù)造成很大壓力你怎么辦?

在回答這個(gè)問(wèn)題前,請(qǐng)想好自己的項(xiàng)目是否真的需要使用購(gòu)物車(chē)?(SKU數(shù)少,商品結(jié)構(gòu)單一等就不需要使用購(gòu)物車(chē)了)

購(gòu)物車(chē)的設(shè)計(jì)方案:

購(gòu)物車(chē)的實(shí)現(xiàn)不存在哪種方式更好,完全是根據(jù)公司和項(xiàng)目架構(gòu)相關(guān)的,類(lèi)似蘇寧使用的是數(shù)據(jù)庫(kù)存儲(chǔ),但是國(guó)美使用的就是Session,不同的軟件架構(gòu)和不同的業(yè)務(wù)需求對(duì)應(yīng)的購(gòu)物車(chē)存儲(chǔ)也是不一樣的

用數(shù)據(jù)庫(kù)存你得給數(shù)據(jù)庫(kù)造成多大的負(fù)擔(dān)啊, 而且對(duì)于購(gòu)物車(chē), 這種需要實(shí)時(shí)操作的東西, 數(shù)據(jù)庫(kù)的訪問(wèn)量一大了, 就容易出現(xiàn)并發(fā)錯(cuò)誤, 或者直接崩潰.

用Session確實(shí)效率很高, 而且會(huì)話是針對(duì)各個(gè)連接的, 所以便于管理, 但是用Session也不是完美的, 因?yàn)镾ession是有有效期的, 根據(jù)服務(wù)器的設(shè)置不同而不一樣長(zhǎng), 如果你在購(gòu)物的過(guò)程中Session超時(shí)了, 那么購(gòu)物車(chē)中的東西就會(huì)全沒(méi)了.不知道你看過(guò)當(dāng)當(dāng)網(wǎng)的購(gòu)物車(chē)沒(méi)有, 當(dāng)你下線之后, 再次上線, 購(gòu)物車(chē)中的東西還是存在的, 這對(duì)于用戶(hù)來(lái)說(shuō)非常方便.所以如果你的服務(wù)器夠強(qiáng)的話, 你完全可以用一個(gè)靜態(tài)變量來(lái)保存所有用戶(hù)的購(gòu)物車(chē), 比如用一個(gè)靜態(tài)的Map, 以IP作為Key,區(qū)分不同用戶(hù)的購(gòu)物車(chē), 這樣就可以使用戶(hù)在下線的情況下也可以保存購(gòu)物車(chē)中的內(nèi)容.這種方法實(shí)現(xiàn)過(guò), 只是沒(méi)有用大量的并發(fā)訪問(wèn)測(cè)試其穩(wěn)定性, 但是一定是可行的。?

采用存儲(chǔ)過(guò)程將購(gòu)物車(chē)存儲(chǔ)于數(shù)據(jù)庫(kù)相應(yīng)表的方式,優(yōu)點(diǎn):數(shù)據(jù)穩(wěn)定,不易丟失。缺點(diǎn):效率低,增加數(shù)據(jù)庫(kù)服務(wù)器負(fù)擔(dān)。變量 + Datatable保存于客戶(hù)端,優(yōu)點(diǎn):效率高,減輕數(shù)據(jù)庫(kù)服務(wù)器負(fù)擔(dān)。缺點(diǎn):Session保存的變量容易丟失,但是一般情況下不會(huì)造成影響。變量 + 購(gòu)物車(chē)對(duì)象保存于客戶(hù)端,這種方式以面向?qū)ο鬄橹笇?dǎo)思想,邏輯上具有一定的復(fù)雜性。優(yōu)點(diǎn):效率高,減輕數(shù)據(jù)庫(kù)服務(wù)器負(fù)擔(dān),使用便捷。缺點(diǎn):Session保存的變量容易丟失,但是一般情況下不會(huì)造成影響

購(gòu)物車(chē)的核心功能

購(gòu)物車(chē)數(shù)據(jù)存數(shù)據(jù)庫(kù)好處有很多,可以分析購(gòu)買(mǎi)行為,可以為客戶(hù)保存購(gòu)買(mǎi)信息(不會(huì)因?yàn)闉g覽器關(guān)閉而丟失)等,我的這個(gè)項(xiàng)目的購(gòu)物車(chē)使用的就是將購(gòu)物車(chē)數(shù)據(jù)存數(shù)據(jù)庫(kù)中,未登錄時(shí)可以加20個(gè)商品,登錄后可以加50個(gè)。

32.做促銷(xiāo)時(shí),商品詳情頁(yè)面的靜態(tài)頁(yè)面如何處理價(jià)格問(wèn)題。

京東商品詳情頁(yè)雖然僅是單個(gè)頁(yè)面,但是其數(shù)據(jù)聚合源是非常多的,除了一些實(shí)時(shí)性要求比較高的如價(jià)格、庫(kù)存、服務(wù)支持等通過(guò)AJAX異步加載加載之外,其他的數(shù)據(jù)都是在后端做數(shù)據(jù)聚合然后拼裝網(wǎng)頁(yè)模板的。整個(gè)京東有數(shù)億商品,如果每次動(dòng)態(tài)獲取如上內(nèi)容進(jìn)行模板拼裝,數(shù)據(jù)來(lái)源之多足以造成性能無(wú)法滿足要求;最初的解決方案是生成靜態(tài)頁(yè),但是靜態(tài)頁(yè)的最大的問(wèn)題:

1、無(wú)法迅速響應(yīng)頁(yè)面需求變更;

2、很難做多版本線上對(duì)比測(cè)試。如上兩個(gè)因素足以制約商品頁(yè)的多樣化發(fā)展,因此靜態(tài)化技術(shù)不是很好的方案。

?

數(shù)據(jù)主要分為四種:商品頁(yè)基本信息、商品介紹(異步加載)、其他信息(分類(lèi)、品牌、店鋪等)、其他需要實(shí)時(shí)展示的數(shù)據(jù)(價(jià)格、庫(kù)存等)。而其他信息如分類(lèi)、品牌、店鋪是非常少的,完全可以放到一個(gè)占用內(nèi)存很小的Redis中存儲(chǔ);而商品基本信息我們可以借鑒靜態(tài)化技術(shù)將數(shù)據(jù)做聚合存儲(chǔ),這樣的好處是數(shù)據(jù)是原子的,而模板是隨時(shí)可變的,吸收了靜態(tài)頁(yè)聚合的優(yōu)點(diǎn),彌補(bǔ)了靜態(tài)頁(yè)的多版本缺點(diǎn);另外一個(gè)非常嚴(yán)重的問(wèn)題就是嚴(yán)重依賴(lài)這些相關(guān)系統(tǒng),如果它們掛了或響應(yīng)慢則商品頁(yè)就掛了或響應(yīng)慢;商品介紹我們也通過(guò)AJAX技術(shù)惰性加載(因?yàn)槭堑诙?#xff0c;只有當(dāng)用戶(hù)滾動(dòng)鼠標(biāo)到該屏?xí)r才顯示);而實(shí)時(shí)展示數(shù)據(jù)通過(guò)AJAX技術(shù)做異步加載

?

1、接收商品變更消息,做商品基本信息的聚合,即從多個(gè)數(shù)據(jù)源獲取商品相關(guān)信息如圖片列表、顏色尺碼、規(guī)格參數(shù)、擴(kuò)展屬性等等,聚合為一個(gè)大的JSON數(shù)據(jù)做成數(shù)據(jù)閉環(huán),以key-value存儲(chǔ);因?yàn)槭情]環(huán),即使依賴(lài)的系統(tǒng)掛了我們商品頁(yè)還是能繼續(xù)服務(wù)的,對(duì)商品頁(yè)不會(huì)造成任何影響;

2、接收商品介紹變更消息,存儲(chǔ)商品介紹信息;

3、介紹其他信息變更消息,存儲(chǔ)其他信息

技術(shù)選型

MQ可以使用如Apache ActiveMQ;

Worker/動(dòng)態(tài)服務(wù)可以通過(guò)如Java技術(shù)實(shí)現(xiàn);

RPC可以選擇如alibaba Dubbo;

KV持久化存儲(chǔ)可以選擇SSDB(如果使用SSD盤(pán)則可以選擇SSDB+RocksDB引擎)或者ARDB(LMDB引擎版);

緩存使用Redis;

SSDB/Redis分片使用如Twemproxy,這樣不管使用Java還是Nginx+Lua,它們都不關(guān)心分片邏輯;

前端模板拼裝使用Nginx+Lua;

數(shù)據(jù)集群數(shù)據(jù)存儲(chǔ)的機(jī)器可以采用RAID技術(shù)或者主從模式防止單點(diǎn)故障;

因?yàn)閿?shù)據(jù)變更不頻繁,可以考慮SSD替代機(jī)械硬盤(pán)。

?

核心流程

1、首先我們監(jiān)聽(tīng)商品數(shù)據(jù)變更消息;

2、接收到消息后,數(shù)據(jù)聚合Worker通過(guò)RPC調(diào)用相關(guān)系統(tǒng)獲取所有要展示的數(shù)據(jù),此處獲取數(shù)據(jù)的來(lái)源可能非常多而且響應(yīng)速度完全受制于這些系統(tǒng),可能耗時(shí)幾百毫秒甚至上秒的時(shí)間;

3、將數(shù)據(jù)聚合為JSON串存儲(chǔ)到相關(guān)數(shù)據(jù)集群;

4、前端Nginx通過(guò)Lua獲取相關(guān)集群的數(shù)據(jù)進(jìn)行展示;商品頁(yè)需要獲取基本信息+其他信息進(jìn)行模板拼裝,即拼裝模板僅需要兩次調(diào)用(另外因?yàn)槠渌畔?shù)據(jù)量少且對(duì)一致性要求不高,因此我們完全可以緩存到Nginx本地全局內(nèi)存,這樣可以減少遠(yuǎn)程調(diào)用提高性能);當(dāng)頁(yè)面滾動(dòng)到商品介紹頁(yè)面時(shí)異步調(diào)用商品介紹服務(wù)獲取數(shù)據(jù);

5、如果從聚合的SSDB集群/Redis中獲取不到相關(guān)數(shù)據(jù);則回源到動(dòng)態(tài)服務(wù)通過(guò)RPC調(diào)用相關(guān)系統(tǒng)獲取所有要展示的數(shù)據(jù)返回(此處可以做限流處理,因?yàn)槿绻罅空?qǐng)求過(guò)來(lái)的話可能導(dǎo)致服務(wù)雪崩,需要采取保護(hù)措施),此處的邏輯和數(shù)據(jù)聚合Worker完全一樣;然后發(fā)送MQ通知數(shù)據(jù)變更,這樣下次訪問(wèn)時(shí)就可以從聚合的SSDB集群/Redis中獲取數(shù)據(jù)了。

?

基本流程如上所述,主要分為Worker、動(dòng)態(tài)服務(wù)、數(shù)據(jù)存儲(chǔ)和前端展示;因?yàn)橄到y(tǒng)非常復(fù)雜,只介紹動(dòng)態(tài)服務(wù)和前端展示、數(shù)據(jù)存儲(chǔ)架構(gòu);Worker部分不做實(shí)現(xiàn)。

33.商品搜索框的搜索聯(lián)想如何實(shí)現(xiàn)?比如輸入“羽絨” ,然后輸入框下會(huì)列出很多關(guān)于羽絨服的搜索條件?“羽絨服男正品折扣?”等等。

?

34.一個(gè)電商項(xiàng)目,在tomcat里面部署要打幾個(gè)war包?

?

35.你說(shuō)你用了redis緩存,你redis存的是什么格式的數(shù)據(jù),是怎么存的?

?

?36.購(gòu)物車(chē)知識(shí)補(bǔ)充(在設(shè)計(jì)購(gòu)物車(chē)時(shí)需要注意哪些細(xì)節(jié))

為什么購(gòu)物車(chē)的設(shè)計(jì)很重要?

①購(gòu)物車(chē)是消費(fèi)的最后一環(huán)

購(gòu)物車(chē)在用戶(hù)整體消費(fèi)過(guò)程中一般是在最后一環(huán),用戶(hù)完整的消費(fèi)體驗(yàn)應(yīng)該是:打開(kāi)APP或網(wǎng)站->瀏覽商品->加入購(gòu)物車(chē)->確認(rèn)訂單并支付,在這個(gè)過(guò)程中,購(gòu)物車(chē)和支付環(huán)節(jié)可以合并成一環(huán),基本上用戶(hù)點(diǎn)開(kāi)購(gòu)物車(chē)并開(kāi)始填寫(xiě)地址的時(shí)候,就有很大的幾率要完成購(gòu)買(mǎi),做好商品展現(xiàn)以及推送的環(huán)節(jié),如果在最后的購(gòu)物一環(huán)沒(méi)有好的用戶(hù)體驗(yàn),豈不嗚呼哀哉。

②購(gòu)物車(chē)隱含的對(duì)比收藏功能

與現(xiàn)實(shí)購(gòu)物車(chē)不同的是,網(wǎng)絡(luò)消費(fèi)者也比較喜歡把看中但不計(jì)劃買(mǎi)的商品先放入購(gòu)物車(chē),或者把商品統(tǒng)一放到購(gòu)物車(chē)直接進(jìn)行比較,以備日后購(gòu)買(mǎi),因此從購(gòu)物車(chē)保存的信息,就能夠知道用戶(hù)的大致偏好。

③購(gòu)物車(chē)的重交易屬性

用戶(hù)在瀏覽商品涉及的只是前端展示,但購(gòu)物車(chē)這一環(huán)涉及到最終的交易,對(duì)于用戶(hù)來(lái)說(shuō),需要了解本次交易的基本物品信息、價(jià)格信息;而對(duì)于商戶(hù)來(lái)說(shuō),確認(rèn)收款、訂單生成、物流環(huán)節(jié)都需要在這里獲取到信息,才能完成本次的交易。

購(gòu)物車(chē)設(shè)計(jì)需要展示的基本信息

購(gòu)物車(chē)主要作用就是告訴用戶(hù)買(mǎi)了什么,價(jià)格多少,不同類(lèi)型的物品可能會(huì)有不同展示方式,但最基本的包括商品名稱(chēng)、價(jià)格、數(shù)量(若是服務(wù),可能是次數(shù))、其他附屬信息。

哪些細(xì)節(jié)要讓用戶(hù)買(mǎi)得舒服?

親,記得前面說(shuō)的用戶(hù)是如何看待購(gòu)物車(chē)的功能嗎?還記得你的用戶(hù)會(huì)多次使用購(gòu)物車(chē),如果你只是完整做好信息展示不做好其他事情真的好嗎?

①登錄環(huán)節(jié)不要放在加入購(gòu)物車(chē)前

請(qǐng)讓用戶(hù)先加入購(gòu)物車(chē),并在進(jìn)行結(jié)算的時(shí)候在提醒用戶(hù)需要登錄。為什么?過(guò)早提醒用戶(hù)需要登錄才能購(gòu)買(mǎi),會(huì)打斷用戶(hù)瀏覽的流程(用戶(hù)可能還要購(gòu)買(mǎi)其他物品好嗎?)這樣的設(shè)置會(huì)讓部分用戶(hù)避而遠(yuǎn)之。

這里涉及到的一個(gè)點(diǎn)是在APP端需要記憶用戶(hù)加入購(gòu)物車(chē)的信息,與登錄后的購(gòu)物車(chē)信息合并(如果一開(kāi)始沒(méi)有這樣考慮好,技術(shù)那可能會(huì)有難度)

②自動(dòng)勾選用戶(hù)本次挑選的商品

用戶(hù)使用購(gòu)物車(chē)有一個(gè)大的作用就是收藏,所以你要知道很多用戶(hù)在購(gòu)物車(chē)中積累了很多物品,當(dāng)每次挑選加入購(gòu)物車(chē)的商品,用戶(hù)每次來(lái)到購(gòu)物車(chē)要重新把本次的購(gòu)買(mǎi)商品選上是很不好的體驗(yàn)。

所以這里一般是自動(dòng)勾選本次挑選的商品,同樣這里也要儲(chǔ)存用戶(hù)的勾選信息。

③陳列展示,注意沉底商品

讓用戶(hù)看見(jiàn)當(dāng)前想買(mǎi)的商品就好了,把一些時(shí)間久遠(yuǎn)的,已經(jīng)賣(mài)完的沉底顯示。這樣做的好處是能讓用戶(hù)看見(jiàn)之前的選擇但沒(méi)購(gòu)買(mǎi)的商品,提醒一下說(shuō)不定就又勾上買(mǎi)了哦!

④歸類(lèi)展示,可能增加購(gòu)買(mǎi)

考慮如何進(jìn)行歸類(lèi)展示,C2C可以按照商家分類(lèi),B2C可以按照品牌分類(lèi)。

⑤價(jià)格和優(yōu)惠的提醒

消費(fèi)用戶(hù)會(huì)關(guān)系自己每一次的消費(fèi)價(jià)格,為避免商品列表過(guò)長(zhǎng)隱藏價(jià)格信息,APP端一般會(huì)把總價(jià)固定底部提示。同時(shí)在合計(jì)信息中,展示優(yōu)惠價(jià)格,能夠促進(jìn)消費(fèi)者購(gòu)買(mǎi)。

?

哪些細(xì)節(jié)要推動(dòng)用戶(hù)繼續(xù)購(gòu)買(mǎi)?

①還差一點(diǎn)就可以有優(yōu)惠啦!

湊單,常用的手段包括運(yùn)費(fèi)見(jiàn)面或是滿減促銷(xiāo),一般在網(wǎng)站底部會(huì)展示一些適合湊單的商品;在APP端可以給鏈接(不過(guò)需要權(quán)衡用戶(hù)跳轉(zhuǎn)會(huì)不會(huì)再跳回來(lái)哦!)

②提醒用戶(hù)有些商品你真的可以買(mǎi)了

有關(guān)調(diào)查顯示,加入購(gòu)物車(chē)而沒(méi)有購(gòu)買(mǎi)的,在4小時(shí)以?xún)?nèi)提醒用戶(hù),會(huì)有27%的喚醒率哦!

所以需要提醒的幾個(gè)點(diǎn)有:

生成訂單但是還沒(méi)支付的

商品有優(yōu)惠信息

商品庫(kù)存不足的

這些信息可以促進(jìn)消費(fèi)者購(gòu)買(mǎi),注意提醒的時(shí)間段,早上9點(diǎn)至晚上8點(diǎn)為宜,其他時(shí)間段就可能打擾用戶(hù)咯(當(dāng)然也要視產(chǎn)品類(lèi)型而定啦,只不過(guò)大半夜提醒用戶(hù)買(mǎi)東西確實(shí)不好,不是?)

總結(jié)

以上是生活随笔為你收集整理的电商项目介绍的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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