zoukankan      html  css  js  c++  java
  • SSM商城项目(十二)

    1.   学习计划

    1、购物车实现

    2、未登录状态下使用购物车

    3、登录状态下使用购物车

    2.   购物车的实现

    2.1. 功能分析

    1、购物车是一个独立的表现层工程。

    2、添加购物车不要求登录。可以指定购买商品的数量。

    3、展示购物车列表页面

    4、修改购物车商品数量

    5、删除购物车商品

    2.2. 工程搭建

    可以参考e3-content创建。

    e3-car(聚合工程pom)

    |--e3-car-interface(jar)

    |--e3-car-Service(war)

    e3-car-web(war)

    3.   未登录状态下使用购物车

    3.1. 添加购物车

    3.1.1.    功能分析

    在不登陆的情况下也可以添加购物车。把购物车信息写入cookie。

    优点:

    1、不占用服务端存储空间

    2、用户体验好。

    3、代码实现简单。

    缺点:

    1、cookie中保存的容量有限。最大4k

    2、把购物车信息保存在cookie中,更换设备购物车信息不能同步。

    改造商品详情页面

    请求的url:/cart/add/{itemId}

    参数:

    1)商品id: Long itemId
    2)商品数量: int num

    业务逻辑:

    1、从cookie中查询商品列表。

    2、判断商品在商品列表中是否存在。

    3、如果存在,商品数量相加。

    4、不存在,根据商品id查询商品信息。

    5、把商品添加到购车列表。

    6、把购车商品列表写入cookie。

    返回值:逻辑视图

    Cookie保存购物车

    1)key:TT_CART

    2)Value:购物车列表转换成json数据。需要对数据进行编码。

    3)Cookie的有效期:保存7天。

    商品列表:

    List<TbItem>,每个商品数据使用TbItem保存。当根据商品id查询商品信息后,取第一张图片保存到image属性中即可。

    读写cookie可以使用CookieUtils工具类实现。

    3.1.2.    Controller

    @Controller
    public class CarController {
        
        @Value("${CART_EXPIRE}")
        private Integer CART_EXPIRE;
    
        @Autowired
        private ItemService itemService;
        
        @RequestMapping("/cart/add/{itemId}")
        public String addCartItem(@PathVariable Long itemId, Integer num,
                HttpServletRequest request, HttpServletResponse response) {
            // 1、从cookie中查询商品列表。
            List<TbItem> cartList = getCartList(request);
            // 2、判断商品在商品列表中是否存在。
            boolean hasItem = false;
            for (TbItem tbItem : cartList) {
                //对象比较的是地址,应该是值的比较
                if (tbItem.getId() == itemId.longValue()) {
                    // 3、如果存在,商品数量相加。
                    tbItem.setNum(tbItem.getNum() + num);
                    hasItem = true;
                    break;
                }
            }
            if (!hasItem) {
                // 4、不存在,根据商品id查询商品信息。
                TbItem tbItem = itemService.getItemById(itemId);
                //取一张图片
                String image = tbItem.getImage();
                if (StringUtils.isNoneBlank(image)) {
                    String[] images = image.split(",");
                    tbItem.setImage(images[0]);
                }
                //设置购买商品数量
                tbItem.setNum(num);
                // 5、把商品添加到购车列表。
                cartList.add(tbItem);
            }
            // 6、把购车商品列表写入cookie。
            CookieUtils.setCookie(request, response, "car", JsonUtils.objectToJson(cartList), CART_EXPIRE, true);
            return "cartSuccess";
        }
        
        /**
         * 从cookie中取购物车列表
         * <p>Title: getCartList</p>
         * <p>Description: </p>
         * @param request
         * @return
         */
        private List<TbItem> getCartList(HttpServletRequest request) {
            //取购物车列表
            String json = CookieUtils.getCookieValue(request, "car", true);
            //判断json是否为null
            if (StringUtils.isNotBlank(json)) {
                //把json转换成商品列表返回
                List<TbItem> list = JsonUtils.jsonToList(json, TbItem.class);
                return list;
            }
            return new ArrayList<>();
        }
        
    }

    3.2. 展示购物车商品列表

    请求的url:/cart/cart

    参数:无

    返回值:逻辑视图

    业务逻辑:

    1、从cookie中取商品列表。

    2、把商品列表传递给页面。

     Controller

        @RequestMapping("/cart/cart")
        public String showCartList(HttpServletRequest request, Model model) {
            //取购物车商品列表
            List<TbItem> cartList = getCartList(request);
            //传递给页面
            model.addAttribute("cartList", cartList);
            return "cart";
        }

    3.3. 修改购物车商品数量

    3.3.1.    功能分析

    1、在页面中可以修改商品数量

    2、重新计算小计和总计。

    3、修改需要写入cookie。

    4、每次修改都需要向服务端发送一个ajax请求,在服务端修改cookie中的商品数量。

     

    请求的url:/cart/update/num/{itemId}/{num}

    参数:long itemId、int num

    业务逻辑:

    1、接收两个参数

    2、从cookie中取商品列表

    3、遍历商品列表找到对应商品

    4、更新商品数量

    5、把商品列表写入cookie。

    6、响应e3Result。Json数据。

    返回值:

     e3Result。Json数据

    3.3.2.    Controller

    /*修改购物车商品数量*/
        @RequestMapping("/cart/update/num/{itemId}/{num}")
        public E3Result updateNum(@PathVariable Long itemId,@PathVariable Integer num,HttpServletRequest request,HttpServletResponse response){
            //从cookie中查询商品列表。
            List<TbItem> cartList = getCartList(request);
            for (TbItem tbItem : cartList) {
                if(tbItem.getId()==itemId.longValue()){
                    tbItem.setNum(num);
                }
            }
            CookieUtils.setCookie(request, response, "car", JsonUtils.objectToJson(cartList), CART_EXPIRE, true);
            return E3Result.ok();
        }

    3.3.3.    解决请求*.html后缀无法返回json数据的问题

    在springmvc中请求*.html不可以返回json数据。

    修改web.xml,添加url拦截格式。

    </servlet-mapping>
            <servlet-mapping>
            <servlet-name>e3-car-web</servlet-name>
            <url-pattern>*.action</url-pattern>
    </servlet-mapping>

    3.4. 删除购物车商品

    3.4.1.    功能分析

    请求的url:/cart/delete/{itemId}

    参数:商品id

    返回值:展示购物车列表页面。Url需要做redirect跳转。

    业务逻辑:

    1、从url中取商品id

    2、从cookie中取购物车商品列表

    3、遍历列表找到对应的商品

    4、删除商品。

    5、把商品列表写入cookie。

    6、返回逻辑视图:在逻辑视图中做redirect跳转。

    3.4.2.    Controller

        @RequestMapping("/cart/delete/{itemId}")
        public String deleteCarItem(@PathVariable Long itemId,HttpServletRequest request,HttpServletResponse response){
            //从cookie中查询商品列表。
                    List<TbItem> cartList = getCartList(request);
                    for (TbItem tbItem : cartList) {
                        if(tbItem.getId()==itemId.longValue()){
                            cartList.remove(tbItem);
                            break;
                        }
                    }
            CookieUtils.setCookie(request, response, "car", JsonUtils.objectToJson(cartList), CART_EXPIRE, true);
            return "redirect:/cart/cart.html";
        }

    3.5. 小结

    使用cookie实现购物车:

    优点:

    1、实现简单

    2、不需要占用服务端存储空间。

    缺点:

    1、存储容量有限

    2、更换设备购车信息不能同步。

    实现购车商品数据同步:

    1、要求用户登录。

    2、把购物车商品列表保存到数据库中。推荐使用redis。

    3、Key:用户id,value:购车商品列表。推荐使用hash,hash的field:商品id,value:商品信息。

    4、在用户未登录情况下写cookie。当用户登录后,访问购物车列表时,

    a)         把cookie中的数据同步到redis。

    b)        把cookie中的数据删除

    c)         展示购物车列表时以redis为准。

    d)        如果redis中有数据cookie中也有数据,需要做数据合并。相同商品数量相加,不同商品添加一个新商品。

    5、如果用户登录状态,展示购物车列表以redis为准。如果未登录,以cookie为准。

    4.   登录状态下使用购物车

    4.1. 功能分析

    1、购物车数据保存的位置:

    未登录状态下,把购物车数据保存到cookie中。

    登录状态下,需要把购物车数据保存到服务端。需要永久保存,可以保存到数据库中。可以把购物车数据保存到redis中。

    2、redis使用的数据类型

      a)使用hash数据类型

      b)Hash的Key应该是用户id。Hash中的field是商品id,value可以把商品信息转成json

    3、添加购物车

      登录状态下直接把商品数据保存到redis中。

      未登录状态保存到cookie中。

    4、如何判断是否登录

      a)从cookie中取token

      b)取不到未登录

      c)取到token,到redis中查询token是否过期

      d)如果过期,未登录状态

      e)没过期,登录状态

    4.2. 判断用户是否登录

    4.2.1.   功能分析

    应该使用拦截器实现。

    1、实现一个HandlerInterceptor接口。

    2、在执行handler方法之前做业务处理

    3、从cookie中取token。使用CookieUtils工具类实现。

    4、没有取到token,用户未登录,放行。

    5、取到token,调用sso系统的服务,根据token查询用户信息。

    6、没有返回用户信息。登录已经过期,未登录,放行。

    7.返回用户信息。用户是登录状态。可以把用户对象保存到request中,在Controller中可以通过判断request中是否包含用户对象,确定是否为登录状态。

    4.2.2.   拦截器

    pom.xml

            <dependency>
                <groupId>cn.e3mall</groupId>
                <artifactId>e3-sso-interface</artifactId>
                <version>0.0.1-SNAPSHOT</version>
            </dependency>

    引用服务

        <dubbo:reference interface="cn.e3mall.sso.service.TokenService" id="tokenService" /> 
    public class LoginInterceptor implements HandlerInterceptor{
    
        @Autowired
        private TokenService tokenService;
        
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            // 前处理,执行handler之前执行此方法
            //返回true,放行   false:拦截
            //从cookie中取token
            String token=CookieUtils.getCookieValue(request, "token");
            //如果没有token,未登录,直接放行
            if(StringUtils.isBlank(token)){
                return true;
            }
            //取到token,需要调用sso的服务,根据token取用户信息
            E3Result e3Result = tokenService.getUserByToken(token);
            //没有取到,登录过期,放行。
            if(e3Result.getStatus()!=200){
                return true;
            }
            //取到用户信息,登录状态。
            TbUser user = (TbUser) e3Result.getData();
            //把用户信息放到request中。只需要在Controller中判断request中是否包含user信息,放行
            request.setAttribute("user", user);
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                ModelAndView modelAndView) throws Exception {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
                throws Exception {
            // TODO Auto-generated method stub
            
        }
    
    }

    4.2.3.   配置拦截器

        <!-- 拦截器配置 -->
        <mvc:interceptors>
            <mvc:interceptor>
                <mvc:mapping path="/**"/>
                <bean class="cn.e3mall.car.interceptor.LoginInterceptor"></bean>
            </mvc:interceptor>
        </mvc:interceptors>

    4.3. 添加购物车

    4.3.1.   Service

    @Service
    public
    class CartServiceImpl implements CartService{ @Autowired private JedisClient jedisClient; @Autowired private TbItemMapper itemMapper; @Override public E3Result addCart(long userId, long itemId, int num) { //判断商品是否存在 Boolean hexists = jedisClient.hexists("Cart:" + userId, itemId + ""); //如果存在数量相加 if (hexists) { String json = jedisClient.hget("Cart:" + userId, itemId + ""); //把json转换成TbItem TbItem item = JsonUtils.jsonToPojo(json, TbItem.class); item.setNum(item.getNum() + num); //写回redis jedisClient.hset("Cart:" + userId, itemId + "", JsonUtils.objectToJson(item)); return E3Result.ok(); } //如果不存在,根据商品id取商品信息 TbItem item = itemMapper.selectByPrimaryKey(itemId); //设置购物车数据量 item.setNum(num); //取一张图片 String image = item.getImage(); if (StringUtils.isNotBlank(image)) { item.setImage(image.split(",")[0]); } //添加到购物车列表 jedisClient.hset("Cart:" + userId, itemId + "", JsonUtils.objectToJson(item)); return E3Result.ok(); } }

    发布服务

    <dubbo:service interface="cn.e3mall.car.service.CartService" ref="cartServiceImpl" timeout="600000"/>

    4.3.2.   Controller

     

    引用服务 

     <dubbo:reference interface="cn.e3mall.car.service.CartService" id="cartService" /> 

    4.4. 展示购物车

    4.4.1.   Service

        @Override
        public E3Result mergeCart(long userId, List<TbItem> itemList) {
            //遍历商品列表
            //把列表添加到购物车
            //判断购物车是否有此商品
            //如果有, 数量相加
            //如果没有,添加新的商品
            for (TbItem tbItem : itemList) {
                addCart(userId, tbItem.getId(), tbItem.getNum());
            }
            return E3Result.ok();
        }
    
        //获得购物车列表
        @Override
        public List<TbItem> getCartList(long userId) {
            //根据用户id查询购物车列表
            List<String> jsonList = jedisClient.hvals("Cart:" + userId);
            ArrayList<TbItem> itemList = new ArrayList<>();
            for (String string : jsonList) {
                TbItem item = JsonUtils.jsonToPojo(string, TbItem.class);
                itemList.add(item);
            }
            return itemList;
        }

    4.4.2.   Controller

    @RequestMapping("/cart/cart")
        public String showCartList(HttpServletRequest request, HttpServletResponse response,Model model) {
            //从cookie中取购物车列表
            List<TbItem> cartList = getCartList(request);
            //判断用户是否为登录状态
            TbUser user = (TbUser) request.getAttribute("user");
            //如果是登录状态
            if (user != null) {
                //从cookie中取购物车列表
                //如果不为空,把cookie中的购物车商品和服务端的购物车商品合并。
                cartService.mergeCart(user.getId(), cartList);
                //把cookie中的购物车删除
                CookieUtils.deleteCookie(request, response, "cart");
                //从服务端取购物车列表
                cartList = cartService.getCartList(user.getId());
                
            }
            //传递给页面
            model.addAttribute("cartList", cartList);
            return "cart";
        }

    4.5. 更新购物车数量

    4.5.1.   Service

        @Override
        public E3Result updateCart(long userId, long itemId, int num) {
            //从redis中取商品信息
            String json = jedisClient.hget("Cart:" + userId, itemId + "");
            //更新商品数量
            TbItem tbItem = JsonUtils.jsonToPojo(json, TbItem.class);
            tbItem.setNum(num);
            //写入redis
            jedisClient.hset("Cart:" + userId, itemId + "",JsonUtils.objectToJson(tbItem));
            return E3Result.ok();
        }

    4.5.2.   Controller

    4.6. 删除购物车

    4.6.1.   Service

        @Override
        public E3Result deleteCartItem(long userId, long itemId) {
            //删除购物车商品
            jedisClient.hdel("Cart:" + userId, itemId + "");
            return E3Result.ok();
        }

    4.6.2.   Controller

  • 相关阅读:
    cmd 进入mysql 小技巧
    【scikit-learn】交叉验证及其用于參数选择、模型选择、特征选择的样例
    向txt文件中写入换行
    CTabCtrl的使用
    unicode下数据之间的转换
    下载数据库包
    python3.5.1语法
    配置Python+selenium+firefox自动化测试
    使用Tesseract OCR识别验证码
    white的配置使用
  • 原文地址:https://www.cnblogs.com/huozhonghun/p/10167391.html
Copyright © 2011-2022 走看看