16、购物车结构说明、购物车模块搭建、购物陈商品列表空时添加新购物车、uuid作为未登录下的key、未登录购物车验证功能后端代码、购物车前端显示、数量增减、登录后购物车列表、合并登录和没登录的购物车

购物车结构说明

购物车java结构是List的集合形式。Cart中包含sellerId和sellerName以及List三个属性。

购物车模块搭建

在这里插入图片描述
一、搭建cart-interface模块,不使用骨架
在这里插入图片描述
二、搭建cart-service模块,使用骨架
1、在web-inf中添加web.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	version="2.5">	
	
	<!-- 加载spring容器 -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath*:spring/applicationContext*.xml</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	
	
</web-app>

2、在resources中添加文件夹以及配置文件
在这里插入图片描述
applicationContext-service.xml全文如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 访问dubbo要占用的当前主机端口,默认端口不写是20880 -->
    <dubbo:protocol name="dubbo" port="20887"></dubbo:protocol> 
	<dubbo:application name="myApplication-cart-service"/>  
    <dubbo:registry address="zookeeper://192.168.25.128:2181"/>
    <dubbo:annotation package="com.myApplication.cart.service.impl" />  
</beans>

3、在java文件夹中添加CartServiceImpl实现类
在这里插入图片描述
三、搭建cart-web模块
1、在web-inf的web.xml文件中添加springmvc配置和security配置
全文如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	version="2.5">
	<!-- 解决post乱码 -->
	<filter>
		<filter-name>CharacterEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>utf-8</param-value>
		</init-param>
		<init-param>
			<param-name>forceEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>CharacterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

	<servlet>
		<servlet-name>springmvc</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<!-- 指定加载的配置文件 ,通过参数contextConfigLocation加载 -->
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:spring/springmvc.xml</param-value>
		</init-param>
	</servlet>

	<servlet-mapping>
		<servlet-name>springmvc</servlet-name>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:spring/spring-security.xml</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<filter>
		<filter-name>springSecurityFilterChain</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>springSecurityFilterChain</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

	<welcome-file-list>
		<welcome-file>cart.html</welcome-file>
	</welcome-file-list>
</web-app>

