当前位置:   article > 正文

SpringBoot-整合druid_springboot整合druid

springboot整合druid

SpringBoot-整合druid

1.JDBC+HikariDataSource

1.应用实例-需求

● 需求:演示 Spring Boot 如何通过 jdbc+HikariDataSource 完成对 Mysql 操作 说明: HikariDataSource : 目前市面上非常优秀的数据源, 是 springboot2 默认数据源

2.应用实例-代码实现

  1. 创建测试数据库和表
-- 创建 spring_boot 
DROP DATABASE IF EXISTS spring_boot; CREATE DATABASE spring_boot; 
USE spring_boot; 
-- 创建家居表 
CREATE TABLE furn( `id` INT(11) PRIMARY KEY AUTO_INCREMENT, ## id 
`name` VARCHAR(64) NOT NULL, ## 家居名 
`maker` VARCHAR(64) NOT NULL, ## 厂商
`price` DECIMAL(11,2) NOT NULL, ## 价格
`sales` INT(11) NOT NULL, ## 销量
`stock` INT(11) NOT NULL, ## 库存
`img_path` VARCHAR(256) NOT NULL ## 照片路径 
);

-- 初始化家居数据
INSERT INTO furn(`id` , `name` , `maker` , `price` , `sales` , `stock` , `img_path`) VALUES(NULL , ' 北 欧 风 格 小 桌 子 ' , ' 熊 猫 家 居 ' , 180 , 666 , 7 , 'assets/images/product-image/1.jpg'); 
INSERT INTO furn(`id` , `name` , `maker` , `price` , `sales` , `stock` , `img_path`) VALUES(NULL , ' 简 约 风 格 小 椅 子 ' , ' 熊 猫 家 居 ' , 180 , 666 , 7 , 'assets/images/product-image/2.jpg'); 
INSERT INTO furn(`id` , `name` , `maker` , `price` , `sales` , `stock` , `img_path`) VALUES(NULL , ' 典 雅 风 格 小 台 灯 ' , ' 蚂 蚁 家 居 ' , 180 , 666 , 7 , 'assets/images/product-image/3.jpg'); 
INSERT INTO furn(`id` , `name` , `maker` , `price` , `sales` , `stock` , `img_path`) VALUES(NULL , ' 温 馨 风 格 盆 景 架 ' , ' 蚂 蚁 家 居 ' , 180 , 666 , 7 , 'assets/images/product-image/4.jpg'); SELECT * FROM furn;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  1. 进 行 数 据 库 开 发 , 在 pom.xml 引 入 data-jdbc starter , 参 考 官 方 文 档 https://docs.spring.io/spring-boot/docs/current/reference/html/using.html#using.build-systems.starters

image-20220814165510657

<!--进行数据库开发,引入data-jdbc starter-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  1. Spring Boot 不知道项目要操作 Mysql 还是 Oracle , 需要在 pom.xml 指定导入数据库 驱动, 并指定对应版本.
<!--引入mysql的驱动
1. 说明这里没有使用版本仲裁  <mysql.version>8.0.26</mysql.version>
2. 指定的版本是5.1.49
-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.49</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  1. 在 application.yml 配置操作数据源的信息
spring:
  datasource:
    #说明:如果没有指定useSSL=true,启动项目可能会爆红警告,环境问题
    url: jdbc:mysql://127.0.0.1:3306/spring_boot?useSSL=true&useUnicode=true&characterEncoding=UTF-8
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

