SpringBoot使用redis结合mysql数据库(黑名单)渲染商品详情界面

目录

一、界面效果

二、前端代码

 三、后端代码(redis+blacklist)

3.1 ProducatController

3.2 ProductService

3.3 ProductDao

 3.4 映射文件


一、界面效果

二、前端代码

商品详情前端代码

<template>
  <van-nav-bar
    title="商品详情"
    left-text="返回"
    right-text="分享"
    left-arrow
    @click-left="onClickLeft"
    @click-right="onClickRight"
  />
  <van-swipe :autoplay="3000" lazy-render>
    <van-swipe-item v-for="image in product.img" :key="image">
      <img :src="image" style="width: 100%; height: 250px" @click="show" />
    </van-swipe-item>
  </van-swipe>
  <div class="Detail">
    <div class="price">
      <div>
        到手价¥<span>{{ product.price }}</span>
      </div>
    </div>
    <h4>{{ product.name }}</h4>
    <van-text-ellipsis
      rows="1"
      :content="product.subName"
      expand-text="展开"
      collapse-text="收起"
    />
  </div>
  <div class="warp">
    <van-tabs v-model:active="active" swipeable>
      <van-tab title="商品介绍">
        <div v-html="product.brief"></div>
      </van-tab>
      <van-tab title="规格参数"> 3333 </van-tab>
      <van-tab title="售后保障">
        <div>
          <div class="mod_tit_line">
            <h3>权利声明</h3>
          </div>
          京东商城上的所有商品信息、客户评价、商品咨询、网友讨论等内容,是京东商城重要的经营资源,未经许可,禁止非法转载使用。
          <div class="for_separator"></div>
          <p>
            <b>注:</b
            >本站商品信息均来自于厂商,其真实性、准确性和合法性由信息拥有者(厂商)负责。本站不提供任何保证,并不承担任何法律责任。
          </p>
        </div>
      </van-tab>
    </van-tabs>
  </div>
  <van-action-bar>
    <van-action-bar-icon icon="chat-o" text="客服" color="#ee0a24" />
    <van-action-bar-icon icon="cart-o" text="购物车" />
    <van-action-bar-icon icon="star" text="已收藏" color="#ff5000" />
    <van-action-bar-button type="warning" text="加入购物车" />
    <van-action-bar-button type="danger" text="立即购买" />
  </van-action-bar>
  <van-share-sheet
    v-model:show="showShare"
    title="立即分享给好友"
    :options="options"
    @select="onSelect"
  />
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { showToast } from "vant";
import { useRoute, useRouter } from "vue-router";
import { productApi } from "@/api/index";
import { showImagePreview } from "vant";

const onClickLeft = () => history.back();
const onClickRight = () => {
  showShare.value = true;
};
const active = ref(0);
const route = useRoute();

onMounted(() => {
  callDetail();
});
const showShare = ref(false);
const options = [
  { name: "微信", icon: "wechat" },
  { name: "微博", icon: "weibo" },
  { name: "复制链接", icon: "link" },
  { name: "分享海报", icon: "poster" },
  { name: "二维码", icon: "qrcode" },
];

const onSelect = (option) => {
  showToast(option.name);
  showShare.value = false;
};
const show = () => {
  showImagePreview({
    images: product.value.img.split(","),
  });
};
const callDetail = () => {
  productApi.selectById.call({ id: route.query.id }).then((res: any) => {
    console.log(res);
    product.value = res;
    product.value.img=res.img.split(',')
  });
};
const product: any = ref({

});
</script>
<style>
.warp img {
  width: 100%;
}
</style>
<style scoped>
.van-action-bar {
  z-index: 50;
}
.price {
  color: red;
  font-size: 14px;
}
.price span {
  font-size: 20px;
}
.Detail {
  background-color: #fff;
  padding: 5px;
  border-radius: 0 0 10px 10px;
}
.Detail h4 {
  margin: 5px 0;
}
.Detail p {
  font-size: 15px;
}
.warp {
  margin-top: 10px;
  background-color: #fff;
  padding: 5px;
  border-radius: 10px 10px 0 0;
}
</style>

 三、后端代码(redis+blacklist)

3.1 ProducatController

    /**
     * 商品详情
     * @param id
     * @return
     */
    @GetMapping("/detail")
    public Product detail(Integer id) {
        int a=10;
        return productService.detail(id);
    }

3.2 ProductService

package com.beimao.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.smart.core.exception.BizException;
import com.beimao.common.model.Product;
import com.beimao.dao.ProductDao;
import com.beimao.dao.ProductMapper;
import com.beimao.model.EsProduct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class ProductService {
    /**
     * redis黑名单解决击穿问题
     */
    
    @Autowired
    private ProductDao productDao;
    @Resource(name = "redisTemplate")
    private HashOperations<String,String,String> hashOperations;
    @Resource(name = "redisTemplate")
    private ValueOperations<String, Product> valueOperations;

    // 黑名单key
    public static final String BLACKLIST_KEY = "product.hei";
    // 商品详情key
    public static final String ProductDetail_KEY = "product.detail";

  
    /**
     * 根据商品id 给商品详情
     * 先从redis中查询,如果redis中没有,则从数据库中查询
     *
     * @param id
     * @return
     */
    public Product detail(Integer id) {
        /**
         * 先验证商品id是否合法
         */
        if (id <= 0) {
            log.debug("商品id=》{}不合法", id);
            throw new BizException(100, "商品id不合法");

        }
        /**
         * 从redis里先检查 黑名单里是否有该商品
         * 如果有,抛出异常
         */
        Boolean b = hashOperations.hasKey(BLACKLIST_KEY, id.toString());
        if (b) {
            log.debug("商品不存在,商品在黑名单里,商品id=>{}", id);
            throw new BizException(101, "商品不存在");
        }
        /**
         * 黑名单没有
         * 直接从redis里查询是否有该商品
         * 有就返回,没有就查数据库
         */
        Product product = valueOperations.get(ProductDetail_KEY+id);
        if (ObjectUtil.isNotEmpty(product)) {
            log.debug("商品id=>{},从redis里查询到商品", id);
            return product;
        }
        /**
         * redis里面没有 就从数据库里面查
         * 数据库有就加入redis里面,没有就加入黑名单
         */
        product = productDao.detail(id);
        if (ObjectUtil.isEmpty(product)) {
            // 数据库查不到就加入黑名单
            hashOperations.put(BLACKLIST_KEY, id.toString(), DateUtil.now());
            log.debug("数据库里没有该商品,商品id=>{}加入黑名单", id);
        }
        // 数据库里面有就将该商品存到redis里面,设置ttl 一天
        /**
         *  错峰解决redis里的雪崩问题
         */
        int expire= RandomUtil.randomInt(-60 , 60);
        valueOperations.set(ProductDetail_KEY+id, product,24*60+expire, TimeUnit.MINUTES);
        return product;
    }

}

3.3 ProductDao

 /**
     * 根据商品id查询商品详情
     * @param id
     * @return
     */
    Product detail(Integer id);

 3.4 映射文件

<!--   根据id查询商品详情-->
    <select id="detail" resultType="com.beimao.common.model.Product">
        select id,subName,status,price,seq,tags,`name`,categoryId,img,brief
        from 205_product where id = #{id}
    </select>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今天的接口写完了吗?

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值