2、在resources文件中添加文件夹及配置文件
在这里插入图片描述
spring-security.xml中配置security整合cas的配置,全文如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
	xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
						http://www.springframework.org/schema/beans/spring-beans.xsd
						http://www.springframework.org/schema/security 
						http://www.springframework.org/schema/security/spring-security.xsd">
	
	<http pattern="/css/**" security="none"></http>
	<http pattern="/js/**" security="none"></http>
	<http pattern="/img/**" security="none"></http>
	<http pattern="/plugins/**" security="none"></http>
	<http pattern="/cart.html" security="none"></http>	
	<!-- 添加购物车可以不用登录,存到cookie中  如果这样访问,未登录时获取name会崩 改在http中添加的第一句-->
	<!--<http pattern="/cart/*.do" security="none"></http>-->
	
	<!--   entry-point-ref  入口点引用 -->
	<http use-expressions="false" entry-point-ref="casProcessingFilterEntryPoint">
        <intercept-url pattern="/cart/*.do" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
        <intercept-url pattern="/**" access="ROLE_USER"/>   
        <csrf disabled="true"/>  
        <!-- custom-filter为过滤器, position 表示将过滤器放在指定的位置上,before表示放在指定位置之前  ,after表示放在指定的位置之后  -->           
        <custom-filter ref="casAuthenticationFilter"  position="CAS_FILTER" />      
        <custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER"/>  
        <custom-filter ref="singleLogoutFilter" before="CAS_FILTER"/>  
    </http>
    
  	<!-- CAS入口点 开始 -->
    <beans:bean id="casProcessingFilterEntryPoint" class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">  
        <!-- cas登录服务器登录URL -->  
        <beans:property name="loginUrl" value="http://localhost:8080/cas/login"/>
        <beans:property name="serviceProperties" ref="serviceProperties"/>  
    </beans:bean>      
    <beans:bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">  
        <!--service 配置自身工程的根地址+/login/cas   -->  
        <beans:property name="service" value="http://localhost:9107/login/cas"/>
    </beans:bean>  
    <!-- CAS入口点 结束 -->

    
    <!-- 认证过滤器 开始 -->
    <beans:bean id="casAuthenticationFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter">  
        <beans:property name="authenticationManager" ref="authenticationManager"/>  
    </beans:bean>  
		<!-- 认证管理器 -->
	<authentication-manager alias="authenticationManager">
		<authentication-provider  ref="casAuthenticationProvider">
		</authentication-provider>
	</authentication-manager>
		<!-- 认证提供者 -->
	<beans:bean id="casAuthenticationProvider"     class="org.springframework.security.cas.authentication.CasAuthenticationProvider">  
        <beans:property name="authenticationUserDetailsService">  
            <beans:bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">  
                <beans:constructor-arg ref="userDetailService" />  
            </beans:bean>  
        </beans:property>  
        <beans:property name="serviceProperties" ref="serviceProperties"/>  
        <!-- ticketValidator 为票据验证器 -->
        <beans:property name="ticketValidator">  
            <beans:bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">  
                <!-- 设置cas票据验证地址 -->
                <beans:constructor-arg index="0" value="http://localhost:8080/cas"/>
            </beans:bean>  
        </beans:property>  
        <beans:property name="key" value="an_id_for_this_auth_provider_only"/> 
    </beans:bean>        
     <!-- springScurity认证类 -->
	<beans:bean id="userDetailService" class="com.pinyougou.user.service.UserDetailServiceImpl"/>  
	
	<!-- 认证过滤器 结束 -->
	
	
	<!-- 单点登出  开始  -->     
    <beans:bean id="singleLogoutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter"/>          
    <beans:bean id="requestSingleLogoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">  
        <beans:constructor-arg value="http://localhost:8080/cas/logout?service=http://localhost:9107/"/>
        <beans:constructor-arg>  
            <beans:bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>  
        </beans:constructor-arg> 
        <!-- 将本地/logout/cas和 64行退出后的部分进行绑定 -->     
        <beans:property name="filterProcessesUrl" value="/logout/cas"/>  
    </beans:bean>  
    <!-- 单点登出  结束 -->  
	
</beans:beans>

springmvc.xml中配置引用的dubbo服务,全文如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

	<mvc:annotation-driven>
		<mvc:message-converters register-defaults="true">
			<bean
				class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
				<property name="supportedMediaTypes" value="application/json" />
				<property name="features">
					<array>
						<value>WriteMapNullValue</value>
						<value>WriteDateUseDateFormat</value>
					</array>
				</property>
			</bean>
		</mvc:message-converters>
	</mvc:annotation-driven>

	<!-- 引用dubbo 服务 -->
	<dubbo:application name="myApplication-cart-web" />
	<dubbo:registry address="zookeeper://192.168.25.128:2181" />
	<dubbo:annotation package="com.myApplication.cart.controller" />
</beans>

3、在java文件夹中添加controller以及用于用户验证的UserDetailServiceImpl
在这里插入图片描述
UserDetailServiceImpl中的全文如下:

//注意认证类的包名要和spring-security.xml文件中的包名一致
//该类可以拷贝shop-web子模块中的
//该类的目的已经不是为了进行用户认证,在调用该类前springSecurity已经从CAS做完认证后才调用,该类的执行只为了拿到角色"ROLE_USER"返回用户角色信息
public class UserDetailServiceImpl implements UserDetailsService {

	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		System.out.println("经过认证类:"+username);
		
		List<GrantedAuthority> authorities=new ArrayList();
		authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
		
		return new User(username,"",authorities);
	}
}

购物车商品列表添加新购物车

创建cart购物车pojo类
在这里插入图片描述
在CartServiceImpl实现类中添加新增方法(需要在interface中添加对应的方法略)
在这里插入图片描述
1、添加一个方法来判断新添加的购物车是否已经存在集合中
在这里插入图片描述
searchCartListBySellerId方法全文如下:

    //查找原来的集合中有没有将要添加的购物车
    private Cart searchCartListBySellerId(List<Cart> cartList, String sellerId) {
        for (Cart cart : cartList) {
            if (sellerId.equals(cart.getSellerId())) {
                return cart;
            }
        }
        return null;
    }

