yml配置动态数据源(数据库@DS)与引起(If you want an embedded database (H2, HSQL or Derby))类问题

这篇具有很好参考价值的文章主要介绍了yml配置动态数据源(数据库@DS)与引起(If you want an embedded database (H2, HSQL or Derby))类问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1:yml 配置

spring:
  datasource:
    dynamic:
      datasource:
        master:
          url: jdbc:mysql://192.168.11.50:3306/dsdd?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
          username: root
          password: root
          driver-class-name: com.mysql.cj.jdbc.Driver
        second-datasource:
          url: jdbc:mysql://192.168.11.50:3306/commons_utils?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
          username: root
          password: root
          driver-class-name: com.mysql.cj.jdbc.Driver

2:必须pom依赖配

        <!-- 动态数据源 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>3.2.0</version>
        </dependency>

2-1:不要加入一下依赖不然会报以下错误

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.200</version>
            <scope>runtime</scope>
        </dependency>

        <!-- druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.6</version>
        </dependency>

yml配置动态数据源(数据库@DS)与引起(If you want an embedded database (H2, HSQL or Derby))类问题,数据库

2-2:当出现以上错误可以在yml配置文件去掉DruidDataSourceAutoConfigure,如下

spring:
  autoconfigure:
    exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure

3:加入数据库连接池druid依赖管理(使用多数据源一定要用链接池),Druid是阿里巴巴开源的一个数据库连接池和实时数据分析组件。相比其他连接池,Druid在功能特性、性能、监控等方面有很多优势,比如支持SQL解析、慢SQL日志、提供多维度监控等

spring:
  autoconfigure:
    exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
  datasource:
    druid:
      stat-view-servlet:
        enabled: true
        loginUsername: admin
        loginPassword: 123456
        allow:
      web-stat-filter:
        enabled: true
    dynamic:
      druid: # 全局druid参数,绝大部分值和默认保持一致。(现已支持的参数如下,不清楚含义不要乱设置)
        # 连接池的配置信息
        # 初始化大小,最小,最大
        initial-size: 5
        min-idle: 5
        maxActive: 20
        # 配置获取连接等待超时的时间r
        maxWait: 60000
        # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
        timeBetweenEvictionRunsMillis: 60000
        # 配置一个连接在池中最小生存的时间,单位是毫秒
        minEvictableIdleTimeMillis: 300000
        validationQuery: SELECT 1 FROM DUAL
        testWhileIdle: true
        testOnBorrow: false
        testOnReturn: false
        # 打开PSCache,并且指定每个连接上PSCache的大小
        poolPreparedStatements: true
        maxPoolPreparedStatementPerConnectionSize: 20
        # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
        filters: stat,wall,slf4j
        # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
        connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
      datasource:
        master:
          url: jdbc:mysql://192.168.11.50:3306/dsdd?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
          username: root
          password: root
          driver-class-name: com.mysql.cj.jdbc.Driver
        second:
          url: jdbc:mysql://192.168.11.50:3306/commons_utils?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
          username: root
          password: root
          driver-class-name: com.mysql.cj.jdbc.Driver

3-1:加入依赖

        <!-- 动态数据源 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>3.2.0</version>
        </dependency>

        <!-- druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.6</version>
        </dependency>

Druid连接池的自动配置类是DruidDataSourceAutoConfigure类上有一行注解

@EnableConfigurationProperties({DruidStatProperties.class, DataSourceProperties.class})

@EnableConfigurationProperties注解的作用是:使配置文件中的配置生效并且映射到指定类的属性

DruidStatProperties:指定的前缀是spring.datasource.druid,主要设置连接池的一些参数

DataSourceProperties:指定的前缀是spring.datasource,主要设置url,username,password等信息

3-2:DruidConfig 配置类

package com.example.poi.config;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
import com.alibaba.druid.util.Utils;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.*;
import java.io.IOException;

/**
 * @Description: DruidConfig配置类
 */
@Configuration
@AutoConfigureAfter(DruidDataSourceAutoConfigure.class)
public class DruidConfig {

    /**
     * 带有广告的common.js全路径,druid-1.1.14
     */
    private static final String FILE_PATH = "support/http/resources/js/common.js";
    /**
     * 原始脚本,触发构建广告的语句
     */
    private static final String ORIGIN_JS = "this.buildFooter();";
    /**
     * 替换后的脚本
     */
    private static final String NEW_JS = "//this.buildFooter();";

