Java技术升华android开发技巧后端开发

第二十四篇:订单系统的实现

2018-07-24  本文已影响68人  __y

前言:
我们已经实现了加入购物车的功能,加入购物车以后,我们下一步一般都是形成订单准备付款啦;那么如何形成订单呢?下面就实现订单系统

1.订单系统的搭建

先来分析一波,我们可以看到订单系统和订单服务是分开来的,即我们要建一个服务工程和一个前台工程;

image.png
建立的过程可以参考taotao-manager和taotao-manager-web
image.png
具体的一些web.xml,pom.xml,还有mybatis等配置可以参考工程里面的~这里就不贴出来了
git传送门
https://github.com/AslanYJ/shopping.git

2.实现登录拦截器

搭建完工程后,我们知道京东的话虽然可以加入购物车但是在结算的时候是一定要登录,也就是说购物车列表页面直接跳转到登录,这里要用到拦截器
拦截器我们采取Springmvc提供的拦截器

image.png
下面贴出逻辑代码
package com.taotao.order.interceptor;

import com.taotao.common.pojo.TaotaoResult;
import com.taotao.pojo.TbUser;
import com.taotao.sso.service.UserService;
import com.taotao.utils.CookieUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoginInterceptor implements HandlerInterceptor {
    @Value("${TOKEN_KEY}")
    private String TOKEN_KEY;
    @Value("${SSO_URL}")
    private String SSO_URL;
    @Autowired
    private UserService userService;
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        //执行Handler之前执行此方法,拦截请求让用户登录就在这个方法拦截
        //1.从cookie中取token。
        String token = CookieUtils.getCookieValue(httpServletRequest,TOKEN_KEY);
        //2.没有token,需要跳转到登录页面。
        if(StringUtils.isBlank(token)) {
            //取当前请求的url
            String url = httpServletRequest.getRequestURL().toString();
            //跳转到登录页面,用redirect比较合适,登录之后还要回到当前页面,因此要在请求url中添加一个回调地址
            httpServletResponse.sendRedirect(SSO_URL + "/page/login?url=" + url);
            //由于没有登录,拦截
            return false;
        }
        //3.有token。调用sso系统的服务,根据token查询用户信息。
        TaotaoResult taotaoResult = userService.getUserMessageByToken(token);
        //4.如果查不到用户信息。用户登录已经过期。需要跳转到登录页面。
        if(taotaoResult.getStatus() != 200) {
            //取当前请求的url
            String url = httpServletRequest.getRequestURL().toString();
            //跳转到登录页面,用redirect比较合适,登录之后还要回到当前页面,因此要在请求url中添加一个回调地址
            httpServletResponse.sendRedirect(SSO_URL + "/page/login?url=" + url);
            //由于没有登录,拦截
            return false;
        }
        TbUser user = (TbUser) taotaoResult.getData();
        httpServletRequest.setAttribute("user",user);
        //5.查询到用户信息。放行
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        // handler执行之后,modelAndView返回之前,可以对返回值进行处理
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        // 在ModelAndView返回之后,这时只能做些异常处理了
    }
}

用到的常量在配置文件里面配置

image.png
记得配置在springmvc.xml里面加载拦截器和拦截器的请求
image.png

3.订单展示确认界面

@Controller
public class OrderController {
    
    @Value("${TT_CART}")
    private String TT_CART;

    /**
     * 展示订单确认页面。
     * <p>Title: showOrderCart</p>
     * <p>Description: </p>
     * @return
     */
    @RequestMapping("/order/order-cart")
    public String showOrderCart(HttpServletRequest request) {
        //取用户id
        //从cookie中取token,然后根据token查询用户信息。需要调用sso系统的服务。
        //根据用户id查询收货地址列表
        //从cookie中取商品列表
        List<TbItem> cartList = getCartList(request);
        //传递给页面
        request.setAttribute("cartList", cartList);
        //返回逻辑视图
        return "order-cart";
    }
    
    /**
     * 从cookie中取购物车列表
     * <p>Title: getCartList</p>
     * <p>Description: </p>
     * @param request
     * @return
     */
    private List<TbItem> getCartList(HttpServletRequest request) {
        //取购物车列表
        String json = CookieUtils.getCookieValue(request, TT_CART, true);
        //判断json是否为null
        if (StringUtils.isNotBlank(json)) {
            //把json转换成商品列表返回
            List<TbItem> list = JsonUtils.jsonToList(json, TbItem.class);
            return list;
        }
        return new ArrayList<>();
    }
}