2、如果集合中没有要添加的购物车,创建购物车,并根据上一步查找到的item数据写入数据
在这里插入图片描述
3、创建第2步中的addOrderItemToList方法
在这里插入图片描述
4、当购物车集合中已经存在我们要添加的购物车
同样调用addOrderItemToList方法。
在这里插入图片描述

uuid作为未登录下的key

我们需要操控cookie来实现将uuid存储到cookie中。在common模块中引入工具类
在这里插入图片描述
CookieUtil中的全文如下:

package util;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

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


/**
 * 
 * Cookie 工具类
 *
 */
public final class CookieUtil {

    /**
     * 得到Cookie的值, 不编码
     * 
     * @param request
     * @param cookieName
     * @return
     */
    public static String getCookieValue(HttpServletRequest request, String cookieName) {
        return getCookieValue(request, cookieName, false);
    }

    /**
     * 得到Cookie的值,
     * 
     * @param request
     * @param cookieName
     * @return
     */
    public static String getCookieValue(HttpServletRequest request, String cookieName, boolean isDecoder) {
        Cookie[] cookieList = request.getCookies();
        if (cookieList == null || cookieName == null) {
            return null;
        }
        String retValue = null;
        try {
            for (int i = 0; i < cookieList.length; i++) {
                if (cookieList[i].getName().equals(cookieName)) {
                    if (isDecoder) {
                        retValue = URLDecoder.decode(cookieList[i].getValue(), "UTF-8");
                    } else {
                        retValue = cookieList[i].getValue();
                    }
                    break;
                }
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return retValue;
    }

    /**
     * 得到Cookie的值,
     * 
     * @param request
     * @param cookieName
     * @return
     */
    public static String getCookieValue(HttpServletRequest request, String cookieName, String encodeString) {
        Cookie[] cookieList = request.getCookies();
        if (cookieList == null || cookieName == null) {
            return null;
        }
        String retValue = null;
        try {
            for (int i = 0; i < cookieList.length; i++) {
                if (cookieList[i].getName().equals(cookieName)) {
                    retValue = URLDecoder.decode(cookieList[i].getValue(), encodeString);
                    break;
                }
            }
        } catch (UnsupportedEncodingException e) {
        	 e.printStackTrace();
        }
        return retValue;
    }

    /**
     * 设置Cookie的值 不设置生效时间默认浏览器关闭即失效,也不编码
     */
    public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
            String cookieValue) {
        setCookie(request, response, cookieName, cookieValue, -1);
    }

    /**
     * 设置Cookie的值 在指定时间内生效,但不编码
     */
    public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
            String cookieValue, int cookieMaxage) {
        setCookie(request, response, cookieName, cookieValue, cookieMaxage, false);
    }

