[Business Function Chapter 97] Microservice-springcloud-springboot-e-commerce shopping cart module-obtain the shopping cart information of the currently logged in user

Shopping cart function

1. Shopping cart module

1.Create cart service

  We need to first create a cart microservice, then add relevant dependencies, set configurations, and release annotations.

<dependencies>
        <dependency>
            <groupId>com.msb.mall</groupId>
            <artifactId>mall-commons</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

Then the configuration in the properties file

server.port=40000
spring.application.name=mall-cart

spring.cloud.nacos.discovery.server-addr=192.168.56.100:8848
spring.thymeleaf.cache=false

Then add the configuration of the configuration center: bootstrap.yml file

spring.application.name=mall-cart
spring.cloud.nacos.config.server-addr=192.168.56.100:8848

Release the annotations of the registration center

image.png

2.Nginx configuration

  First, specify the corresponding domain name in host in windows

image.png

Copy the corresponding static resources to the static/cart directory of Nginx

image.png

Then modify the Nginx configuration file

image.png

Then restart the nginx service

docker restart nginx

3. Configure gateway service

  When Nginx receives access to cart.msb.comthis domain name, it will reverse proxy the service to the gateway service. At this time, the gateway service needs to route the request to the shopping cart service. We need to modify the configuration of the gateway service

image.png

Finally, just adjust the path of the static resources in the template page.

image.png

Then start the service access

image.png

2. Shopping cart function

1. Shopping cart mode processing

  Discuss how data in the shopping cart is stored. We can see multiple items in the shopping cart

image.png

Then we can choose to store the corresponding data in Redis. We must carefully consider the corresponding data storage structure, because there are many records. If we use List to store

[

{
    
    skuId:1,subTile:'华为',price:666}

,{
    
    skuId:1,subTile:'华为',price:666}

,{
    
    skuId:1,subTile:'华为',price:666}

]

Then it will be more troublesome when we add, delete, and modify the number of products later. We need to take out the entire data in the List, then find the data we want to operate, and then write all the data back to Redis. This way Obviously not advisable, at this time we can consider hashing to store:

image.png

In this way, we can deal with it one by one, which will be more flexible than the above. Then the structure we store in the backend service is

Map<String,Map<String,CartItemVo>>

2. Shopping Cart VO

  For the information storage of the shopping cart, we create two corresponding VO objects.

package com.msb.mall.vo;

import java.math.BigDecimal;
import java.util.List;

/**
 * 购物车中的商品信息
 */
public class CartItem {
    
    

    // 商品的编号 SkuId
    private Long skuId;
    // 商品的图片
    private String image;
    // 商品的标题
    private String title;
    // 是否选中
    private boolean check = true;
    // 商品的销售属性
    private List<String> skuAttr;
    // 商品的单价
    private BigDecimal price;
    // 购买的数量
    private Integer count;
    // 商品的总价
    private BigDecimal totalPrice;

    public Long getSkuId() {
    
    
        return skuId;
    }

    public void setSkuId(Long skuId) {
    
    
        this.skuId = skuId;
    }

    public String getImage() {
    
    
        return image;
    }

    public void setImage(String image) {
    
    
        this.image = image;
    }

    public String getTitle() {
    
    
        return title;
    }

    public void setTitle(String title) {
    
    
        this.title = title;
    }

    public boolean isCheck() {
    
    
        return check;
    }

    public void setCheck(boolean check) {
    
    
        this.check = check;
    }

    public List<String> getSkuAttr() {
    
    
        return skuAttr;
    }

    public void setSkuAttr(List<String> skuAttr) {
    
    
        this.skuAttr = skuAttr;
    }

    public BigDecimal getPrice() {
    
    
        return price;
    }

    public void setPrice(BigDecimal price) {
    
    
        this.price = price;
    }

    public Integer getCount() {
    
    
        return count;
    }

    public void setCount(Integer count) {
    
    
        this.count = count;
    }

    public BigDecimal getTotalPrice() {
    
    
        // 商品的总价  price * count
        return price.multiply(new BigDecimal(count));
    }

}

Cart

package com.msb.mall.vo;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;

/**
 * 购物车
 */
public class Cart {
    
    
    // 购物车中的商品种类
    private Integer countType;

    // 选中的商品数量
    private Integer checkCountNum;

    // 选中商品的总价
    private BigDecimal totalAmount;

    // 购物中存储的商品信息
    private List<CartItem> items;

    public Integer getCountType() {
    
    
        return items.size();
    }


    public Integer getCheckCountNum() {
    
    
        Integer count = 0;
        for (CartItem item : items) {
    
    
            if (item.isCheck()){
    
    
                count += item.getCount();
            }
        }
        return count;
    }


    public BigDecimal getTotalAmount() {
    
    
        BigDecimal amount = new BigDecimal(0);
        for (CartItem item : items) {
    
    
            if (item.isCheck()){
    
    
                amount = amount.add(item.getTotalPrice());
            }
        }
        return amount;
    }


    public List<CartItem> getItems() {
    
    
        return items;
    }

    public void setItems(List<CartItem> items) {
    
    
        this.items = items;
    }
}

