[TOC]
## 步驟 1 : 先運行,看到效果,再學習
先將完整的 tmall_ssm 項目(向老師要相關資料),配置運行起來,確認可用之后,再學習做了哪些步驟以達到這樣的效果。
## 步驟 2 : 模仿和排錯
在確保可運行項目能夠正確無誤地運行之后,再嚴格照著教程的步驟,對代碼模仿一遍。
模仿過程難免代碼有出入,導致無法得到期望的運行結果,此時此刻通過比較**正確答案** ( 可運行項目 ) 和自己的代碼,來定位問題所在。
采用這種方式,**學習有效果,排錯有效率**,可以較為明顯地提升學習速度,跨過學習路上的各個檻。
## 步驟 3 : 查看購物車頁面的問題
查看購物車頁面有個問題,必須建立在已經登錄的狀態之上。 如果沒有登錄,而訪問地址:
`http://127.0.0.1:8080/tmall_ssm/forecart`
會導致異常產生。

## 步驟 4 : 解決思路
所以在查看購物車之前,應該進行登錄操作,但是又不能確保用戶一定會記得登錄,那么怎么辦呢?
準備一個過濾器,當訪問那些需要登錄才能做的頁面的時候,進行是否登錄的判斷,如果不通過,那么就跳轉到login.jsp頁面去,提示用戶登錄。
哪些頁面需要登錄?哪些頁面不需要呢?
a. 不需要登錄也可以訪問的
如:注冊,登錄,產品,首頁,分類,查詢等等
b. 需要登錄才能夠訪問的
如:購買行為,加入購物車行為,查看購物車,查看我的訂單等等
## 步驟 5 : LoginInterceptor
新建一個過濾器LoginInterceptor ,根據`解決思路`中
哪些頁面需要登錄?哪些頁面不需要呢?
a. 不需要登錄也可以訪問的
如:注冊,登錄,產品,首頁,分類,查詢等等
b. 需要登錄才能夠訪問的
如:購買行為,加入購物車行為,查看購物車,查看我的訂單等等
不需要登錄也可以訪問的已經確定了,但是需要登錄才能夠訪問,截止目前為止還不能確定,所以這個過濾器就判斷如果不是注冊,登錄,產品這些,就進行登錄校驗
1. 準備字符串數組 noNeedAuthPage,存放哪些不需要登錄也能訪問的路徑
2. 獲取uri
3. 去掉前綴/tmall_ssm
4. 如果訪問的地址是/fore開頭
4.1 取出fore后面的字符串,比如是forecart,那么就取出cart
4.2 判斷cart是否是在noNeedAuthPage
4.2 如果不在,那么就需要進行是否登錄驗證
4.3 從session中取出"user"對象
4.4 如果對象不存在,就客戶端跳轉到login.jsp
4.5 否則就正常執行
~~~
package com.dodoke.tmall.interceptor;
import java.util.Arrays;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.dodoke.tmall.pojo.User;
import com.dodoke.tmall.service.CategoryService;
import com.dodoke.tmall.service.OrderItemService;
public class LoginInterceptor extends HandlerInterceptorAdapter {
@Autowired
CategoryService categoryService;
@Autowired
OrderItemService orderItemService;
/**
* 在業務處理器處理請求之前被調用 如果返回false 從當前的攔截器往回執行所有攔截器的afterCompletion(),再退出攔截器鏈
* 如果返回true 執行下一個攔截器,直到所有的攔截器都執行完畢 再執行被攔截的Controller 然后進入攔截器鏈,
* 從最后一個攔截器往回執行所有的postHandle() 接著再從最后一個攔截器往回執行所有的afterCompletion()
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
HttpSession session = request.getSession();
String contextPath = session.getServletContext().getContextPath(); // /tmall_ssm
String[] noNeedAuthPage = new String[] { "home", "checkLogin", "register", "loginAjax", "login", "product",
"category", "search" };
String uri = request.getRequestURI(); // /tmall_ssm/forecart
// 刪除字符串
uri = StringUtils.remove(uri, contextPath);
System.out.println(uri); // /forecart
// startsWith() 方法用于檢測字符串是否以指定的前綴開始
if (uri.startsWith("/fore")) {
// 該方法取uri內分隔符"/fore"后的字符串。
String method = StringUtils.substringAfterLast(uri, "/fore");
// Array.asList:把一般數組用Array.asList轉為List
if (!Arrays.asList(noNeedAuthPage).contains(method)) {
User user = (User) session.getAttribute("user");
if (null == user) {
response.sendRedirect("loginPage");
return false;
}
}
}
return true;
}
/**
* 在業務處理器處理請求執行完成后,生成視圖之前執行的動作 可在modelAndView中加入數據,比如當前時間
*/
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
/**
* 在DispatcherServlet完全處理完請求后被調用,可用于清理資源等
*
* 當有攔截器拋出異常時,會從當前攔截器往回執行所有的攔截器的afterCompletion()
*/
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
~~~
## 步驟 6 : springMVC.xml
在springMVC.xml中新增對登陸狀態攔截器的配置
~~~
<?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:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
<!--啟動注解識別 -->
<context:annotation-config />
<!-- 掃描Controller,并將其生命周期納入Spring管理 -->
<context:component-scan base-package="com.dodoke.tmall.controller">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<!-- 注解驅動,以使得訪問路徑與方法的匹配可以通過注解配置 -->
<mvc:annotation-driven />
<!--開通靜態資源的訪問 -->
<mvc:default-servlet-handler />
<!-- 視圖定位到/WEB/INF/jsp 這個目錄下 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" /> <!-- /WEB-INF/jsp/xxx.jsp -->
<property name="suffix" value=".jsp" />
</bean>
<!-- 對上傳文件的解析 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/fore*"/>
<bean class="com.dodoke.tmall.interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
</beans>
~~~
## 步驟 7 : 測試
接下來再試圖在未登陸狀態下訪問購物車:
`http://127.0.0.1:8080/tmall_ssm/forecart`
就會觀察到跳轉到登陸頁面的現象了

> 拓展:百度搜索,調查過濾器與攔截器的區別
- 項目簡介
- 功能一覽
- 前臺
- 后臺
- 開發流程
- 需求分析-展示
- 首頁
- 產品頁
- 分類頁
- 搜索結果頁
- 購物車查看頁
- 結算頁
- 確認支付頁
- 支付成功頁
- 我的訂單頁
- 確認收貨頁
- 確認收貨成功頁
- 評價頁
- 需求分析-交互
- 分類頁排序
- 立即購買
- 加入購物車
- 調整訂單項數量
- 刪除訂單項
- 生成訂單
- 訂單頁功能
- 確認付款
- 確認收貨
- 提交評價信息
- 登錄
- 注冊
- 退出
- 搜索
- 前臺需求列表
- 需求分析后臺
- 分類管理
- 屬性管理
- 產品管理
- 產品圖片管理
- 產品屬性設置
- 用戶管理
- 訂單管理
- 后臺需求列表
- 表結構設計
- 數據建模
- 表與表之間的關系
- 后臺-分類管理
- 可運行的項目
- 靜態資源
- JSP包含關系
- 查詢
- 分頁
- 增加
- 刪除
- 編輯
- 修改
- 做一遍
- 重構
- 分頁方式
- 分類逆向工程
- 所有逆向工程
- 后臺其他頁面
- 屬性管理實現
- 產品管理實現
- 產品圖片管理實現
- 產品屬性值設置
- 用戶管理實現
- 訂單管理實現
- 前端
- 前臺-首頁
- 可運行的項目
- 靜態資源
- ForeController
- home方法
- home.jsp
- homePage.jsp
- 前臺-無需登錄
- 注冊
- 登錄
- 退出
- 產品頁
- 模態登錄
- 分類頁
- 搜索
- 前臺-需要登錄
- 購物流程
- 立即購買
- 結算頁面
- 加入購物車
- 查看購物車頁面
- 登錄狀態攔截器
- 其他攔截器
- 購物車頁面操作
- 訂單狀態圖
- 生成訂單
- 我的訂單頁
- 我的訂單頁操作
- 評價產品
- 總結