    /**
     * 设置Cookie的值 不设置生效时间,但编码
     */
    public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
            String cookieValue, boolean isEncode) {
        setCookie(request, response, cookieName, cookieValue, -1, isEncode);
    }

    /**
     * 设置Cookie的值 在指定时间内生效, 编码参数
     */
    public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
            String cookieValue, int cookieMaxage, boolean isEncode) {
        doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, isEncode);
    }

    /**
     * 设置Cookie的值 在指定时间内生效, 编码参数(指定编码)
     */
    public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
            String cookieValue, int cookieMaxage, String encodeString) {
        doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, encodeString);
    }

    /**
     * 删除Cookie带cookie域名
     */
    public static void deleteCookie(HttpServletRequest request, HttpServletResponse response,
            String cookieName) {
        doSetCookie(request, response, cookieName, "", -1, false);
    }

    /**
     * 设置Cookie的值,并使其在指定时间内生效
     * 
     * @param cookieMaxage cookie生效的最大秒数
     */
    private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response,
            String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) {
        try {
            if (cookieValue == null) {
                cookieValue = "";
            } else if (isEncode) {
                cookieValue = URLEncoder.encode(cookieValue, "utf-8");
            }
            Cookie cookie = new Cookie(cookieName, cookieValue);
            if (cookieMaxage > 0)
                cookie.setMaxAge(cookieMaxage);
            if (null != request) {// 设置域名的cookie
            	String domainName = getDomainName(request);
            	System.out.println(domainName);
                if (!"localhost".equals(domainName)) {
                	cookie.setDomain(domainName);
                }
            }
            cookie.setPath("/");
            response.addCookie(cookie);
        } catch (Exception e) {
        	 e.printStackTrace();
        }
    }

    /**
     * 设置Cookie的值,并使其在指定时间内生效
     * 
     * @param cookieMaxage cookie生效的最大秒数
     */
    private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response,
            String cookieName, String cookieValue, int cookieMaxage, String encodeString) {
        try {
            if (cookieValue == null) {
                cookieValue = "";
            } else {
                cookieValue = URLEncoder.encode(cookieValue, encodeString);
            }
            Cookie cookie = new Cookie(cookieName, cookieValue);
            if (cookieMaxage > 0)
                cookie.setMaxAge(cookieMaxage);
            if (null != request) {// 设置域名的cookie
            	String domainName = getDomainName(request);
            	System.out.println(domainName);
                if (!"localhost".equals(domainName)) {
                	cookie.setDomain(domainName);
                }
            }
            cookie.setPath("/");
            response.addCookie(cookie);
        } catch (Exception e) {
        	 e.printStackTrace();
        }
    }

    /**
     * 得到cookie的域名
     */
    private static final String getDomainName(HttpServletRequest request) {
        String domainName = null;

        String serverName = request.getRequestURL().toString();
        if (serverName == null || serverName.equals("")) {
            domainName = "";
        } else {
            serverName = serverName.toLowerCase();
            serverName = serverName.substring(7);
            final int end = serverName.indexOf("/");
            serverName = serverName.substring(0, end);
            final String[] domains = serverName.split("\\.");
            int len = domains.length;
            if (len > 3) {
                // www.xxx.com.cn
                domainName = "." + domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1];
            } else if (len <= 3 && len > 1) {
                // xxx.com or xxx.cn
                domainName = "." + domains[len - 2] + "." + domains[len - 1];
            } else {
                domainName = serverName;
            }
        }

        if (domainName != null && domainName.indexOf(":") > 0) {
            String[] ary = domainName.split("\\:");
            domainName = ary[0];
        }
        return domainName;
    }

}

在CartController中添加 获取uuid的方法getUuid:

    public String getUuid() {
        String uuid = CookieUtil.getCookieValue(request, "uuid", "utf-8");
        if (uuid == null || uuid.equals("")) {
            uuid = UUID.randomUUID().toString();
            CookieUtil.setCookie(request, response, "uuid", uuid, 48 * 60 * 60, "utf-8");
        }
        return uuid;
    }

未登录购物车验证功能后端代码

1、需要判断是否已经登录。需要修改springSecurity.xml文件,释放静态资源的方式不能是,这样的话,在后端通过security框架获取用户名访问的配置。
在这里插入图片描述
2、在后端判断是否登录,将购物车集合存入redis中。
如果没有登录,通过security框架获取到的是‘’anonymousUser‘’。
在这里插入图片描述

购物车前端显示

调用下面的findCartList方法。
前端操作。

前端数量增减实现

附:
js文件的controller全文如下:

app.controller('cartController',function ($scope,cartService) {

    //获取购物车列表
    $scope.findCartList =function () {
        cartService.findCartList().success(
            function (response) {
                $scope.cartList = response;
            }
        )
    }

    //添加商品到购物车列表
    $scope.addItemToCartList = function (itemId,num) {
        cartService.addItemToCartList(itemId,num).success(
            function (response) {
                if(response.success){
                    $scope.findCartList(); //刷新列表
                }else{
                    alert(response.message);
                }
            }
        )
    }
})

附:js文件的service全文如下:

app.service('cartService',function ($http) {
    //获取购物车列表
    this.findCartList = function () {
        return $http.get('cart/findCartList.do');
    }

    //添加商品到购物车
    //cart/addItemToCartList.do?itemId=1369360&num=1
    this.addItemToCartList = function (itemId,num) {
        return $http.get('cart/addItemToCartList.do?itemId='+itemId+"&num="+num);
    }
})

登录后购物车列表

在这里插入图片描述

合并登录和没登录的购物车

添加一个合并两个购物车集合的方法mergeCartList
在这里插入图片描述
在controller类中通过判断,操作是否合并。如果未登录状态没有添加购物车,就不需要合并。
在这里插入图片描述
实现上边引用的两个方法,一个是添加到redis中,一个是从redis中删除。
在这里插入图片描述
在这里插入图片描述

附:
后端控制器CartController全文如下:

@RestController
@RequestMapping("/cart")
public class CartController {

    @Reference
    private CartService cartService;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private HttpServletResponse response;

    public String getUuid() {
        String uuid = CookieUtil.getCookieValue(request, "uuid", "utf-8");
        if (uuid == null || uuid.equals("")) {
            uuid = UUID.randomUUID().toString();
            CookieUtil.setCookie(request, response, "uuid", uuid, 48 * 60 * 60, "utf-8");
        }
        return uuid;
    }

    @RequestMapping("/addItemToCartList")
    public Result addItemToCartList(Long itemId, Integer num) {
        try {
            //通过在springSecurity.xml中的配置,如果是未登录状态的访问,返回值是anonymousUser
            String uuid = SecurityContextHolder.getContext().getAuthentication().getName();
            if ("anonymousUser".equals(uuid)) {       //未登录的状态
                uuid = getUuid();
            }
            //如果未登录
            //String uuid = getUuid();
            List<Cart> cartList = cartService.findCartListFromRedis(uuid);
            cartList = cartService.addItemToCartList(cartList, itemId, num);
            //将新数据保存回redis缓存中
            cartService.saveCartListToRedis(uuid, cartList);
            return new Result(true, "添加购物车成功!");
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false, "添加购物车失败!");
        }
    }

    @RequestMapping("/findCartList")
    public List<Cart> findCartList() {
        //通过在springSecurity.xml中的配置,如果是未登录状态的访问,返回值是anonymousUser
        String loginName = SecurityContextHolder.getContext().getAuthentication().getName();
        String uuid = getUuid();
        //获取未登录的购物车
        List<Cart> cartList = cartService.findCartListFromRedis(uuid);
        if (!"anonymousUser".equals(loginName)) {       //已经登录的状态  需要合并
            //从redis中获取购物车(登录的购物车)
            List<Cart> cartListLogin = cartService.findCartListFromRedis(loginName);
            if (cartList.size() > 0) {      //当未登录状态时存在购物车数据才合并,然后将合并后的数据存入到redis中
                cartList = cartService.mergeCartList(cartList, cartListLogin);

                cartService.saveCartListToRedis(loginName, cartList);

                //将购物车从redis中删除
                cartService.delCartListToRedis(uuid);

            } else {    //如果不需要合并,直接让cartList等于cartListLogin,返回。
                cartList = cartListLogin;
            }

        }
        return cartList;
    }
}

附:后端CartService全文如下:

public interface CartService {
    // 添加商品到购物车列表(1.要加商品的列表  2.加入商品的id  3.加入商品数量)
    public List<Cart> addItemToCartList(List<Cart> cartList, Long itemId, Integer num);

    //从redis缓存中查找购物车集合
    public List<Cart> findCartListFromRedis(String name);

    //将购物车集合保存到redis中
    public void saveCartListToRedis(String name,List<Cart> cartList);

    //合并购物车
    public List<Cart> mergeCartList(List<Cart> cartList1, List<Cart> cartList2) ;

    //删除未登录状态的购物车
    public void delCartListToRedis(String key);
}

附:后端CartServiceImpl全文如下:

@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private TbItemMapper itemMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public List<Cart> addItemToCartList(List<Cart> cartList, Long itemId, Integer num) {


        //根据itemID获取item对象
        TbItem item = itemMapper.selectByPrimaryKey(itemId);

        //查找之前的购物车集合中是否已经存在要添加的购物车
        Cart cart = searchCartListBySellerId(cartList, item.getSellerId());

        if (cart == null) { //如果之前的购物车集合中没有要添加的购物车
            cart = new Cart();//创建一个购物车
            cart.setSellerId(item.getSellerId());
            cart.setSellerName(item.getSeller());

            List<TbOrderItem> orderItemList = new ArrayList<>();
            orderItemList = addOrderItemToList(orderItemList, item, num);
            cart.setOrderItemList(orderItemList);

            cartList.add(cart);
        } else {      //在之前的购物车中已经有要添加的购物车
            List<TbOrderItem> orderItemList = addOrderItemToList(cart.getOrderItemList(), item, num);
            cart.setOrderItemList(orderItemList);
            //cartList.add(cart);//此处不需要再添加


            //如果购物车中的购物明细的数量小于等于0,移除这个购物车
            if (cart.getOrderItemList().size() <= 0) {
                    cartList.remove(cart);
            }
        }





        return cartList;
    }



    //查找原来的集合中有没有将要添加的购物车
    private Cart searchCartListBySellerId(List<Cart> cartList, String sellerId) {
        for (Cart cart : cartList) {
            if (sellerId.equals(cart.getSellerId())) {
                return cart;
            }
        }
        return null;
    }

    //将orderItem添加进集合中
    private List<TbOrderItem> addOrderItemToList(List<TbOrderItem> orderItemList, TbItem item, Integer num) {
        if (orderItemList.size() > 0) {     //如果集合中有数据,说明不是新创建,判断是否存在要添加的数据
            for (TbOrderItem orderItem : orderItemList) {
                if (item.getId().equals(orderItem.getItemId())) {    //说明集合中已经有要添加的数据
                    //直接进行数量的累加
                    orderItem.setNum(orderItem.getNum() + num);
                    //总价格的修改
                    orderItem.setTotalFee(new BigDecimal(orderItem.getNum() * orderItem.getPrice().doubleValue()));

                    //如果num的数量小于等于0,移除这条orderItem
                    if(orderItem.getNum()<=0){
                        orderItemList.remove(orderItem);
                    }

                    //将集合返回
                    return orderItemList;
                }
            }
        }

        //说明购物车集合是新创建的,或者是集合中没有找到要添加的数据,需要创建新的orderItem数据
        TbOrderItem orderItem = new TbOrderItem();

        orderItem.setItemId(item.getId());
        orderItem.setNum(num);
        orderItem.setGoodsId(item.getGoodsId());
        orderItem.setPicPath(item.getImage());
        orderItem.setTitle(item.getTitle());
        orderItem.setPrice(item.getPrice());
        orderItem.setSellerId(item.getSellerId());
        orderItem.setTotalFee(new BigDecimal(orderItem.getNum() * orderItem.getPrice().doubleValue()));

        orderItemList.add(orderItem);

        return orderItemList;
    }

    //根据name从redis中获取购物车集合
    @Override
    public List<Cart> findCartListFromRedis(String name) {
        List<Cart> cartList = (ArrayList<Cart>) redisTemplate.boundHashOps("cartList").get(name);
        if (cartList == null){
            cartList = new ArrayList<Cart>();
        }
        return cartList;
    }

    //将购物车集合保存到redis中
    @Override
    public void saveCartListToRedis(String name,List<Cart> cartList){
        redisTemplate.boundHashOps("cartList").put(name, cartList);
    }

    //用来合并两个购物车(未登录状态的和已登录状态的
    @Override
    public List<Cart> mergeCartList(List<Cart> cartList1, List<Cart> cartList2) {
        for(Cart cart: cartList2){
            //需要一件一件的合并相同商品的数量
            for(TbOrderItem orderItem:cart.getOrderItemList()){
                cartList1= addItemToCartList(cartList1,orderItem.getItemId(),orderItem.getNum());
            }
        }
        return cartList1;
    }
    @Override
    public void delCartListToRedis(String key){
        //System.out.println("删除redis购物车数据....."+key);
        redisTemplate.boundHashOps("cartList").delete(key);
    }

}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值