    /**
     * 去除Druid监控页面的广告
     *
     * @param properties DruidStatProperties属性集合
     * @return {@link FilterRegistrationBean}
     */
    @Bean
    @ConditionalOnWebApplication
    @ConditionalOnProperty(name = "spring.datasource.druid.stat-view-servlet.enabled", havingValue = "true")
    public FilterRegistrationBean<RemoveAdFilter> removeDruidAdFilter(
            DruidStatProperties properties) throws IOException {
        // 获取web监控页面的参数
        DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
        // 提取common.js的配置路径
        String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
        String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
        // 获取common.js
        String text = Utils.readFromResource(FILE_PATH);
        // 屏蔽 this.buildFooter(); 不构建广告
        final String newJs = text.replace(ORIGIN_JS, NEW_JS);
        FilterRegistrationBean<RemoveAdFilter> registration = new FilterRegistrationBean<>();
        registration.setFilter(new RemoveAdFilter(newJs));
        registration.addUrlPatterns(commonJsPattern);
        return registration;
    }

    /**
     * 删除druid的广告过滤器
     *
     * @author BBF
     */
    private class RemoveAdFilter implements Filter {

        private final String newJs;

        public RemoveAdFilter(String newJs) {
            this.newJs = newJs;
        }

        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            chain.doFilter(request, response);
            // 重置缓冲区,响应头不会被重置
            response.resetBuffer();
            response.getWriter().write(newJs);
        }
    }
}

4:配置动态数据源方法二,yml随意配置或者通过配置类生成数据库链接

4-1:yml配置(记得配置数据库链接池)

datasource:
  master:
    url: jdbc:mysql://192.168.11.50:3306/dsdd?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
  second:
    url: jdbc:mysql://192.168.11.50:3306/commons_utils?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver

4-2:配置动态源数据类

@Configuration
public class DatabaseConfig {

    @Value("${datasource.master.url}")
    private String dataSourceUrl;

    @Value("${datasource.master.username}")
    private String dataSourceUsername;

    @Value("${datasource.master.password}")
    private String dataSourcePassword;

    @Value("${datasource.master.driver-class-name}")
    private String dataSourceDriverClassName;

    @Value("${datasource.second.url}")
    private String dataSourceUrl2;

    @Value("${datasource.second.username}")
    private String dataSourceUsername2;

    @Value("${datasource.second.password}")
    private String dataSourcePassword2;

    @Value("${datasource.second.driver-class-name}")
    private String dataSourceDriverClassName2;

    public DataSource dataSource() {
        return  DataSourceBuilder.create()
                .url(dataSourceUrl)
                .username(dataSourceUsername)
                .password(dataSourcePassword)
                .driverClassName("com.mysql.cj.jdbc.Driver")
                .build();
    }
    public DataSource dataSource2() {
        return DataSourceBuilder.create()
                .url(dataSourceUrl2)
                .username(dataSourceUsername2)
                .password(dataSourcePassword2)
                .driverClassName("com.mysql.cj.jdbc.Driver")
                .build();
    }

    // 添加动态数据源
    @Bean
    public DynamicRoutingDataSource dynamicDataSource() {
        DynamicRoutingDataSource dynamicRoutingDataSource = new DynamicRoutingDataSource();
        dynamicRoutingDataSource.addDataSource("master", dataSource());
        dynamicRoutingDataSource.addDataSource("two", dataSource2());
        return dynamicRoutingDataSource;
    }
}

4-3:在server服务层通过@DS调用

    @Override
    @DS("two")
    public List<EntityDemo> testSql(Page<EntityDemo> pageList, String id)  {
        List<EntityDemo> entityDemos = entityDemoMapper.testSql(pageList, id);
        DynamicDataSourceContextHolder.clear();
        return entityDemos;

4-4:可以在启动类观察动态数据源情况如下:run.getBean(DataSource.class).getConnection();

@SpringBootApplication
@MapperScan(basePackages = "com.example.poi.mapper")
public class PoiApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(PoiApplication.class, args);
        // 检查数据库连接是否正常
        try {
            // 获取DataSource bean,并调用getConnection()方法测试连接
            run.getBean(javax.sql.DataSource.class).getConnection();
            System.out.println("数据库连接正常!");
        } catch (Exception e) {
            System.err.println("数据库连接异常:" + e.getMessage());
            // 处理连接异常的逻辑
        }
    }
}

yml配置动态数据源(数据库@DS)与引起(If you want an embedded database (H2, HSQL or Derby))类问题,数据库

5:方法三配置动态数据源使,使用注解的方式(推荐使用)

5-1:yml配置

spring:
  datasource:
    master:
      jdbcUrl: jdbc:mysql://192.168.11.50:3306/dsdd?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
      username: root
      password: root
      driver-class-name: com.mysql.cj.jdbc.Driver
    second:
      jdbcUrl: jdbc:mysql://192.168.11.50:3306/commons_utils?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
      username: root
      password: root
      driverClassName: com.mysql.cj.jdbc.Driver
    druid:
      #连接池初始化时创建的数据库连接数量
      initial-size: 10
      #连接池中保持最小的空闲连接数量。如果空闲连接数量少于这个值,连接池会创建新的连接来补充
      min-idle: 5
      #
      max-active: 80
      #配置获取链接等待超时的时间
      max-wait:
    type: com.alibaba.druid.pool.DruidDataSource