但是测试的时候会跳回主页,这不是我们想要的,不信你试试~
如果是的话,请往下看!
在taotao-sso-web中可以看到这一段代码;js首先会去尝试获取从Controller端传过来的回调地址,如果取到了回调地址,那么登录成功后会跳转到回调地址,如果没有取到回调地址,那么登录成功后直接访问的便是淘淘商城首页,在上图中之所以我登录成功后访问到的是淘淘商城首页就是因为我们没有在PageController 当中添加回调地址。


image.png image.png

那么我们改造一下PageController

@Controller
public class PageController {


    @RequestMapping("/page/register")
    public String showRegister(){
        return "register";
    }

    @RequestMapping("/page/login")
    public String showLogin(String url, Model model){
        model.addAttribute("redirect",url);
        return "login";
    }
}

OK.跳转就完成了!

4.生产订单

image.png

可以看到表单的内容是隐藏的。我们可以根据表单的内容,来用一个对象来存储


image.png

我们分析下上图的表单,这个表单中包含了三张表的信息,其中<input type="hidden" name="paymentType" value="1"/>便是tb_order表中的付款类型字段,这里默认是1了,<c:forEach>遍历的是购物车列表,var="cart"表示单个购物车对象,varStatus="status"的用法如下所示

     varStatus属性可以方便我们实现一些与行数相关的功能,如:奇数行、偶数行差异;最后一行特殊处理等等。先就varStatus属性常用参数总结下:
${status.index}      输出行号,从0开始。
${status.count}      输出行号,从1开始。
${status.current}   当前这次迭代的(集合中的)项
${status.first}  判断当前项是否为集合中的第一项,返回值为true或false
${status.last}   判断当前项是否为集合中的最后一项,返回值为true或false
begin、end、step分别表示:起始序号,结束序号,跳跃步伐。

我们可以用一个List集合来表示商品列表的集合,一个orderShipping来表示;
我们在taotao-order-interface中存放这个对象,因为如果放common-utils的话,我们taotao-order已经依赖了common-utils工程了,如果再依赖就变成了相互依赖,这是行不通的!所以放taotao-order-interface中


image.png
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;
    }
}

业务逻辑:
1、接收表单的数据
2、生成订单id
3、向订单表插入数据。
4、向订单明细表插入数据
5、向订单物流表插入数据。
6、返回TaotaoResult。
返回值:TaotaoResult

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private TbOrderMapper orderMapper;
    @Autowired
    private TbOrderItemMapper orderItemMapper;
    @Autowired
    private TbOrderShippingMapper orderShippingMapper;
    @Autowired
    private JedisClient jedisClient;
    
    @Value("${ORDER_GEN_KEY}")
    private String ORDER_GEN_KEY;
    @Value("${ORDER_ID_BEGIN}")
    private String ORDER_ID_BEGIN;
    @Value("${ORDER_ITEM_ID_GEN_KEY}")
    private String ORDER_ITEM_ID_GEN_KEY;
    
    @Override
    public TaotaoResult createOrder(OrderInfo orderInfo) {
        // 1、接收表单的数据
        // 2、生成订单id
        if (!jedisClient.exists(ORDER_GEN_KEY)) {
            //设置初始值
            jedisClient.set(ORDER_GEN_KEY, ORDER_ID_BEGIN);
        }
        String orderId = jedisClient.incr(ORDER_GEN_KEY).toString();
        orderInfo.setOrderId(orderId);
        orderInfo.setPostFee("0");
        //1、未付款,2、已付款,3、未发货,4、已发货,5、交易成功,6、交易关闭
        orderInfo.setStatus(1);
        Date date = new Date();
        orderInfo.setCreateTime(date);
        orderInfo.setUpdateTime(date);
        // 3、向订单表插入数据。
        orderMapper.insert(orderInfo);
        // 4、向订单明细表插入数据
        List<TbOrderItem> orderItems = orderInfo.getOrderItems();
        for (TbOrderItem tbOrderItem : orderItems) {
            //生成明细id
            Long orderItemId = jedisClient.incr(ORDER_ITEM_ID_GEN_KEY);
            tbOrderItem.setId(orderItemId.toString());
            tbOrderItem.setOrderId(orderId);
            //插入数据
            orderItemMapper.insert(tbOrderItem);
        }
        // 5、向订单物流表插入数据。
        TbOrderShipping orderShipping = orderInfo.getOrderShipping();
        orderShipping.setOrderId(orderId);
        orderShipping.setCreated(date);
        orderShipping.setUpdated(date);
        orderShippingMapper.insert(orderShipping);
        // 6、返回TaotaoResult。
        return TaotaoResult.ok(orderId);
    }

}

image.png

可以到我们的拦截器,订单系统都完全跑起来了~

上一篇 下一篇

猜你喜欢

热点阅读