​ 5.创建src\main\java\com\llp\springboot\bean\Furn.java

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Furn {
    private Integer id;

    private String name;

    private String maker;

    private BigDecimal price;

    private Integer sales;

    private Integer stock;

    private String imgPath = "assets/images/product-image/1.jpg";
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

3.应用实例-测试结果

1.创建src\test\java\com\llp\springboot\ApplicationTests.java 测试类

/**
 * 如何在springboot中开发测试类,需要引入如下的依赖
 *        <dependency>
 *           <groupId>org.springframework.boot</groupId>
 *           <artifactId>spring-boot-starter-test</artifactId>
 *        </dependency>
 */
@SpringBootTest
public class ApplicationTests {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Test
    public void contextLoads() {
        BeanPropertyRowMapper<Furn> rowMapper = new BeanPropertyRowMapper(Furn.class);
        List<Furn> furns = jdbcTemplate.query("select * from furn", rowMapper);
        for (Furn furn : furns) {
            System.out.println(furn);
        }
        System.out.println(jdbcTemplate.getDataSource().getClass());
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

可以看到springBoot默认使用的是HikariDataSource 数据源

image-20220814165845926

2.整合 Druid 到 Spring-Boot

1.官方文档

1.使用手册

https://github.com/alibaba/druid

image-20220814170213913

2.中文手册

https://github.com/alibaba/druid/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98

2.基本介绍

  1. HiKariCP: 目前市面上非常优秀的数据源, 是 springboot2 默认数据源

  2. Druid: 性能优秀,Druid 提供性能卓越的连接池功能外【Java 基础】,还集成了 SQL 监 控,黑名单拦截等功能,强大的监控特性,通过 Druid 提供的监控功能,可以清楚知道连 接池和 SQL 的工作情况,所以根据项目需要,我们也要掌握 Druid 和 SpringBoot 整合

  3. 整合 Druid 到 Spring-Boot 方式

● 自定义方式

● 引入 starter 方式

3.Durid 基本使用

1.需求: 将 Spring-Boot 的数据源切换成 Druid
2.代码实现
  1. 修改 pom.xml , 引入 druid 依赖
<!--引入德鲁伊依赖-->
<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>druid</artifactId>
   <version>1.1.17</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2.创建src\main\java\com\llp\springboot\config\DruidDataSourceConfig.java 配置类

@Configuration
public class DruidDataSourceConfig {

    //编写方法,注入DruidDataSource
    //为什么我们注入自己的DataSource , 默认的HiKariDatasource失效?
    //1. 默认的数据源是如配置? @ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
    //   解读通过@ConditionalOnMissingBean({ DataSource.class}) 判断如果容器有DataSource Bean 就不注入默认的HiKariDatasource
    @ConfigurationProperties("spring.datasource")
    @Bean
    public DataSource dataSource() {
        //1. 配置了 @ConfigurationProperties("spring.datasource")
        //   就可以读取到application.yml的配置,注意:我们需要将bean注入到spring ioc容器中、bean中提供get\set方法
        //2. 我们就不需要调用DruidDataSource 对象的setXxx, 会自动关联

        DruidDataSource druidDataSource = new DruidDataSource();
        //druidDataSource.setUrl();
        //druidDataSource.setUsername();
        //druidDataSource.setPassword();
        return druidDataSource;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  1. 完成测试,运行 ApplicationTests.java , 观察数据源的运行类型

image-20220814181728551

4.Durid 监控功能-SQL 监控

1.需求: 配置 Druid 的监控功能,包括 SQL 监控、SQL 防火墙、Web 应用、Session 监控等

在配置监控功能之前,我们先来看看如何配置 Druid 的监控页面

<!-- 配置 Druid 监控信息显示页面 -->  
<servlet>  
    <servlet-name>DruidStatView</servlet-name>  
    <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>  
    <init-param>  
	<!-- 允许清空统计数据 -->  
	<param-name>resetEnable</param-name>  
	<param-value>true</param-value>  
    </init-param>  
    <init-param>  
	<!-- 用户名 -->  
	<param-name>loginUsername</param-name>  
	<param-value>druid</param-value>  
    </init-param>  
    <init-param>  
	<!-- 密码 -->  
	<param-name>loginPassword</param-name>  
	<param-value>druid</param-value>  
    </init-param>  
</servlet>  
<servlet-mapping>  
    <servlet-name>DruidStatView</servlet-name>  
    <url-pattern>/druid/*</url-pattern>  
</servlet-mapping>  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

image-20220814183739265

1.在springBoot项目中,我们需要将StatViewServlet注入到容器中并配置登录的用户名和密码等信息

/**
 * <!-- 配置 Druid 监控信息显示页面 -->
 * <servlet>
 *     <servlet-name>DruidStatView</servlet-name>
 *     <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
 *     <init-param>
 *     <!-- 允许清空统计数据 -->
 *     <param-name>resetEnable</param-name>
 *     <param-value>true</param-value>
 *     </init-param>
 *     <init-param>
 *     <!-- 用户名 -->
 *     <param-name>loginUsername</param-name>
 *     <param-value>druid</param-value>
 *     </init-param>
 *     <init-param>
 *     <!-- 密码 -->
 *     <param-name>loginPassword</param-name>
 *     <param-value>druid</param-value>
 *     </init-param>
 * </servlet>
 * <servlet-mapping>
 *     <servlet-name>DruidStatView</servlet-name>
 *     <url-pattern>/druid/*</url-pattern>
 * </servlet-mapping>
 * @return
 */
@Bean
public ServletRegistrationBean registrationBean(){
    StatViewServlet statViewServlet = new StatViewServlet();
    //配置监控页面的访问路径
    ServletRegistrationBean registrationBean = new ServletRegistrationBean(statViewServlet, "/druid/*");
    //配置登录用户名和密码,结合上面这段 init-param即配置servlet的初始化参数,key和其保持一致,value值我们可以自行定义
    registrationBean.addInitParameter("loginUsername","llp");
    registrationBean.addInitParameter("loginPassword","123");
    return registrationBean;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

2.启动完成测试http://localhost:8080/druid/login.html,我这里配置了拦截器匹配规则是/**,但是访问druid的监控是走的servlet不会走拦截器,因此可以直接访问

image-20220814184402415

image-20220814184531350

image-20220814184542828

2.SQL 监控数据

https://github.com/alibaba/druid/wiki/%E9%85%8D%E7%BD%AE_StatFilter

image-20220814191838045

1.那么如何在springboot项目中配置druid的sql监控功能呢,从上面可以看到我们需要在注入druidDataSource数据源对象的地方添加一个属性 druidDataSource.setFilters("stat");

@ConfigurationProperties("spring.datasource")
@Bean
public DataSource dataSource() throws SQLException {
    //1. 配置了 @ConfigurationProperties("spring.datasource")
    //   就可以读取到application.yml的配置,注意:我们需要将bean注入到spring ioc容器中、bean中提供get\set方法
    //2. 我们就不需要调用DruidDataSource 对象的setXxx, 会自动关联

    DruidDataSource druidDataSource = new DruidDataSource();

    //配置sql监控
    druidDataSource.setFilters("stat");
    return druidDataSource;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

2.模拟操作 DB 的请求

@Controller
@RequiredArgsConstructor
public class DruidSqlController {

    private final JdbcTemplate jdbcTemplate;

    @ResponseBody
    @GetMapping("/sql")
    public List<Furn> getFurnList(){
        BeanPropertyRowMapper<Furn> furnBeanPropertyRowMapper = new BeanPropertyRowMapper<>(Furn.class);
        List<Furn> furnList = jdbcTemplate.query("select * from furn", furnBeanPropertyRowMapper);
        System.out.println(furnList);
        return furnList;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

3.我们来看下sql监控的效果

image-20220814192722457

image-20220814192946889

5.Durid 监控功能-Web 关联监控

1.需求: 配置 Web 关联监控配置:Web 应用、URI 监控
2.官方文档

https://github.com/alibaba/druid/wiki/%E9%85%8D%E7%BD%AE_%E9%85%8D%E7%BD%AEWebStatFilter

image-20220814194521364

image-20220814194532601

3.Web 关联监控配置-Web 应用、URI 监控

1.修改src\main\java\com\llp\springboot\config\DruidDataSourceConfig.java

/**
 * 配置druid的web应用和url监控功能
 * <filter>
 *     <filter-name>DruidWebStatFilter</filter-name>
 *     <filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>
 *     <init-param>
 *        <param-name>exclusions</param-name>
 *        <param-value>*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*</param-value>
 *     </init-param>
 *   </filter>
 *   <filter-mapping>
 *     <filter-name>DruidWebStatFilter</filter-name>
 *     <url-pattern>/*</url-pattern>
 *   </filter-mapping>
 */
@Bean
public FilterRegistrationBean webStatFilter(){
    WebStatFilter webStatFilter = new WebStatFilter();
    FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(webStatFilter);
    filterRegistrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
    filterRegistrationBean.setUrlPatterns(Arrays.asList("/*"));
    return filterRegistrationBean;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  1. 为了测试方便,将拦截器放行 /sql 请求
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        /**
         * 1.拦截器会先拦截controller的路径映射
         * 2.如果找不到则去静态资源下查找
         * 3.这里配置/**会拦截所有的请求,包括静态资源
         * 4.这里不拦截静态资源,为什么直接写成 "/images/**","/css/**" ?
         * 5.在SpringBoot中引入了spring-boot-starter-web 依赖,每个starter都会对于的自动装配
         * 6.在WebProperties中配置了类路径映射,因此可以直接省略/static/
         * private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",
         *              "classpath:/resources/", "classpath:/static/", "classpath:/public/" };
         *
         */
        registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**").excludePathPatterns("/","/login","/upload.html","/upload","/images/**","/css/**","/sql");
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

3.重启项目,看看 Web 应用和 URI 监控页面

image-20220814195336374

image-20220814195517371

6.Durid 监控功能-SQL 防火墙

1.需求: 配置 SQL 防火墙
2.官方文档

https://github.com/alibaba/druid/wiki/%E9%85%8D%E7%BD%AE-wallfilter

image-20220814200409860

1.修改src\main\java\com\llp\springboot\config\DruidDataSourceConfig.java

@ConfigurationProperties("spring.datasource")
@Bean
public DataSource dataSource() throws SQLException {
    //1. 配置了 @ConfigurationProperties("spring.datasource")
    //   就可以读取到application.yml的配置,注意:我们需要将bean注入到spring ioc容器中、bean中提供get\set方法
    //2. 我们就不需要调用DruidDataSource 对象的setXxx, 会自动关联

    DruidDataSource druidDataSource = new DruidDataSource();

    //stat:配置sql监控, wall:配置druid sql防火墙
    druidDataSource.setFilters("stat,wall");
    return druidDataSource;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

2.完成测试,重启项目,看看 SQL 防火墙监控是否生效

image-20220814200459289

7.Durid 监控功能-Session 监控

注意:Durid 的Session 监控的是用户的系统不是druid的后台系统

1.需求: 配置 Session 监控
2.官方文档

https://github.com/alibaba/druid/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98

image-20220814201000879

image-20220814201011954

3.Session 监控
  1. 重启项目, 先登录管理系统

image-20220814201056283

  1. 完成测试, 查看监控页需要输入用户名和密码, 点击 Session 监控,可以看到相关信息 (注意要登录用户系统,才能看到 Session 监控信息)

image-20220814200859472

8.Druid Spring Boot Starter

1.基本介绍
  1. 前面我们使用的是自己引入 druid+配置类方式整合 Druid 和监控
  2. Druid Spring Boot Starter 可以让程序员在 Spring Boot 项目中更加轻松集成 Druid 和监控
  3. 每个starter都对应一个自动配置类,这里其实也是根据DruidStatProperties类的属性去匹配@ConfigurationProperties("spring.datasource.druid")

image-20220814204057196

2.应用实例
1.需求: 使用 Druid Spring Boot Starter 方式完成 Druid 集成和监控
2.具体实现
  1. 修改 pom.xml 注销 druid 的依赖

image-20220814201547876

  1. 注销src\main\java\com\llp\springboot\config\DruidDataSourceConfig.java

image-20220814201636183

3.这样我们之前配置的druid就失效了

  1. 查看 druid 文档 https://github.com/alibaba/druid,引入 druid starter
<!--引入druid starter-->
<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>druid-spring-boot-starter</artifactId>
   <version>1.1.17</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

image-20220814201920057

image-20220814201928436

  1. 确认 druid starter 引入哪些依赖

image-20220814202353676

  1. 修改 resources/application.yml 增加配置参数
spring:
  datasource:
    #说明:如果没有指定useSSL=true,启动项目可能会爆红警告,环境问题
    url: jdbc:mysql://127.0.0.1:3306/spring_boot?useSSL=true&useUnicode=true&characterEncoding=UTF-8
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
    druid:
      #配置druid和监控功能
      stat-view-servlet:
        enabled: true
        login-username: llp
        login-password: 123
        reset-enable: false
        #配置web监控
      web-stat-filter:
        enabled: true
        #配置路径,如果没有设置默认为/*
        url-pattern: /*
        exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
      filter:
        #配置sql监控
        stat:
          #1000毫秒及以上就是满慢sql
          slow-sql-millis: 1000
          #启用慢查询log日志
          log-slow-sql: true
          enabled: true
          #配置sql防火墙
        wall:
          #启用
          enabled: true
          config:
            #不允许删除表的sql操作
            drop-table-allow: false
            #不孕执行select *的sql执行
            select-all-column-allow: false
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

image-20220814203701345

image-20220814203921222

7.删除德鲁伊广告配置,新增配置类如下

/**
 * 去除druid底部的广告配置类
 */
@Configuration
@ConditionalOnWebApplication
@AutoConfigureAfter(DruidDataSourceAutoConfigure.class)
@ConditionalOnProperty(name = "spring.datasource.druid.stat-view-servlet.enabled", havingValue = "true", matchIfMissing = true)
public class RemoveDruidOtherConfig {


    /**
     * 方法描述:  除去页面底部的广告
     */
    @Bean
    public FilterRegistrationBean removeDruidAdFilterBean(DruidStatProperties properties) {
        final String filePath = "support/http/resources/js/common.js";
        
        // 获取web监控页面的参数
        DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
        // 提取common.js的配置路径
        String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
        String jsPattern = pattern.replaceAll("\\*", "js/common.js");

        //创建filter进行过滤
        Filter filter = new Filter() {
            @Override
            public void init(FilterConfig filterConfig) throws ServletException {
            }

            @Override
            public void doFilter(ServletRequest req, ServletResponse rep, FilterChain chain) throws IOException, ServletException {
                chain.doFilter(req, rep);
                // 重置缓冲区,响应头不会被重置
                rep.resetBuffer();
                // 获取common.js
                String text = Utils.readFromResource(filePath);
                // 正则替换, 除去底部的广告信息
                text = text.replaceAll("<a.*?banner\"></a><br/>", "");
                text = text.replaceAll("powered.*?shrek.wang</a>", "");
                rep.getWriter().write(text);
            }

            @Override
            public void destroy() {
            }
        };
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(filter);
        registrationBean.addUrlPatterns(jsPattern);
        return registrationBean;
    }
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/857088
推荐阅读
相关标签
  

闽ICP备14008679号