[TOC]
## 步骤 1 : 先运行,看到效果,再学习
先将完整的 tmall_ssm 项目(向老师要相关资料),配置运行起来,确认可用之后,再学习做了哪些步骤以达到这样的效果。
## 步骤 2 : 模仿和排错
在确保可运行项目能够正确无误地运行之后,再严格照着教程的步骤,对代码模仿一遍。
模仿过程难免代码有出入,导致无法得到期望的运行结果,此时此刻通过比较**正确答案** ( 可运行项目 ) 和自己的代码,来定位问题所在。
采用这种方式,**学习有效果,排错有效率**,可以较为明显地提升学习速度,跨过学习路上的各个槛。
## 步骤 3 : 界面效果
在未登录状态(如果已经登录就看不到这个效果了,需要先退出,所以要先做退出),点击购买或者加入购物车就会弹出这个模态对话框
在这个模态对话框上可以进行登录操作,如果账号和密码出错会出现 "账号密码错误" 提示。

## 步骤 4 : imgAndInfo.jsp
立即购买和加入购物车这两个按钮的监听是放在imgAndInfo.jsp页面中
这两个按钮都会通过JQuery的`.get`方法,用异步ajax的方式访问forecheckLogin,获取当前是否登录状态
如果返回的不是"success" 即表明是未登录状态,那么就会打开登录的模态窗口
`$("#loginModal").modal('show');`
监听购买按钮:
~~~
$(".buyLink").click(function(){
var page = "forecheckLogin";
$.get(
page,
function(result){
if("success"==result){
。。。略
}
else{
$("#loginModal").modal('show');
}
}
);
return false;
});
~~~
加入购物车按钮监听:
~~~
$(".addCartLink").click(function(){
var page = "forecheckLogin";
$.get(
page,
function(result){
if("success"==result){
。。。略
}
else{
$("#loginModal").modal('show');
}
}
);
return false;
});
~~~
## 步骤 5 : ForeController.checkLogin()
在上一步的ajax访问路径`/forecheckLogin`会导致`ForeController.checkLogin()`方法被调用。
获取session中的"user"对象
如果不为空,即表示已经登录,返回字符串"success"
如果为空,即表示未登录,返回字符串"fail"
~~~
package com.dodoke.tmall.controller;
import java.util.List;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.util.HtmlUtils;
import com.dodoke.tmall.pojo.Category;
import com.dodoke.tmall.pojo.Product;
import com.dodoke.tmall.pojo.ProductImage;
import com.dodoke.tmall.pojo.PropertyValue;
import com.dodoke.tmall.pojo.Review;
import com.dodoke.tmall.pojo.User;
import com.dodoke.tmall.service.CategoryService;
import com.dodoke.tmall.service.OrderItemService;
import com.dodoke.tmall.service.OrderService;
import com.dodoke.tmall.service.ProductImageService;
import com.dodoke.tmall.service.ProductService;
import com.dodoke.tmall.service.PropertyValueService;
import com.dodoke.tmall.service.ReviewService;
import com.dodoke.tmall.service.UserService;
@Controller
@RequestMapping("")
public class ForeController {
@Autowired
CategoryService categoryService;
@Autowired
ProductService productService;
@Autowired
UserService userService;
@Autowired
ProductImageService productImageService;
@Autowired
PropertyValueService propertyValueService;
@Autowired
OrderService orderService;
@Autowired
OrderItemService orderItemService;
@Autowired
ReviewService reviewService;
@RequestMapping("forehome")
public String home(Model model) {
List<Category> cs = categoryService.list();
productService.fill(cs);
productService.fillByRow(cs);
model.addAttribute("cs", cs);
return "fore/home";
}
@RequestMapping("foreregister")
public String register(Model model, User user) {
String name = user.getName();
// 把账号里的特殊符号进行转义
name = HtmlUtils.htmlEscape(name);
user.setName(name);
boolean exist = userService.isExist(name);
if (exist) {
String m = "用户名已经被使用,不能使用";
model.addAttribute("msg", m);
model.addAttribute("user", null);
return "fore/register";
}
userService.add(user);
return "redirect:registerSuccessPage";
}
@RequestMapping("forelogin")
public String login(@RequestParam("name") String name, @RequestParam("password") String password, Model model,
HttpSession session) {
name = HtmlUtils.htmlEscape(name);
User user = userService.get(name, password);
if (null == user) {
model.addAttribute("msg", "账号密码错误");
return "fore/login";
}
session.setAttribute("user", user);
return "redirect:forehome";
}
@RequestMapping("forelogout")
public String logout(HttpSession session) {
session.removeAttribute("user");
return "redirect:forehome";
}
@RequestMapping("foreproduct")
public String product(int pid, Model model) {
Product p = productService.get(pid);
// 根据对象p,获取这个产品对应的单个图片集合
List<ProductImage> productSingleImages = productImageService.list(p.getId(), ProductImageService.type_single);
// 根据对象p,获取这个产品对应的详情图片集合
List<ProductImage> productDetailImages = productImageService.list(p.getId(), ProductImageService.type_detail);
p.setProductSingleImages(productSingleImages);
p.setProductDetailImages(productDetailImages);
// 获取产品的所有属性值
List<PropertyValue> pvs = propertyValueService.list(p.getId());
// 获取产品对应的所有的评价
List<Review> reviews = reviewService.list(p.getId());
// 设置产品的销量和评价数量
productService.setSaleAndReviewNumber(p);
model.addAttribute("reviews", reviews);
model.addAttribute("p", p);
model.addAttribute("pvs", pvs);
return "fore/product";
}
@RequestMapping("forecheckLogin")
@ResponseBody
public String checkLogin(HttpSession session) {
User user = (User) session.getAttribute("user");
if (null != user) {
return "success";
}
return "fail";
}
}
~~~
## 步骤 6 : modal.jsp
modal.jsp 页面被 footer.jsp 所包含,所以每个页面都是加载了的。
通过imgAndInfo.jsp页面中的购买按钮或者加入购物车按钮显示出来。
点击登录按钮时,使用imgAndInfo.jsp 页面中的ajax代码进行登录验证:
~~~
$("button.loginSubmitButton").click(function(){
var name = $("#name").val();
var password = $("#password").val();
if(0==name.length||0==password.length){
$("span.errorMessage").html("请输入账号密码");
$("div.loginErrorMessageDiv").show();
return false;
}
var page = "foreloginAjax";
$.post(
page,
{"name":name,"password":password},
function(result){
if("success"==result){
location.reload();
}
else{
$("span.errorMessage").html("账号密码错误");
$("div.loginErrorMessageDiv").show();
}
}
);
return true;
});
~~~
modal.jsp:
~~~
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<div class="modal " id="loginModal" tabindex="-1" role="dialog" >
<div class="modal-dialog loginDivInProductPageModalDiv">
<div class="modal-content">
<div class="loginDivInProductPage">
<div class="loginErrorMessageDiv">
<div class="alert alert-danger" >
<button type="button" class="close" data-dismiss="alert" aria-label="Close"></button>
<span class="errorMessage"></span>
</div>
</div>
<div class="login_acount_text">账户登录</div>
<div class="loginInput " >
<span class="loginInputIcon ">
<span class=" glyphicon glyphicon-user"></span>
</span>
<input id="name" name="name" placeholder="手机,会员名,邮箱" type="text">
</div>
<div class="loginInput " >
<span class="loginInputIcon ">
<span class=" glyphicon glyphicon-lock"></span>
</span>
<input id="password" name="password" type="password" placeholder="密码" type="text">
</div>
<span class="text-danger">不要输入真实的天猫账号密码</span><br><br>
<div>
<a href="#nowhere">忘记登录密码</a>
<a href="registerPage" class="pull-right">免费注册</a>
</div>
<div style="margin-top:20px">
<button class="btn btn-block redButton loginSubmitButton" type="submit">登录</button>
</div>
</div>
</div>
</div>
</div>
<div class="modal" id="deleteConfirmModal" tabindex="-1" role="dialog" >
<div class="modal-dialog deleteConfirmModalDiv">
<div class="modal-content">
<div class="modal-header">
<button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<h4 class="modal-title">确认删除?</h4>
</div>
<div class="modal-footer">
<button data-dismiss="modal" class="btn btn-default" type="button">关闭</button>
<button class="btn btn-primary deleteConfirmButton" id="submit" type="button">确认</button>
</div>
</div>
</div>
</div>
~~~
## 步骤 7 : `ForeController.loginAjax()`
在上一步modal.jsp中,点击了登录按钮之后,访问路径/foreloginAjax,导致`ForeController.loginAjax()`方法被调用
1. 获取账号密码
2. 通过账号密码获取User对象
2.1 如果User对象为空,那么就返回"fail"字符串。
2.2 如果User对象不为空,那么就把User对象放在session中,并返回"success" 字符串
~~~
package com.dodoke.tmall.controller;
import java.util.List;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.util.HtmlUtils;
import com.dodoke.tmall.pojo.Category;
import com.dodoke.tmall.pojo.Product;
import com.dodoke.tmall.pojo.ProductImage;
import com.dodoke.tmall.pojo.PropertyValue;
import com.dodoke.tmall.pojo.Review;
import com.dodoke.tmall.pojo.User;
import com.dodoke.tmall.service.CategoryService;
import com.dodoke.tmall.service.OrderItemService;
import com.dodoke.tmall.service.OrderService;
import com.dodoke.tmall.service.ProductImageService;
import com.dodoke.tmall.service.ProductService;
import com.dodoke.tmall.service.PropertyValueService;
import com.dodoke.tmall.service.ReviewService;
import com.dodoke.tmall.service.UserService;
@Controller
@RequestMapping("")
public class ForeController {
@Autowired
CategoryService categoryService;
@Autowired
ProductService productService;
@Autowired
UserService userService;
@Autowired
ProductImageService productImageService;
@Autowired
PropertyValueService propertyValueService;
@Autowired
OrderService orderService;
@Autowired
OrderItemService orderItemService;
@Autowired
ReviewService reviewService;
@RequestMapping("forehome")
public String home(Model model) {
List<Category> cs = categoryService.list();
productService.fill(cs);
productService.fillByRow(cs);
model.addAttribute("cs", cs);
return "fore/home";
}
@RequestMapping("foreregister")
public String register(Model model, User user) {
String name = user.getName();
// 把账号里的特殊符号进行转义
name = HtmlUtils.htmlEscape(name);
user.setName(name);
boolean exist = userService.isExist(name);
if (exist) {
String m = "用户名已经被使用,不能使用";
model.addAttribute("msg", m);
model.addAttribute("user", null);
return "fore/register";
}
userService.add(user);
return "redirect:registerSuccessPage";
}
@RequestMapping("forelogin")
public String login(@RequestParam("name") String name, @RequestParam("password") String password, Model model,
HttpSession session) {
name = HtmlUtils.htmlEscape(name);
User user = userService.get(name, password);
if (null == user) {
model.addAttribute("msg", "账号密码错误");
return "fore/login";
}
session.setAttribute("user", user);
return "redirect:forehome";
}
@RequestMapping("forelogout")
public String logout(HttpSession session) {
session.removeAttribute("user");
return "redirect:forehome";
}
@RequestMapping("foreproduct")
public String product(int pid, Model model) {
Product p = productService.get(pid);
// 根据对象p,获取这个产品对应的单个图片集合
List<ProductImage> productSingleImages = productImageService.list(p.getId(), ProductImageService.type_single);
// 根据对象p,获取这个产品对应的详情图片集合
List<ProductImage> productDetailImages = productImageService.list(p.getId(), ProductImageService.type_detail);
p.setProductSingleImages(productSingleImages);
p.setProductDetailImages(productDetailImages);
// 获取产品的所有属性值
List<PropertyValue> pvs = propertyValueService.list(p.getId());
// 获取产品对应的所有的评价
List<Review> reviews = reviewService.list(p.getId());
// 设置产品的销量和评价数量
productService.setSaleAndReviewNumber(p);
model.addAttribute("reviews", reviews);
model.addAttribute("p", p);
model.addAttribute("pvs", pvs);
return "fore/product";
}
@RequestMapping("forecheckLogin")
@ResponseBody
public String checkLogin(HttpSession session) {
User user = (User) session.getAttribute("user");
if (null != user) {
return "success";
}
return "fail";
}
@RequestMapping("foreloginAjax")
@ResponseBody
public String loginAjax(@RequestParam("name") String name, @RequestParam("password") String password,
HttpSession session) {
name = HtmlUtils.htmlEscape(name);
User user = userService.get(name, password);
if (null == user) {
return "fail";
}
session.setAttribute("user", user);
return "success";
}
}
~~~
- 项目简介
- 功能一览
- 前台
- 后台
- 开发流程
- 需求分析-展示
- 首页
- 产品页
- 分类页
- 搜索结果页
- 购物车查看页
- 结算页
- 确认支付页
- 支付成功页
- 我的订单页
- 确认收货页
- 确认收货成功页
- 评价页
- 需求分析-交互
- 分类页排序
- 立即购买
- 加入购物车
- 调整订单项数量
- 删除订单项
- 生成订单
- 订单页功能
- 确认付款
- 确认收货
- 提交评价信息
- 登录
- 注册
- 退出
- 搜索
- 前台需求列表
- 需求分析后台
- 分类管理
- 属性管理
- 产品管理
- 产品图片管理
- 产品属性设置
- 用户管理
- 订单管理
- 后台需求列表
- 表结构设计
- 数据建模
- 表与表之间的关系
- 后台-分类管理
- 可运行的项目
- 静态资源
- JSP包含关系
- 查询
- 分页
- 增加
- 删除
- 编辑
- 修改
- 做一遍
- 重构
- 分页方式
- 分类逆向工程
- 所有逆向工程
- 后台其他页面
- 属性管理实现
- 产品管理实现
- 产品图片管理实现
- 产品属性值设置
- 用户管理实现
- 订单管理实现
- 前端
- 前台-首页
- 可运行的项目
- 静态资源
- ForeController
- home方法
- home.jsp
- homePage.jsp
- 前台-无需登录
- 注册
- 登录
- 退出
- 产品页
- 模态登录
- 分类页
- 搜索
- 前台-需要登录
- 购物流程
- 立即购买
- 结算页面
- 加入购物车
- 查看购物车页面
- 登录状态拦截器
- 其他拦截器
- 购物车页面操作
- 订单状态图
- 生成订单
- 我的订单页
- 我的订单页操作
- 评价产品
- 总结