5-2:配置动态源数据类(在需要切换的地方使用@DS就可以),整合mybatis-plus的过程中,我们还需要创建动态数据源的SqlSessionFactory,如果我们想要实现动态数据源切换,则需要手动配置SqlSessionFactory,以便于它使用动态数据源,同理事务管理器也需要重新配置:

@Configuration
public class DatabaseConfig {


    @Bean("one")
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean("two")
    @ConfigurationProperties(prefix = "spring.datasource.second")
    public DataSource dataSource2() {
        return DataSourceBuilder.create().build();
    }

    //添加动态数据源
    @Bean
    public DynamicRoutingDataSource dynamicDataSource(@Qualifier("one") DataSource dataSource, @Qualifier("two") DataSource dataSource2) {
        DynamicRoutingDataSource dynamicRoutingDataSource = new DynamicRoutingDataSource();
        dynamicRoutingDataSource.addDataSource("master", dataSource);
        dynamicRoutingDataSource.addDataSource("two", dataSource2);
        return dynamicRoutingDataSource;
    }


    @Bean("sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactoryBean(DynamicRoutingDataSource dynamicRoutingDataSource) throws Exception {
    	//使用SqlSessionFactoryBean不可以正常使用 BaseMapper的MyBatis通用的CRUD
        //SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
        sessionFactory.setDataSource(dynamicRoutingDataSource);
        return sqlSessionFactoryBean.getObject();
    }

    /**
     * 重写事务管理器,管理动态数据源
     */
    @Primary
    @Bean(value = "transactionManager")
    public PlatformTransactionManager annotationDrivenTransactionManager(DynamicRoutingDataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}

5-3:切换使用数据源

yml配置动态数据源(数据库@DS)与引起(If you want an embedded database (H2, HSQL or Derby))类问题,数据库

6:方法四配置动态数据源使用,使用注解的方式(推荐使用)

6-1:添加注解和切面

package com.example.poi.minds.annotation;

import java.lang.annotation.*;

/**
 * @Author xu
 * @create 2023/9/7 22
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MinDS {

    /**
     * groupName or specific database name or spring SPEL name.
     *
     * @return the database you want to switch
     */
    String value() default "";
}

package com.example.poi.minds.aop;

import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.example.poi.config.DataSourceHolder;
import com.example.poi.desensitization.annotation.SensitiveDecode;
import com.example.poi.desensitization.annotation.SensitiveEncode;
import com.example.poi.desensitization.utils.SensitiveInfoUtil;
import com.example.poi.minds.annotation.MinDS;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.List;

/**
 * @Author xu
 * @create 2023/9/7 22
 */
@Slf4j
@Aspect
@Component
public class MinDSAspect {

    /**
     * 定义切点Pointcut
     */
    @Pointcut("@annotation(com.example.poi.minds.annotation.MinDS) ")
    public void dsPointCut() {
    }

    @Around("dsPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        // 处理结果

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        MinDS minDS = method.getAnnotation(MinDS.class);
        String value = minDS.value();
        if (StringUtils.isBlank(value)) {
            return null;
        }
        DataSourceHolder.setDataSource(value);
        try {
            return joinPoint.proceed();
        } finally {
            DataSourceHolder.clearDataSource();
        }
    }
}

yml配置动态数据源(数据库@DS)与引起(If you want an embedded database (H2, HSQL or Derby))类问题,数据库文章来源地址https://www.toymoban.com/news/detail-695852.html

6-2:动态数据源简单的说就是能够自由切换的数据源,Spring提供了一个抽象类AbstractRoutingDataSource,我们只需要extends ,并且重写determineCurrentLookupKey()即可determineCurrentLookupKey()的作用:返回需要切换的数据源的key,然后根据这个key获取对应的数据源信息

package com.example.poi.config;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**
 * @Author xu
 * @create 2023/9/7 22
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
    /**
     * 返回需要使用的数据源key,将会按照这个key从Map中获取对应的数据源(切换)
     * @return
     */
    @Override
    protected Object determineCurrentLookupKey() {
        //从ThreadLocal中取出key
        return DataSourceHolder.getDataSource();
    }

}

6-3:单独封装一个类:DataSourceHolder,在多线程的情况下,数据源切换如何保证线程隔离呢?,我们不能这边切换了影响了其他线程的执行,这里我们便想到了ThreadLocal

package com.example.poi.config;

/**
 * @Author xu
 * @create 2023/9/7 20
 */
/**
 * 线程安全类:使用ThreadLocal存储切换数据源后的KEY
 */
