一述召、編寫web.xml
<!-- 配置springmvc的核心控制器 -->
<servlet>
<servlet-name>seckill-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-*.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>seckill-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
在這里就真正的將Mybatis蒲跨、SpringMVC译断、Spring進行了整合。因為Spring和SpringMVC本來就是雙胞胎兄弟财骨,所以整合起來非常方便镐作。
二、編寫spring-web.xml
<!-- 開啟springmvc注解模式
1.自動注冊DefaultAnnotationHandlerMapping隆箩,AnnotationMethodHandlerAdapter
2.提供一系列:數據綁定,數字和日期的format @NumberFormat @DateTimeFormat
xml json默認讀寫功能
-->
<mvc:annotation-driven />
<!-- 加入對靜態(tài)資源js羔杨,css捌臊,gif等的處理,允許使用/做全局映射 -->
<mvc:default-servlet-handler/>
<!-- 配置jsp兜材,顯示ViewResolver -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 配置掃描web相關的bean -->
<context:component-scan base-package="com.codeliu.web"></context:component-scan>
總共做了四步理澎,第一是注解驅動逞力,能夠幫我們自動注冊一些東西。第二是配置不攔截靜態(tài)資源糠爬,因為上面我們的DispatcherServlet默認的攔截路徑是/寇荧,如果是*.do之類的則不用配置這一項。第三是加了前后綴执隧,這不也可有可無揩抡。第四步是進行包的掃描,這一步在配置spring-service.xml時也進行了包掃描镀琉,兩者不能混為一談峦嗤。
三、編寫相關的Controller
這里代碼有點多就不貼了屋摔。SeckillController.java里有五個方法烁设,分別是
- String getList(Model model):獲取所有的秒殺商品。
- String detail(@PathVariable("seckillId") Long seckillId, Model model):單個秒殺商品的詳情頁钓试。
- SeckillResult<Long> getTime():獲取系統(tǒng)的當前時間装黑。因為每個人的電腦時間不一樣,所以我們要統(tǒng)一時間弓熏。
- SeckillResult<Exposer> exposer(@PathVariable("seckillId") Long seckillId):秒殺地址的暴露曹体。
- SeckillResult<SeckillExecution> execution(@PathVariable("seckillId") Long seckillId, @CookieValue(value = "killedPhone", required = false) Long userPhone, @PathVariable("MD5") String MD5):執(zhí)行秒殺。
主要講一下暴露秒殺地址和執(zhí)行秒殺這兩個方法硝烂,這里我們返回值使用了SeckillResult<T>箕别,該類是將Ajax傳遞的數據封裝成json并返回。
四滞谢、編寫jsp頁面
這里我們使用bootstrap框架串稀,有列表頁list.jsp和詳情頁details.jsp。我們使用Ajax+json進行數據的交互狮杨。
五母截、前后端交互
這里使用了一個很重要的概念,那就是js模塊化橄教。和java的包性質差不多清寇。因為js寫多了就看的很亂,所以我們把相關的一些代碼放在一個模塊中护蝶,這樣debug更快华烟。同時也應該注意一些代碼的重用以及代碼的美觀,比如傳輸的url持灰,我們統(tǒng)一放在一起盔夜。
// 封裝秒殺相關的ajax的url
URL:{
now:function() {
return '/SSM_seckill/seckill/time/now';
},
exposer:function(seckillId) {
return '/SSM_seckill/seckill/' + seckillId + '/exposer';
},
execution:function(seckillId, md5) {
return '/SSM_seckill/seckill/' + seckillId + '/' + md5 + '/execution';
}
},
而不是什么地方要有就寫。
代碼就不貼了,這里主要就是和controller層進行數據的交互喂链。
六返十、遇到的錯誤
(1)這個是手誤造成的,本來寫EL表達式是${}的形式椭微,結果被我寫成了#{}洞坑。看來是OGNL寫多了蝇率。
(2)這個涉及到加/和不加/的區(qū)別迟杂,在不加/的情況下,其參照路徑是當前資源的訪問路徑瓢剿。在加/的情況下逢慌,分為前臺路徑和后臺路徑,前臺路徑的參照路徑是web服務器的根路徑间狂,后臺路徑的參照路徑是web應用的根路徑攻泼。
(3)bootstrap的模態(tài)框再特定條件下不會彈出
使用js來控制bootstrap的模態(tài)框,在cookie里有用戶的手機號時才會彈出鉴象,但測試的時候發(fā)現一直沒有彈出忙菠,查看瀏覽器的控制臺,發(fā)現在detail.jsp中seckill.js文件加載失敗
<script src="../../resources/script/seckill.js" type="text/javascript"></script>
寫成上面的形式就能正常彈出纺弊,但寫成全路徑或者其他的方式牛欢,均無法加載。具體原因有待查找淆游。
(4)彈出框一直彈出
本來如果在cookie里能夠查找到相應手機號傍睹,模態(tài)框就不會彈出,用戶就可以訪問秒殺的詳情頁面犹菱,但發(fā)現輸入手機號卻一直彈出框框拾稳,查看cookie,發(fā)現已經存入
注意我上面圈起來的腊脱,問題就出在那里访得,我存入cookie時,path的路徑寫成了/seckill陕凹,這樣在詳情頁根本就找不到cookie悍抑,所以會一直彈出,改成/SSM_seckill/seckill就好了杜耙。只要保證在當前路徑能訪問到cookie就可以搜骡。
(5)秒殺倒計時,數字不能正常顯示
因為在details.jsp中泥技,使用EL表達式往jquery中傳值時浆兰,不加引號一直出紅線磕仅,雖然不影響結果珊豹,但看著不舒服簸呈,所以就把時間都傳成了字符串的格式,在jquery中進行接收時店茶,如果不轉換成Number格式蜕便,就會成為NaN。
// 因為使用EL表達式贩幻,傳過來的是字符串轿腺,轉換成數字
startTime = Number(startTime);
endTime = Number(endTime);
seckillId = Number(seckillId);
(6)md5的值無法傳遞過去
通過調試可以發(fā)現在獲取秒殺地址的時候,md5的值已經獲取到了丛楚,但執(zhí)行秒殺的時候族壳,md5的值卻為null,導致一直秒殺錯誤趣些。出現這樣的問題仿荆,首先先分析是否是json傳遞的過程中出現了問題,通過打印發(fā)現問題不是在這里坏平,那就返回代碼去找拢操,后來發(fā)現是在類中,md5字段set方法的問題舶替,并不是我沒有給它set方法令境,一開始字段的名稱我寫的MD5,然后set方法如下
public void setMD5(String mD5) {
MD5 = mD5;
}
估計問題就出在這里顾瞪,把MD5寫成md5舔庶,能夠正常執(zhí)行秒殺。
(7)中文出現亂碼
這些中文的信息我都是放在一個枚舉類中陈醒。出現這種情況惕橙,第一想到的就是是否是傳遞給前端時,沒有設置編碼孵延,發(fā)現都設置了吕漂,使用springmvc的編碼器也不起作用,后來通過調試發(fā)現在controller中獲取到的枚舉值就已經是亂碼了尘应。
問題就是惶凝,在枚舉類中只給字段加了get方法,沒有set方法H帧2韵省!
(8)重復秒殺出錯
因為這里的秒殺成功表使用的是手機加商品id共同構成主鍵玷犹,當重復秒殺的時候混滔,主鍵沖突,sql語句會直接報錯,這樣自定義的異常就無法起作用坯屿,所以我們在insert語句中加入ignore關鍵字油湖,忽略報錯,讓insert語句的返回值為0领跛,這樣就可以捕獲相關的異常乏德。
<!-- 主鍵沖突,會報錯吠昭,使用 ignore可以忽略報錯喊括,返回值為0-->
insert ignore into success_killed(seckill_id,user_phone,state) values(#{seckillId}, #{userPhone}, 0)
七、總結
到此矢棚,MVC三層都完成了郑什。接下來就是進行優(yōu)化。
通過寫這么一個小項目蒲肋,發(fā)現自己編碼能力太差了蘑拯,debug能力也有待提高,1小時編碼肉津,2小時找bug强胰,真的是在寫bug。