功能分析
1、在购物车页面点击“去结算”按钮,跳转到订单确认页面
a)必须要求用户登录
b)使用拦截器实现。
c)如果用户未登录跳转到登录页面。
d)如果用户已经登录,放行。展示确认页面。
e)判断cookie中是否有购物车数据
f)如果有同步到服务端。
2、订单确认页面中选择收货地址,选择支付方式,确认商品列表。
a)根据用户id查询收货地址列表
b)展示支付方式列表。
c)从购物车中取商品列表,从服务端取购物车列表。
3、订单确认页面点击“提交”,生成订单。
展示订单生成完成,或者跳转到支付页面。
展示订单确认页面
功能分析
1、根据id查询用户的收货地址列表(使用静态数据)
2、从购物车中取商品列表,展示到页面。调用购物车服务查询。
Dao层
直接从redis中取购车商品列表。
Service层
收货地址静态数据,没有server。
调用购物车的service查询购物车商品列表。
2.3.4.Controller
引用购物车服务
请求的url:/order/order-cart
参数:没有参数
返回值:逻辑视图
@RequestMapping("/order/order-cart")
public String showOrderCart(HttpServletRequest request) {
//取用户id
TbUser user= (TbUser) request.getAttribute("user");
//根据用户id取收货地址列表
//使用静态数据。。。
//取支付方式列表
//静态数据
//根据用户id取购物车列表
List<TbItem> cartList = cartService.getCartList(user.getId());
//把购物车列表传递给jsp
request.setAttribute("cartList", cartList);
//返回页面
return "order-cart";
}
登录拦截器:
1、从cookie中取token
2、如果没有取到,没有登录,跳转到sso系统的登录页面。
用户登录成功后,跳转到当前请求的url,拦截
3、如果取到token。判断登录是否过期,需要调用sso系统的服务,根据token取用户信息
4、如果没有取到用户信息,登录已经过期,重新登录。跳转到登录页面。用户登录成功后,跳转到当前请求的url,拦截
5、如果取到用户信息,用户已经是登录状态,把用户信息保存到request中。放行
6、判断cookie中是否有购物车信息,如果有合并购物车
/**
* 用户登录拦截器
* <p>Title: LoginInterceptor</p>
* <p>Description: </p>
* <p>Company: www.itcast.cn</p>
* @version 1.0
*/
public class LoginInterceptor implements HandlerInterceptor {
@Value("${SSO_URL}")
private String SSO_URL;
@Autowired
private TokenService tokenService;
@Autowired
private CartService cartService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//从cookie中取token
String token = CookieUtils.getCookieValue(request, "token");
//判断token是否存在
if (StringUtils.isBlank(token)) {
//如果token不存在,未登录状态,跳转到sso系统的登录页面。用户登录成功后,跳转到当前请求的url
response.sendRedirect(SSO_URL + "/page/login?redirect=" + request.getRequestURL());
//拦截
return false;
}
//如果token存在,需要调用sso系统的服务,根据token取用户信息
E3Result e3Result = tokenService.getUserByToken(token);
//如果取不到,用户登录已经过期,需要登录。
if (e3Result.getStatus() != 200) {
//如果token不存在,未登录状态,跳转到sso系统的登录页面。用户登录成功后,跳转到当前请求的url
response.sendRedirect(SSO_URL + "/page/login?redirect=" + request.getRequestURL());
//拦截
return false;
}
//如果取到用户信息,是登录状态,需要把用户信息写入request。
TbUser user = (TbUser) e3Result.getData();
request.setAttribute("user", user);
//判断cookie中是否有购物车数据,如果有就合并到服务端。
String jsonCartList = CookieUtils.getCookieValue(request, "cart", true);
if (StringUtils.isNoneBlank(jsonCartList)) {
//合并购物车
cartService.mergeCart(user.getId(), JsonUtils.jsonToList(jsonCartList, TbItem.class));
}
//放行
return true;
}
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
// TODO Auto-generated method stub
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
// TODO Auto-generated method stub
}
}
拦截器在Springmvc配置:
<!-- 配置拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="cn.e3mall.order.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
提交订单:
功能分析
1、在订单确认页面点击“提交订单”按钮生成订单。
2、请求的url:/order/create
3、参数:提交的是表单的数据。保存的数据:订单、订单明细、配送地址。
a)向tb_order中插入记录。
i.订单号需要手动生成。
要求订单号不能重复。
订单号可读性号。
可以使用redis的incr命令生成订单号。订单号需要一个初始值。
ii.Payment:表单数据
iii.payment_type:表单数据
iv.user_id:用户信息
v.buyer_nick:用户名
vi.其他字段null
b)向tb_order_item订单明细表插入数据。
i.Id:使用incr生成
ii.order_id:生成的订单号
iii.其他的都是表单中的数据。
c)tb_order_shipping,订单配送信息
i.order_id:生成的订单号
ii.其他字段都是表单中的数据。
d)使用pojo接收表单的数据。
可以扩展TbOrder,在子类中添加两个属性一个是商品明细列表,一个是配送信息。
把pojo放到e3-order-interface工程中。
/**
* pojo接收表单的数据,拓展TbOrder,
* 包含orderItems和orderShipping两个属性
* <p>Title: OrderInfo</p>
* <p>Description: </p>
* <p>Company: www.itcast.cn</p>
* @version 1.0
*/
public class OrderInfo extends TbOrder implements Serializable {
private List<TbOrderItem> orderItems;
private TbOrderShipping orderShipping;
public List<TbOrderItem> getOrderItems() {
return orderItems;
}
public void setOrderItems(List<TbOrderItem> orderItems) {
this.orderItems = orderItems;
}
public TbOrderShipping getOrderShipping() {
return orderShipping;
}
public void setOrderShipping(TbOrderShipping orderShipping) {
this.orderShipping = orderShipping;
}
}
interface:
E3Result createOrder(OrderInfo orderInfo);
service层:
1、接收表单的数据
2、生成订单id
3、向订单表插入数据。
4、向订单明细表插入数据
5、向订单物流表插入数据。
6、返回e3Result。
返回值:e3Result
/**
* 订单处理服务
* <p>Title: OrderServiceImpl</p>
* <p>Description: </p>
* <p>Company: www.itcast.cn</p>
* @version 1.0
*/
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private TbOrderMapper orderMapper;
@Autowired
private TbOrderItemMapper orderItemMapper;
@Autowired
private TbOrderShippingMapper orderShippingMapper;
@Autowired
private JedisClient jedisClient;
@Value("${ORDER_ID_GEN_KEY}")
private String ORDER_ID_GEN_KEY;
@Value("${ORDER_ID_START}")
private String ORDER_ID_START;
@Value("${ORDER_DETAIL_ID_GEN_KEY}")
private String ORDER_DETAIL_ID_GEN_KEY;
@Override
public E3Result createOrder(OrderInfo orderInfo) {
//生成订单号。使用redis的incr生成。
if (!jedisClient.exists(ORDER_ID_GEN_KEY)) {
jedisClient.set(ORDER_ID_GEN_KEY, ORDER_ID_START);
}
String orderId = jedisClient.incr(ORDER_ID_GEN_KEY).toString();
//补全orderInfo(TbOrder)的属性
orderInfo.setOrderId(orderId);
//1、未付款,2、已付款,3、未发货,4、已发货,5、交易成功,6、交易关闭
orderInfo.setStatus(1);
orderInfo.setCreateTime(new Date());
orderInfo.setUpdateTime(new Date());
//插入订单表
orderMapper.insert(orderInfo);
//向订单明细表(TbOrderItem)插入数据。
List<TbOrderItem> orderItems = orderInfo.getOrderItems();
for (TbOrderItem tbOrderItem : orderItems) {
//生成明细id
String odId = jedisClient.incr(ORDER_DETAIL_ID_GEN_KEY).toString();
//补全pojo的属性
tbOrderItem.setId(odId);
tbOrderItem.setOrderId(orderId);
//向明细表插入数据
orderItemMapper.insert(tbOrderItem);
}
//向订单物流表(TbOrderShipping)插入数据
TbOrderShipping orderShipping = orderInfo.getOrderShipping();
orderShipping.setOrderId(orderId);
orderShipping.setCreated(new Date());
orderShipping.setUpdated(new Date());
orderShippingMapper.insert(orderShipping);
//返回E3Result,包含订单号
return E3Result.ok(orderId);
}
}
Controller:
请求的url:/order/create
参数:使用OrderInfo接收
返回值:逻辑视图。
业务逻辑:
1、接收表单提交的数据OrderInfo。
2、补全用户信息。
3、调用Service创建订单。
4、返回逻辑视图展示成功页面
a)需要Service返回订单号
b)当前日期加三天。
@RequestMapping(value="/order/create", method=RequestMethod.POST)
public String createOrder(OrderInfo orderInfo, HttpServletRequest request) {
//取用户信息
TbUser user = (TbUser) request.getAttribute("user");
//把用户信息添加到orderInfo中。
orderInfo.setUserId(user.getId());
orderInfo.setBuyerNick(user.getUsername());
//调用服务生成订单
E3Result e3Result = orderService.createOrder(orderInfo);
//如果订单生成成功,需要删除购物车
if (e3Result.getStatus() == 200) {
//清空购物车
cartService.clearCartItem(user.getId());
}
//把订单号传递给页面
request.setAttribute("orderId", e3Result.getData());
request.setAttribute("payment", orderInfo.getPayment());
//返回逻辑视图
return "success";
}
清空购物车的interface:
E3Result clearCartItem(long userId);
service层:
@Override
public E3Result clearCartItem(long userId) {
//删除购物车信息
jedisClient.del(REDIS_CART_PRE + ":" + userId);
return E3Result.ok();
}