• JAVAEE——宜立方商城09:Activemq整合spring的应用场景、添加商品同步索引库、商品详情页面动态展示与使用缓存


    1. 学习计划

    1、Activemq整合spring的应用场景

    2、添加商品同步索引库

    3、商品详情页面动态展示

    4、展示详情页面使用缓存

    2. Activemq整合spring

    2.1. 使用方法

    第一步:引用相关的jar包。

        <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jms</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context-support</artifactId>
            </dependency>

    第二步:配置Activemq整合spring。配置ConnectionFactory

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
        xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    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-4.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd 
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
    
    
        <!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
        <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
            <property name="brokerURL" value="tcp://192.168.25.168:61616" />
        </bean>
        <!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
        <bean id="connectionFactory"
            class="org.springframework.jms.connection.SingleConnectionFactory">
            <!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
            <property name="targetConnectionFactory" ref="targetConnectionFactory" />
        </bean>
    </beans>

    第三步:配置生产者。

    使用JMSTemplate对象。发送消息。

    第四步:在spring容器中配置Destination

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
        xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
        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-4.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
    
        <!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
        <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
            <property name="brokerURL" value="tcp://192.168.25.168:61616" />
        </bean>
        <!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
        <bean id="connectionFactory"
            class="org.springframework.jms.connection.SingleConnectionFactory">
            <!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
            <property name="targetConnectionFactory" ref="targetConnectionFactory" />
        </bean>
        <!-- 配置生产者 -->
        <!-- Spring提供的JMS工具类,它可以进行消息发送、接收等 -->
        <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
            <!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
            <property name="connectionFactory" ref="connectionFactory" />
        </bean>
        <!--这个是队列目的地,点对点的 -->
        <bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
            <constructor-arg>
                <value>spring-queue</value>
            </constructor-arg>
        </bean>
        <!--这个是主题目的地,一对多的 -->
        <bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
            <constructor-arg value="topic" />
        </bean>
    </beans>


    第五步:代码测试 

    @Test
        public void testSpringActiveMq() throws Exception {
            //初始化spring容器
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-activemq.xml");
            //从spring容器中获得JmsTemplate对象
            JmsTemplate jmsTemplate = applicationContext.getBean(JmsTemplate.class);
            //从spring容器中取Destination对象
            Destination destination = (Destination) applicationContext.getBean("queueDestination");
            //使用JmsTemplate对象发送消息。
            jmsTemplate.send(destination, new MessageCreator() {
                
                @Override
                public Message createMessage(Session session) throws JMSException {
                    //创建一个消息对象并返回
                    TextMessage textMessage = session.createTextMessage("spring activemq queue message");
                    return textMessage;
                }
            });
        }


    2.2. 代码测试
     

    2.2.1. 发送消息

    第一步:初始化一个spring容器

    第二步:从容器中获得JMSTemplate对象。

    第三步:从容器中获得一个Destination对象

    第四步:使用JMSTemplate对象发送消息,需要知道Destination

    @Test
        public void testQueueProducer() throws Exception {
            // 第一步:初始化一个spring容器
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-activemq.xml");
            // 第二步:从容器中获得JMSTemplate对象。
            JmsTemplate jmsTemplate = applicationContext.getBean(JmsTemplate.class);
            // 第三步:从容器中获得一个Destination对象
            Queue queue = (Queue) applicationContext.getBean("queueDestination");
            // 第四步:使用JMSTemplate对象发送消息,需要知道Destination
            jmsTemplate.send(queue, new MessageCreator() {
                
                @Override
                public Message createMessage(Session session) throws JMSException {
                    TextMessage textMessage = session.createTextMessage("spring activemq test");
                    return textMessage;
                }
            });
        }


    2.2.2. 接收消息
     

    e3-search-Service中接收消息。

    第一步:把Activemq相关的jar包添加到工程中

    第二步:创建一个MessageListener的实现类。

    @Test
        public void testQueueProducer() throws Exception {
            // 第一步:初始化一个spring容器
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-activemq.xml");
            // 第二步:从容器中获得JMSTemplate对象。
            JmsTemplate jmsTemplate = applicationContext.getBean(JmsTemplate.class);
            // 第三步:从容器中获得一个Destination对象
            Queue queue = (Queue) applicationContext.getBean("queueDestination");
            // 第四步:使用JMSTemplate对象发送消息,需要知道Destination
            jmsTemplate.send(queue, new MessageCreator() {
                
                @Override
                public Message createMessage(Session session) throws JMSException {
                    TextMessage textMessage = session.createTextMessage("spring activemq test");
                    return textMessage;
                }
            });
        }


    第三步:配置springActivemq整合。

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
        xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
        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-4.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
    
        <!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
        <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
            <property name="brokerURL" value="tcp://192.168.25.168:61616" />
        </bean>
        <!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
        <bean id="connectionFactory"
            class="org.springframework.jms.connection.SingleConnectionFactory">
            <!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
            <property name="targetConnectionFactory" ref="targetConnectionFactory" />
        </bean>
        <!--这个是队列目的地,点对点的 -->
        <bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
            <constructor-arg>
                <value>spring-queue</value>
            </constructor-arg>
        </bean>
        <!--这个是主题目的地,一对多的 -->
        <bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
            <constructor-arg value="topic" />
        </bean>
        <!-- 接收消息 -->
        <!-- 配置监听器 -->
        <bean id="myMessageListener" class="cn.e3mall.search.listener.MyMessageListener" />
        <!-- 消息监听容器 -->
        <bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
            <property name="connectionFactory" ref="connectionFactory" />
            <property name="destination" ref="queueDestination" />
            <property name="messageListener" ref="myMessageListener" />
        </bean>
    </beans>

    第四步:测试代码。

    @Test
        public void testQueueConsumer() throws Exception {
            //初始化spring容器
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-activemq.xml");
            //等待
            System.in.read();
        }


    3. 
    添加商品同步索引库 

    3.1. Producer

    e3-manager-server工程中发送消息。

    当商品添加完成后发送一个TextMessage,包含一个商品id

     

    @Override
        public e3Result addItem(TbItem item, String desc) {
            // 1、生成商品id
            final long itemId = IDUtils.genItemId();
            // 2、补全TbItem对象的属性
            item.setId(itemId);
            //商品状态,1-正常,2-下架,3-删除
            item.setStatus((byte) 1);
            Date date = new Date();
            item.setCreated(date);
            item.setUpdated(date);
            // 3、向商品表插入数据
            itemMapper.insert(item);
            // 4、创建一个TbItemDesc对象
            TbItemDesc itemDesc = new TbItemDesc();
            // 5、补全TbItemDesc的属性
            itemDesc.setItemId(itemId);
            itemDesc.setItemDesc(desc);
            itemDesc.setCreated(date);
            itemDesc.setUpdated(date);
            // 6、向商品描述表插入数据
            itemDescMapper.insert(itemDesc);
            //发送一个商品添加消息
            jmsTemplate.send(topicDestination, new MessageCreator() {
                
                @Override
                public Message createMessage(Session session) throws JMSException {
                    TextMessage textMessage = session.createTextMessage(itemId + "");
                    return textMessage;
                }
            });
            // 7、e3Result.ok()
            return e3Result.ok();
        }


    3.2. Consumer
     

    3.2.1. 功能分析

    1、接收消息。需要创建MessageListener接口的实现类。

    2、取消息,取商品id

    3、根据商品id查询数据库。

    4、创建一SolrInputDocument对象。

    5、使用SolrServer对象写入索引库。

    6、返回成功,返回e3Result

    3.2.2. Dao

    根据商品id查询商品信息。

     

    映射文件:

    <select id="getItemById" parameterType="long" resultType="cn.e3mall.common.pojo.SearchItem">
            SELECT
                a.id,
                a.title,
                a.sell_point,
                a.price,
                a.image,
                b. NAME category_name,
                c.item_desc
            FROM
                tb_item a
            JOIN tb_item_cat b ON a.cid = b.id
            JOIN tb_item_desc c ON a.id = c.item_id
            WHERE a.status = 1
              AND a.id=#{itemId}
        </select>


    3.2.3. Service
     

    参数:商品ID

    业务逻辑:

    1、根据商品id查询商品信息。

    2、创建一SolrInputDocument对象。

    3、使用SolrServer对象写入索引库。

    4、返回成功,返回e3Result

    返回值:e3Result

    public e3Result addDocument(long itemId) throws Exception {
            // 1、根据商品id查询商品信息。
            SearchItem searchItem = searchItemMapper.getItemById(itemId);
            // 2、创建一SolrInputDocument对象。
            SolrInputDocument document = new SolrInputDocument();
            // 3、使用SolrServer对象写入索引库。
            document.addField("id", searchItem.getId());
            document.addField("item_title", searchItem.getTitle());
            document.addField("item_sell_point", searchItem.getSell_point());
            document.addField("item_price", searchItem.getPrice());
            document.addField("item_image", searchItem.getImage());
            document.addField("item_category_name", searchItem.getCategory_name());
            document.addField("item_desc", searchItem.getItem_desc());
            // 5、向索引库中添加文档。
            solrServer.add(document);
            solrServer.commit();
            // 4、返回成功,返回e3Result。
            return e3Result.ok();
        }


    3.2.4. Listener
     

    public class ItemChangeListener implements MessageListener {
        
        @Autowired
        private SearchItemServiceImpl searchItemServiceImpl;
    
        @Override
        public void onMessage(Message message) {
            try {
                TextMessage textMessage = null;
                Long itemId = null; 
                //取商品id
                if (message instanceof TextMessage) {
                    textMessage = (TextMessage) message;
                    itemId = Long.parseLong(textMessage.getText());
                }
                //向索引库添加文档
                searchItemServiceImpl.addDocument(itemId);
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    }


    3.2.5. Spring
    配置监听 

     

    3.2.6. 实现流程

     

    4. 商品详情页面展示

    创建一个商品详情页面展示的工程。是一个表现层工程。

    4.1. 工程搭建

    e3-item-web。打包方式war。可以参考e3-portal-web

    4.1.1. Pom文件

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>cn.e3mall</groupId>
            <artifactId>e3-parent</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </parent>
        <groupId>cn.e3mall</groupId>
        <artifactId>e3-item-web</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>war</packaging>
        <dependencies>
            <dependency>
                <groupId>cn.e3mall</groupId>
                <artifactId>e3-manager-interface</artifactId>
                <version>0.0.1-SNAPSHOT</version>
            </dependency>
            <!-- Spring -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jdbc</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jms</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context-support</artifactId>
            </dependency>
            <!-- JSP相关 -->
            <dependency>
                <groupId>jstl</groupId>
                <artifactId>jstl</artifactId>
            </dependency>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>servlet-api</artifactId>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>jsp-api</artifactId>
                <scope>provided</scope>
            </dependency>
            <!-- dubbo相关 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>dubbo</artifactId>
                <!-- 排除依赖 -->
                <exclusions>
                    <exclusion>
                        <groupId>org.springframework</groupId>
                        <artifactId>spring</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>org.jboss.netty</groupId>
                        <artifactId>netty</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>org.apache.zookeeper</groupId>
                <artifactId>zookeeper</artifactId>
            </dependency>
            <dependency>
                <groupId>com.github.sgroschupf</groupId>
                <artifactId>zkclient</artifactId>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
            </dependency>
        </dependencies>
        <!-- 配置tomcat插件 -->
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.tomcat.maven</groupId>
                    <artifactId>tomcat7-maven-plugin</artifactId>
                    <configuration>
                        <port>8086</port>
                        <path>/</path>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>


      

    4.2. 功能分析

    在搜索结果页面点击商品图片或者商品标题,展示商品详情页面。

     

    请求的url/item/{itemId}

    参数:商品id

    返回值:String 逻辑视图

    业务逻辑:

    1、url中取参数,商品id

    2、根据商品id查询商品信息(tb_item)得到一个TbItem对象,缺少images属性,可以创建一个pojo继承TbItem,添加一个getImages方法。在e3-item-web工程中。

    public class Item extends TbItem {
    
        public String[] getImages() {
            String image2 = this.getImage();
            if (image2 != null && !"".equals(image2)) {
                String[] strings = image2.split(",");
                return strings;
            }
            return null;
        }
        
        public Item() {
            
        }
        
        public Item(TbItem tbItem) {
            this.setBarcode(tbItem.getBarcode());
            this.setCid(tbItem.getCid());
            this.setCreated(tbItem.getCreated());
            this.setId(tbItem.getId());
            this.setImage(tbItem.getImage());
            this.setNum(tbItem.getNum());
            this.setPrice(tbItem.getPrice());
            this.setSellPoint(tbItem.getSellPoint());
            this.setStatus(tbItem.getStatus());
            this.setTitle(tbItem.getTitle());
            this.setUpdated(tbItem.getUpdated());
        }
        
    }


    4、展示到页面。3、根据商品id查询商品描述。

    4.3. Dao

    查询tb_item, tb_item_desc两个表,都是单表查询。可以使用逆向工程。

    4.4. Service

    1、根据商品id查询商品信息

    参数:商品id

    返回值:TbItem

    2、根据商品id查询商品描述

    参数:商品id

    返回值:TbItemDesc

    @Override
        public TbItemDesc getItemDescById(long itemId) {
            TbItemDesc itemDesc = itemDescMapper.selectByPrimaryKey(itemId);
            return itemDesc;
        }

    4.5. 表现层

    4.5.1. Controller

    请求的url/item/{itemId}

    参数:商品id

    返回值:String 逻辑视图

    @Controller
    public class ItemController {
    
        @Autowired
        private ItemService itemService;
        
        @RequestMapping("/item/{itemId}")
        public String showItemInfo(@PathVariable Long itemId, Model model) {
            //跟据商品id查询商品信息
            TbItem tbItem = itemService.getItemById(itemId);
            //把TbItem转换成Item对象
            Item item = new Item(tbItem);
            //根据商品id查询商品描述
            TbItemDesc tbItemDesc = itemService.getItemDescById(itemId);
            //把数据传递给页面
            model.addAttribute("item", item);
            model.addAttribute("itemDesc", tbItemDesc);
            return "item";
        }
    }


    4.6. 向业务逻辑中添加缓存
     

    4.6.1. 缓存添加分析

    使用redis做缓存。

    业务逻辑:

    1、根据商品id到缓存中查找

    2、查到缓存,直接返回。

    3、查不到,查询数据库

    4、把数据放到缓存中

    5、返回数据

    缓存中缓存热点数据,提供缓存的使用率。需要设置缓存的有效期。一般是一天的时间,可以根据实际情况跳转。

    需要使用String类型来保存商品数据。

    可以加前缀方法对象redis中的key进行归类。

    ITEM_INFO:123456:BASE

    ITEM_INFO:123456:DESC

     

    如果把二维表保存到redis:

    1、表名就是第一层

    2、主键是第二层

    3、字段名第三次

    三层使用:”分隔作为keyvalue就是字段中的内容。

    4.6.2. redis相关的jar包添加到工程

     

    4.6.3. 添加缓存

    @Override
        public TbItem getItemById(long itemId) {
            try {
                //查询缓存
                String json = jedisClient.get(ITEM_INFO_PRE + ":" + itemId + ":BASE");
                if (StringUtils.isNotBlank(json)) {
                    //把json转换为java对象
                    TbItem item = JsonUtils.jsonToPojo(json, TbItem.class);
                    return item;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            //根据商品id查询商品信息
            //TbItem tbItem = itemMapper.selectByPrimaryKey(itemId);
            TbItemExample example = new TbItemExample();
            //设置查询条件
            Criteria criteria = example.createCriteria();
            criteria.andIdEqualTo(itemId);
            List<TbItem> list = itemMapper.selectByExample(example);
            if (list != null && list.size() > 0) {
                TbItem item = list.get(0);
                try {
                    //把数据保存到缓存
                    jedisClient.set(ITEM_INFO_PRE + ":" + itemId + ":BASE", JsonUtils.objectToJson(item));
                    //设置缓存的有效期
                    jedisClient.expire(ITEM_INFO_PRE + ":" + itemId + ":BASE", ITEM_INFO_EXPIRE);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return item;
            }
            return null;
        }


    取商品描述添加缓存: 

    @Override
        public TbItemDesc getItemDescById(long itemId) {
            try {
                String json = jedisClient.get(ITEM_INFO_PRE + ":" + itemId + ":DESC");
                //判断缓存是否命中
                if (StringUtils.isNotBlank(json) ) {
                    //转换为java对象
                    TbItemDesc itemDesc = JsonUtils.jsonToPojo(json, TbItemDesc.class);
                    return itemDesc;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            TbItemDesc itemDesc = itemDescMapper.selectByPrimaryKey(itemId);
            try {
                jedisClient.set(ITEM_INFO_PRE + ":" + itemId + ":DESC", JsonUtils.objectToJson(itemDesc));
                //设置过期时间
                jedisClient.expire(ITEM_INFO_PRE + ":" + itemId + ":DESC", ITEM_INFO_EXPIRE);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return itemDesc;
        }


      

  • 相关阅读:
    JVM内存参数详解以及配置调优
    Sublime Text 3安装AngularJS插件
    GraphicsMagick安装&make命令使用
    清明节太原两日游
    Java异常处理机制 try-catch-finally
    成都一日游
    降低PNG图片存储大小方法、图片压缩方法
    Windows 10下mysql 64位 安装(mysql-5.7.11-winx64安装)
    解决-Dmaven.multiModuleProjectDirectory system property is not set. Check $M2_HOME environment variabl
    centos 7下Hadoop 2.7.2 伪分布式安装
  • 原文地址:https://www.cnblogs.com/xieyupeng/p/9388391.html
Copyright © 2020-2023  润新知