public class DataSourceHolder {
    /**
     * 线程ThreadLocal
     */
    private static final ThreadLocal<String> dataSources = new InheritableThreadLocal();

    /**
     * 设置数据源
     * @param datasource
     */
    public static void setDataSource(String datasource) {
        dataSources.set(datasource);
    }

    /**
     * 获取数据源
     * @return
     */
    public static String getDataSource() {
        return dataSources.get();
    }

    /**
     * 清除数据源
     */
    public static void clearDataSource() {
        dataSources.remove();
    }

}

到了这里,关于yml配置动态数据源(数据库@DS)与引起(If you want an embedded database (H2, HSQL or Derby))类问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用mybatis和dynamic-datasource-spring-boot-starter动态切换数据源操作数据库

    记录 :415 场景 :使用mybatis和dynamic-datasource-spring-boot-starter动态切换数据源操作数据库。 版本 :JDK 1.8,Spring Boot 2.6.3,dynamic-datasource-spring-boot-starter-3.3.2,mybatis-3.5.9。 源码 :https://github.com/baomidou/dynamic-datasource-spring-boot-starter dynamic-datasource-spring-boot-starter :一个基于springboot的快

    2023年04月19日
    浏览(44)
  • 使用dynamic-datasource-spring-boot-starter动态切换数据源操作数据库(MyBatis-3.5.9)

    记录 :383 场景 :使用dynamic-datasource-spring-boot-starter动态切换数据源,使用MyBatis操作数据库。提供三种示例:一,使用@DS注解作用到类上。二,使用@DS注解作用到方法上。三,不使用注解,使用DynamicDataSourceContextHolder类在方法内灵活切换不同数据源。 源码: https://github.com/

    2024年01月20日
    浏览(52)
  • SpringBoot @DS注解实现多数据源配置及问题解决

    进过验证,@DS注解加到mapper接口、service接口、service方法里都不生效,获取的还是默认的主数据源。猜测是由于spring的aop切面机制导致拦截不到@DS注解,进而不能切换数据源,正确的做法是添加到service实现类或者实现类里具体的方法上。 在事务方法内调用@DS注解的方法,@D

    2023年04月25日
    浏览(34)
  • 「数据库、数据库连接池、数据源」这些概念你真的理解了吗?

    我学习的过程中,对于连接池和数据源分得不是很清楚,而且我发现有的人将数据库等同于数据源,或者将数据源等同于连接池,实际上这些说法并不准确。 在某次工作中,同事 A 说道,这个数据源不行,那么换一个数据源就可以了,结果我看他操作,原来是改写了配置中的

    2023年04月21日
    浏览(62)
  • springboot整合多数据源的配置以及动态切换数据源,注解切换数据源

    在许多应用程序中,可能需要使用多个数据库或数据源来处理不同的业务需求。Spring Boot提供了简便的方式来配置和使用多数据源,使开发人员能够轻松处理多个数据库连接。如果你的项目中可能需要随时切换数据源的话,那我这篇文章可能能帮助到你 ℹ️:这里对于pom文件

    2024年02月10日
    浏览(50)
  • java serverlets使用数据源连接oracle数据库,并执行查询操作代码

    package chap03; import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.PreparedStatement; import java.sql.Statement; import java.util.*; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.Namin

    2024年02月08日
    浏览(51)
  • 自动生成数据库设计文档,支持多数据源批量生成(Word文档)

          在做项目时通常使用PowerDesigner设计数据库,但在项目完成交付项目给客户的时候常常需要一份Word版本的数据库文档给客户,你不能指望每个客户都会用PowerDesigner,所以基于当前开发数据库生成数据库文档就是最佳选择,如果手动编写数据库文档那将是一件非常痛苦的

    2024年04月23日
    浏览(46)
  • 利用 Mybatis-Plus 的动态数据源实现多数据源配置

    目录 一、导入依赖 二、Application.yaml配置文件 三、切换数据源 四、其他方法 4.1 配置多个数据源 4.2 定义Datasource和EntityManager 4.3 在需要使用数据源的地方注入不同的EntityManager 官网:https://baomidou.com/pages/a61e1b/#dynamic-datasource 默认是使用配置文件中master参数设置的数据库。

    2024年02月13日
    浏览(42)
  • springMvc项目如何配置动态数据源

    具体文件引入和结构体参考另一章连接

    2024年01月21日
    浏览(33)
  • Grafana(二)Grafana 两种数据源图表展示(json-api与数据库)

    在先前的博客文章中,我们搭建了Grafana ,它是一个开源的度量分析和可视化工具,可以通过将采集的数据分析、查询,然后进行可视化的展示,接下来我们重点介绍如何使用它来进行数据渲染图表展示 Docker安装Grafana-CSDN博客 文章浏览阅读1.2k次,点赞25次,收藏22次。分析上

    2024年01月17日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包