电商项目day17(跨域&订单)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wangwei_620/article/details/85287370

今日目标:

掌握跨域请求CORS
    完成结算页收货人地址选择功能
    完成结算页支付方式选择
    完成结算页商品清单功能
    保存订单功能

一.商品详情页跨域请求

1.购物车详情页面功能的对接

首先我们在模板中配置添加购物车的点击按钮,我们主要获得两个参数   itemId   和    num  

通过我们通过插值替换,获得商品的id   

我们在本地的静态工程中的controller中的js  中pageController.js编写方法添加购车车的方法,通过请求cart_web的工程

//添加商品到购物车
	$scope.addItemToCartList=function(){
		$http.get("http://localhost:8087/cart/addItemToCartList.do?itemId="+itemId+"&num="+$scope.num).success(function(response){
			if (response.success)
			{
				//添加购物车成功
				location.href="http://localhost:8087/cart.html";
			}else{
				alert(response.message);
			}
		})
	}

我们重新启动购物车相关服务   通过商品详情页面访问,点击添加购物车按钮,出现如下问题:

无法进行跨域访问

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin

域:包含;协议、域名、端口号  三种任意一个不同,就是涉及浏览器跨域问题。    
        http://www.demo.com/a.html
        https://www.demo.com/a.html    

        http://www.demo.com/a.html
        http://www.test.com/a.html        

        http://www.demo.com:8000/a.html
        http://www.demo.com/a.html            
        
    跨域大前提:请求方式是异步请求。ajax。 angularjs的$http发起的请求,全部是异步请求。

同步请求:
    location.href  <a href="">  form表单提交。

2.跨域请求的解决方案(三种解决方案)

   第一种:  jQuery:提供跨域解决方案,jsonp  原理:动态的生成<script>发起同步请求。
        
   第二种: CORS:w3c提供的“跨域资源共享”Cross-origin resource sharing

       它允许浏览器向跨源服务器,发出 XMLHttpRequest 请求,从而克服了 AJAX 只能同源使用的限制。整个 CORS 通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS 通信与同源的 AJAX 通信没有差别,代码完全一样。浏览器一旦发现 AJAX 请求跨
源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现 CORS 通信的关键是服务器。只要服务器实现了 CORS 接口,就可以跨源通信。

又上图我们可以看到,会进行两次请求和两次相应,主要方法是通过设置一些头信息

我们在controller层的添加购物车列表中编写两行代码:

response.setHeader("Access-Control-Allow-Origin", "http://localhost:9105");
response.setHeader("Access-Control-Allow-Credentials", "true");

Access-Control-Allow-Origin
Access-Control-Allow-Origin 是 HTML5 中定义的一种解决资源跨域的策略。
他是通过服务器端返回带有 Access-Control-Allow-Origin 标识的 Response header,用来解决资源的跨域权限问题。
使用方法,在 response 添加 Access-Control-Allow-Origin,例如
Access-Control-Allow-Origin:www.google.com
也可以设置为 * 表示该资源谁都可以用

      第三种方案:  springMVC跨域注解

我们只需要添加一个注解:   @CrossOrigin即可

注意:版本一定要高   4.2以上

我们服务器端允许了跨域的请求,我们必须客户端也开启跨域

如果我们不写上面的配置的话,浏览器则不发cookie

重新测试:

则跳转到购物车页面

二.订单结算页收件人功能展示

1.首先构建订单的模块   order_web   order_interface   order_service

复制address地址的相关文件

2.注意我们没有写order_web工程,直接在cart_web中编写,这样我们就不用重新创建工程,添加spring-security的安全框架

需求分析:

我们必须在AddressControlelr中编写通过用户id找对应的地址列表

/**
	 * 通过用户id查询用户对应的所有的地址
	 */
	@RequestMapping("findAddressListByUserId")
	public List<TbAddress> findAddressListByUserId(){
		//通过spring-security框架获得用户的id
		String userId = SecurityContextHolder.getContext().getAuthentication().getName();
		return addressService.findAddressListByUserId(userId);
	}

service层

/**
	 * 通过用户的id查询所对应的地址列表
	 * @param userId
	 * @return
	 */
	@Override
	public List<TbAddress> findAddressListByUserId(String userId) {
		//通过条件查询获得地址的列表
		TbAddressExample example = new TbAddressExample();
		Criteria criteria = example.createCriteria();
		criteria.andUserIdEqualTo(userId);
		List<TbAddress> addressList = addressMapper.selectByExample(example);
		return addressList;
	}

前台页面:

//通过用户的id查询用户的地址列表
    this.findAddressListByUserId=function(){
        return $http.get('address/findAddressListByUserId.do');
    }

orderController.js

 //发送请求,获得用户对应的地址信息
	$scope.findAddressListByUserId=function () {
		addressService.findAddressListByUserId().success(function (response) {
			$scope.addressList=response;
        })
    }

页面点击的,联动底层的寄送地址

前台实现:

 //展示收件人地址列表
    $scope.findAddressListByUserId=function () {
        addressService.findAddressListByUserId().success(function (response) {
            //收件人地址列表
            $scope.addressList=response;

            for(var i=0;i< $scope.addressList.length;i++){
                if($scope.addressList[i].isDefault=='1'){//默认收件人地址
                    $scope.address=$scope.addressList[i];
                    break;
                }
            }

            //如果没有设置默认收件人地址,取第一个地址为默认地址
            if($scope.address==null){
                $scope.address=$scope.addressList[0];
            }

        })
    }

    //定义寄送至的收件人地址对象
    $scope.address=null;

    //勾选默认收件人地址
    $scope.isSelected=function (addr) {
        if($scope.address==addr){
            return true;
        }else {
            return false;
        }
    }
    //跟改点击选中的状态然后我们,动态给address赋值
    $scope.updateSelected=function (addr) {
        $scope.address=addr;
    }

页面:

三.支付方式选择

思路分析:我们通过分析该项目由两种支付方式,分别是在线是否,通过传过来的值,我们通过传过来的值1或者2判断时那种支付方式

需求分析:

 //支付方式,
    //定义一个实体类
    $scope.entity={paymentType:"1"};
    $scope.updatePaymentType=function (type) {
        $scope.entity.paymentType=type;
    }

四.商品清单与金额显示

思路分析:其实这个功能我们在购物车详情页面已经实现了,findCartList()  所有我们直接用就可以了

六.保存清单

思路分析:

分布式id生成器,IDwork   这个是基于推特公司的开源算法,雪花算法

订单与商家关联:

          购物车结算时,如果有多个商家的商品,根据商家生成多个订单,

数据库表的分析:

注意:我们设计金钱的相关数据时,我们不能页面传递数据,只能后台组装.

随着订单的与日俱增,一台数据库无法满足订单,数据的保存,需要,搭建集群的方式,保存数据,主要考虑订单主键生成策略

四种方法:

第一种:UUID   缺点无法基于UUID生成主键,完成排序

第二种:oracle 的sequence (序列)

第三种:可以基于redis实现数字加一

第四种:开源框架,技术,分布式id生成器    twitter   基于雪花算法生成id

数据库表结构分析:

    tb_order 订单表
      `expire` datetime DEFAULT NULL COMMENT '过期时间,定期清理',  //基于定时任务框架定期清理无效订单 spring task  quartz
    
    后端组装数据
         `order_id` bigint(20) NOT NULL COMMENT '订单id',  //不是主键自增
         `payment` decimal(20,2) DEFAULT NULL COMMENT '实付金额。精确到2位小数;单位:元。如:200.07,表示:200元7分',
         `status` varchar(1) COLLATE utf8_bin DEFAULT NULL COMMENT '状态:1、未付款,2、已付款,3、未发货,4、已发货,5、交易成功,6、交易关闭,7、待评价',
         `create_time` datetime DEFAULT NULL COMMENT '订单创建时间',
         `update_time` datetime DEFAULT NULL COMMENT '订单更新时间',
         `user_id` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '用户id',
         `source_type` varchar(1) COLLATE utf8_bin DEFAULT NULL COMMENT '订单来源:1:app端,2:pc端,3:M端,4:微信端,5:手机qq端',
         `seller_id` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '商家ID',  //来着购物车
    页面提交数据
     `payment_type` varchar(1) COLLATE utf8_bin DEFAULT NULL COMMENT '支付类型,1、在线支付,2、货到付款',
      `receiver_area_name` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '收货人地区名称(省,市,县)街道',
      `receiver_mobile` varchar(12) COLLATE utf8_bin DEFAULT NULL COMMENT '收货人手机',
      `receiver` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '收货人',
    
tb_order_item  订单项表
     
          `id` bigint(20) NOT NULL,    //不是主键自增
          
          `order_id` bigint(20) NOT NULL COMMENT '订单id',    

保存订单实现流程:
        1、构建订单模块
        2、将代码生成器生成的订单相关代码拷贝到项目中
        3、组装订单数据
            1、根据用户名从redis中获取购物车列表
            
            2、构建订单数据(后台组装数据、前台页面传递数据)
        4、保存组装好的数据到数据库中

后台代码实现:

controller层,我们通过spring-cecurity获得用户id  

service层:

我们大多的数据从数据库中获得的,我们通过遍历购物车列表,每个购物车就是一个订单,我们自己创建订单,赋值,最后添加完后我们必须要删除redis数据库中的的购物车数据

 @Autowired
    private RedisTemplate redisTemplate;
	@Autowired
    private TbOrderItemMapper tbOrderItemMapper;
	/**
	 * 增加
	 */
	@Override
	public void add(TbOrder order) {
		//我们必须自己组装数据,很多的数据我们只能从购物车列表中获得,可能购物车中有两个商家,那么我么
		//要通过循环购物车列表来生成订单 ,从redis中获得购物车数据
        //订单与商家关联,订单数据有很多是来自购物车列表数据
        List<Cart> cartList = (List<Cart>) redisTemplate.boundValueOps(order.getUserId()).get();
        //循环购物车   ,组装订单  ,每个购物车列表就是一个订单
        for (Cart cart : cartList) {
            //构建订单对象
            TbOrder tbOrder = new TbOrder();
            /*
            `order_id` bigint(20) NOT NULL COMMENT '订单id',  //不是主键自增
		 `payment` decimal(20,2) DEFAULT NULL COMMENT '实付金额。精确到2位小数;单位:元。如:200.07,表示:200元7分',
		 `status` varchar(1) COLLATE utf8_bin DEFAULT NULL COMMENT '状态:1、未付款,2、已付款,3、未发货,4、已发货,5、交易成功,6、交易关闭,7、待评价',
		 `create_time` datetime DEFAULT NULL COMMENT '订单创建时间',
		 `update_time` datetime DEFAULT NULL COMMENT '订单更新时间',
		 `user_id` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '用户id',
		 `source_type` varchar(1) COLLATE utf8_bin DEFAULT NULL COMMENT '订单来源:1:app端,2:pc端,3:M端,4:微信端,5:手机qq端',
		 `seller_id` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '商家ID',  //来着购物车
             */
            //订单id的封装
            long orderId = idWorker.nextId();
            tbOrder.setOrderId(orderId);
            //订单状态封装
            tbOrder.setStatus("1");
            //创建订单时间
            tbOrder.setCreateTime(new Date());
            //创建跟新订单时间
            tbOrder.setUpdateTime(new Date());
            //用户id,因为我们在controller层已经封装 了,所以我们自己获得就行
            tbOrder.setUserId(order.getUserId());
            //订单来源
            tbOrder.setSourceType("2");
            //商家id
            tbOrder.setSellerId(cart.getSellerId());
            /*
            页面提交数据
	 `payment_type` varchar(1) COLLATE utf8_bin DEFAULT NULL COMMENT '支付类型,1、在线支付,2、货到付款',
	  `receiver_area_name` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '收货人地区名称(省,市,县)街道',
	  `receiver_mobile` varchar(12) COLLATE utf8_bin DEFAULT NULL COMMENT '收货人手机',
	  `receiver` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '收货人',
             */
            //支付类型的封装
            tbOrder.setPaymentType(order.getPaymentType());
            //收货人地址
            tbOrder.setReceiverAreaName(order.getReceiverAreaName());
            //收货人手机
            tbOrder.setReceiverMobile(order.getReceiverMobile());
            //收货人
            tbOrder.setReceiver(order.getReceiver());

            //遍历购物车明细数据,组装订单详情数据
            //我们主要后台组装数据   连个数据  其他的度,在购物车添加数据的时候已经组装好了
            List<TbOrderItem> orderItemList = cart.getOrderItemList();
            //定义一个费用统计的变量
            double payment = 0.00;
            for (TbOrderItem orderItem : orderItemList) {
                //  `id` bigint(20) NOT NULL,    //不是主键自增
              	    orderItem.setId(idWorker.nextId());
                //		  `order_id` bigint(20) NOT NULL COMMENT '订单id',
                    orderItem.setOrderId(orderId);
                    //获得费用
                    payment+=orderItem.getTotalFee().doubleValue();
                    //保存到orderItem中
                tbOrderItemMapper.insert(orderItem);

            }
            //payment  实付金额 我们不是前天传的,我们从后台算的
            tbOrder.setPayment(new BigDecimal(payment));
            //添加到订单表中
             orderMapper.insert(tbOrder);
        }
        //添加完,我们把redis中的购物车数据列表删除
        redisTemplate.boundHashOps("cartList").delete(order.getUserId());
	}

最后实现订单的添加

猜你喜欢

转载自blog.csdn.net/wangwei_620/article/details/85287370