3. Certification information

  We need to query the corresponding shopping cart information in Redis based on the current login user information in the shopping cart service. First, we need to import the relevant dependencies of Redis, and at the same time, we need to use the SpringSession explained earlier to share the authenticated Session information.

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>

Add properties file information

server.port=40000
spring.application.name=mall-cart

spring.cloud.nacos.discovery.server-addr=192.168.56.100:8848
spring.thymeleaf.cache=false

spring.redis.host=192.168.56.100
spring.redis.port=6379
spring.thymeleaf.enabled=false

spring.session.store-type=redis
server.servlet.session.timeout=30m
spring.session.redis.namespace=spring:session

Add cookie configuration information

@Configuration
public class MySessionConfig {
    
    

    /**
     * 自定义Cookie的配置
     * @return
     */
    @Bean
    public CookieSerializer cookieSerializer(){
    
    
        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
        cookieSerializer.setDomainName("msb.com"); // 设置session对应的一级域名
        cookieSerializer.setCookieName("msbsession");
        return cookieSerializer;
    }

    /**
     * 对存储在Redis中的数据指定序列化的方式
     * @return
     */
    @Bean
    public RedisSerializer<Object> redisSerializer(){
    
    
        return new GenericJackson2JsonRedisSerializer();
    }
}

Add custom interceptor

/**
 * 我们自定义的拦截器:帮助我们获取当前登录的用户信息
 *     通过Session共享获取的
 */
public class AuthInterceptor implements HandlerInterceptor {
    
    
    // 本地线程对象  Map<thread,Object>
    public static ThreadLocal<MemberVO> threadLocal = new ThreadLocal();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
    
        // 通过HttpSession获取当前登录的用户信息
        HttpSession session = request.getSession();
        Object attribute = session.getAttribute(AuthConstant.AUTH_SESSION_REDIS);
        if(attribute != null){
    
    
            MemberVO memberVO = (MemberVO) attribute;
            threadLocal.set(memberVO);
        }
        return true;
    }
}

register interceptor

@Configuration
public class MyWebInterceptorConfig implements WebMvcConfigurer {
    
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    
    
        registry.addInterceptor(new AuthInterceptor()).addPathPatterns("/**");
    }
}

Then log in and access the controller service test

image.png

4. Page jump

  Click Add Shopping Cart from the product details page to complete the logic of adding a shopping cart.

image.png

5. Add shopping cart logic

  Specifically complete the logic of adding the shopping cart, and also the logic we want to implement after we obtain the SKUId and quantity of the product in the service.

image.png

Specific core code


    /**
     * 把商品添加到购物车中
     * @param skuId
     * @param num
     * @return
     */
    @Override
    public CartItem addCart(Long skuId, Integer num) throws Exception {
    
    
        BoundHashOperations<String, Object, Object> hashOperations = getCartKeyOperation();
        // 如果Redis存储在商品的信息,那么我们只需要修改商品的数量就可以了
        Object o = hashOperations.get(skuId.toString());
        if(o != null){
    
    
            // 说明已经存在了这个商品那么修改商品的数量即可
            String json = (String) o;
            CartItem item = JSON.parseObject(json, CartItem.class);
            item.setCount(item.getCount()+num);
            hashOperations.put(skuId.toString(),JSON.toJSONString(item));
            return item;
        }
        CartItem item = new CartItem();
        CompletableFuture future1 = CompletableFuture.runAsync(()->{
    
    
            // 1.远程调用获取 商品信息
            R r = productFeignService.info(skuId);
            String skuInfoJSON = (String) r.get("skuInfoJSON");
            SkuInfoVo vo = JSON.parseObject(skuInfoJSON,SkuInfoVo.class);
            item.setCheck(true);
            item.setCount(num);
            item.setPrice(vo.getPrice());
            item.setImage(vo.getSkuDefaultImg());
            item.setSkuId(skuId);
            item.setTitle(vo.getSkuTitle());
        },executor);

        CompletableFuture future2 = CompletableFuture.runAsync(()->{
    
    
            // 2.获取商品的销售属性
            List<String> skuSaleAttrs = productFeignService.getSkuSaleAttrs(skuId);
            item.setSkuAttr(skuSaleAttrs);
        },executor);

        CompletableFuture.allOf(future1,future2).get();
        // 3.把数据存储在Redis中
        String json = JSON.toJSONString(item);
        hashOperations.put(skuId.toString(),json);

        return item;
    }
        private BoundHashOperations<String, Object, Object> getCartKeyOperation() {
    
    
        // hash key: cart:1   skuId:cartItem
        MemberVO memberVO = AuthInterceptor.threadLocal.get();
        String cartKey = CartConstant.CART_PERFIX + memberVO.getId();
        BoundHashOperations<String, Object, Object> hashOperations = redisTemplate.boundHashOps(cartKey);
        return hashOperations;
    }

6. Shopping cart home page

  After adding products to the shopping cart, we can click checkout to enter the shopping cart page. Then we need to query the shopping cart product information of all currently logged in users in the background, and then display it on the page.

image.png

image.png

Then process the data in the page

image.png

image.png

Guess you like

Origin blog.csdn.net/studyday1/article/details/132676376