[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
- 前台-无需登录
- 注册
- 登录
- 退出
- 产品页
- 模态登录
- 分类页
- 搜索
- 前台-需要登录
- 购物流程
- 立即购买
- 结算页面
- 加入购物车
- 查看购物车页面
- 登录状态拦截器
- 其他拦截器
- 购物车页面操作
- 订单状态图
- 生成订单
- 我的订单页
- 我的订单页操作
- 评价产品
- 总结
