当前位置: 首页 > news >正文

SpringBootWeb案例 Part 5

4. 配置文件

员工管理的增删改查功能我们已开发完成,但在我们所开发的程序中还一些小问题,下面我们就来分析一下当前案例中存在的问题以及如何优化解决。

4.1 参数配置化

在我们之前编写的程序中进行文件上传时,需要调用AliOSSUtils工具类,将文件上传到阿里云OSS对象存储服务当中。而在调用工具类进行文件上传时,需要一些参数:

  • endpoint // 阿里云OSS域名

  • accessKeyID // 用户身份ID

  • accessKeySecret // 用户密钥

  • bucketName // 存储空间的名字

关于以上的这些阿里云相关配置信息,我们是直接写死在Java代码中了(硬编码),如果我们在做项目时每涉及到一个第三方技术服务,就将其参数硬编码,那么在Java程序中会存在两个问题:

  1. 如果这些参数发生变化了,就必须在源程序代码中改动这些参数,然后需要重新进行代码的编译,将Java代码编译成class字节码文件再重新运行程序。(比较繁琐)

  2. 如果我们开发的是一个真实的企业级项目, Java类可能会有很多,如果将这些参数分散的定义在各个Java类当中,我们要修改一个参数值,我们就需要在众多的Java代码当中来定位到对应的位置,再来修改参数,修改完毕之后再重新编译再运行。(参数配置过于分散,导致不方便集中的管理和维护

思考:怎样将这些参数集中配置管理呢?

回答:Java代码会有很多这毋庸置疑,但是对于SpringBoot项目来说,什么东西一般只有一个?配置文件只有一个,代码当中所有容易变动的参数建议放在配置文件当中进行管理和维护,也就是application.properties。

将参数集中保存/配置在properties配置文件当中的优点:

  1. 在application.properties当中的配置做了修改,我们不用进行编译,而且,所有的配置如果都交给了application.properties配置文件来集中管理,以后如果我们想修改,我们直接找到properties配置文件来做一个修改就可以了,软编码
  2. 其次,安全:敏感的参数(如数据库连接密码)不应该直接硬编码在代码中,而是通过配置文件进行管理,这样可以降低配置泄漏的风险,并更好的保护敏感信息。
  3. 灵活性和可移植性:不同环境的参数配置只需在对应的配置文件中进行修改即可。
  4. 易用性和可读性:将参数配置到配置文件中,使得参数的设置更加直观和易于理解,提高配置文件的可读性和维护性。

注意:这里的配置文件指的可不是pom.xml,pom.xml这份配置文件是Maven项目的配置文件,是用来配置依赖的,而application.properties才是SpringBoot项目的配置文件。

为了解决以上分析的问题,我们可以将参数配置在配置文件中。而application.properties配置文件的形式就是key = value,前面的key可以自己定义,注意在项目开发时,尽量要定义的有一定的业务含义,如下:

问题解决: 

#自定义的阿里云OSS配置信息
aliyun.oss.endpoint=https://oss-cn-beijing.aliyuncs.com
aliyun.oss.accessKeyId=LTAI5tHGMz3QSEMrwu6wSmSC
aliyun.oss.accessKeySecret=4yBkKaSJvvqobtnK36fTGXiPreqh5P
aliyun.oss.bucketName=gch-web-tlias01

注意:

  • 由于properties配置文件当中的信息本身就是一个字符串,所以我们就不需要再来加引号,后面的分号也不需要,等号两边的空格也不需要。

在将阿里云OSS配置参数交给properties配置文件来管理之后,我们的AliOSSUtils工具类就变为以下形式:

/*** 使用阿里云OSS进行文件存储的工具类*/
@Component
public class AliyunOSSUtils {/** 以下4个参数没有指定值(默认值:null)*//** 指定连接的阿里云OSS服务的地址 */private String endpoint;/** 阿里云OSS AccessKey */private String accessKeyId;private String accessKeySectre;/** 存储空间Bucket的名称 */private String bucketName;//省略其他代码...
}

此时如果直接调用AliOSSUtils类当中的upload方法进行文件上传时,这4项参数全部为null,原因是因为并没有给它赋值。

此时我们是不是需要将配置文件当中所配置的属性值读取出来,并分别赋值给AliOSSUtils工具类当中的各个属性呢?那应该怎么做呢?

想法:IO流,通过IO流读取并解析配置文件当中配置项的值,然后再给成员变量赋值。          

因为application.properties是springboot项目默认的配置文件,所以SpringBoot程序在启动时会默认读取application.properties配置文件,而我们可以使用SpringBoot提供一个的现成的注解:@Value获取配置文件中的数据。  

  • @Value 注解通常用于外部配置的属性注入,具体用法为: @Value("${配置文件中的key}")  
  • 通过@Value注解进行属性注入,将外部的属性配置注入进来赋值给成员变量,在@Value注解当中来指定我们要注入的是配置文件当中的哪一个Key对应的属性值。
/*** 使用阿里云OSS进行文件存储的工具类*/
@Component
public class AliyunOSSUtils {/** 指定连接的阿里云OSS服务的地址 */@Value("${aliyun.oss.endpoint}")private String endpoint;/** 阿里云OSS AccessKey */@Value("${aliyun.oss.accessKeyId}")private String accessKeyId;@Value("${aliyun.oss.accessKeySecret}")private String accessKeySecret;/** 存储空间Bucket的名称 */@Value("${aliyun.oss.bucketName}")private String bucketName;
}

总结:

  • 如果在项目开发当中,我们需要用到一些技术或者是服务,我们就可以把这个技术或者是服务它在运行时所需要的参数直接配置在配置文件当中,交给配置文件进行统一的管理和维护,然后在程序当中我们就可以通过@Value注解来注入对应的外部配置的属性值。

4.2 yml配置文件

  • 全新格式的配置文件 - yml配置文件 

在SpringBoot项目当中,是支持多种配置方式的,前面我们一直使用SpringBoot项目创建完毕后自带的application.properties配置文件进行属性的配置,properties配置文件的配置形式就是键值对Key=Value,等号之前是Key,等号之后是Value,那其实呢,在SpringBoot项目当中是支持多种配置方式的,除了支持properties配置文件以外,还支持另外一种类型的配置文件,就是我们接下来要学习的yml格式的配置文件

  • yml格式的配置文件,它的后缀可以是yml(推荐),也可以是yaml,这两个配置文件它的配置形式都是相同的,仅仅是后缀名不同而已。
  • 如果是yml格式的配置文件,配置文件的名字也必须叫做application.yml。

yml 格式的配置文件,后缀名有两种:

  • yml (推荐)

  • yaml

SpringBoot提供了多种属性配置方式 / SpringBoot所支持的配置文件

  • application.properties

    server.port=8080
    server.address=127.0.0.1
    
  • application.yml

    server:port: 8080address: 127.0.0.1
  • application.yaml

    server:port: 8080address: 127.0.0.1
  • 可以看到,在SpringBoot当中所支持的这三种配置文件,配置文件的名字都是相同的,都叫applictaion,只是文件扩展名不同而已。
  • 如果是yml格式的配置文件,它的配置形式是键值对Key:Value,而且这个Key还是按照层级书写的,相比于传统的properties格式,YAML格式的配置文件使用缩进和结构化语法来表示数据的层级关系。
  1. 层级结构:YAML配置文件使用缩进来表示层级关系,前面的缩进相同,代表它们的层级也相同。比如我们要配置服务器运行的端口号:server.port,

  • 在上面的示例中,porthost 和 timeout 是 server 的子属性它们位于不同的缩进级别

2. 键值对(对象/Map集合):YAML 使用冒号(:)来表示键值对。冒号后面是一个空格,然后是相应的值。

  • 在上面的示例中,urlusername 和 password 是 database 的子属性。

3. 列表(数组/List/Set集合):YAML 支持表示列表数据的方式,使用短横线(-)表示列表中的项目。

  • 在上面的示例中,fruits 是一个包含三个元素的列表。 

4. 注释:使用井号(#)表示注释。井号后面的内容将被视为注释,不会被解析。

  • 在上面的示例中,井号后面的内容是注释,不会影响配置的读取和解析。 

这些是 YAML 配置文件的一些常见形式。通过使用缩进、键值对、列表和注释等语法规则,YAML 配置文件可以更清晰和易读地表示数据的结构和层级关系。

在SpringBoot的resources目录下来创建一份儿applictaion.yml格式的配置文件,创建后可以看到,在我们所创建出来的application.yml格式的配置文件前面多了一个SpringBoot的Logo,这就说明SpringBoot是识别这份配置文件的。 

application.yml

演示:输入server之后给出自动提示,我们要配置的是SpringBoot内嵌的Tomcat服务器运行的端口号,默认是8080,我们可以修改内嵌的Tomcat服务器端口号为9000:

常见的三类配置文件格式的优缺点对比:  

  • XML配置文件当中,我们要定义很多的标签,既要定义开始标签,又要定义结束标签,既有父标签,也有子标签,虽然层级结构比较清晰,但是配置比较臃肿
  • properties配置文件相对于XML配置文件来说,会更加轻量化一些,它的配置格式是键值对Key=Value,但是,在项目开发当中,我们经常会使用大量的框架以及第三方的技术,而在使用框架时,我们又需要在配置文件当中来配置很多的参数,而在框架当中,为了让这个Key更加的简明知意,并且具有一定的标识意义,所以这个Key通常来说都是分层级的,如果用properties配置文件来配置,那就是平铺直叙层级结构并不清晰,而且这个Key越复杂,层级架构约不清晰,所以properties配置文件相对于XML配置文件来说,它会更加轻量化一些,但是它并没有XML配置文件结构清晰。 
  • 如果采用yml格式来配置,这个层级结构就会更加清晰没有一点儿多余的配置,而且通过该配置结构可以更清晰的表示数据的结构和层级关系,完全以数据为中心,简洁,没有一点儿多余的配置。

在SpringBoot当中,仅支持properties和yml格式的配置,而在现在的企业开发当中,SpringBoot项目基本上采用的都是yml格式的配置文件,很少使用properties,所以,推荐使用yml格式的配置文件。

对于yaml格式的配置文件,我们一般会选择yml这个拓展名,更加简单

我们可以看到配置同样的数据信息,yml格式的数据有以下特点:

  1. - 容易阅读
  2. - 容易与脚本语言交互
  3. - 以数据为核心,重数据轻格式

简单的了解过SpringBoot所支持的配置文件,以及不同类型配置文件之间的优缺点之后,接下来我们就来了解下yml配置文件的基本语法:  

  • 大小写敏感

  • 数值前边必须有空格,作为分隔符

  • 使用缩进表示层级关系,缩进时,不允许使用Tab键,只能用空格(对于现在的开发工具来说,使用Tab制表符或者空格无所谓,因为高级开发工具idea中会自动的将yml格式配置文件当中的Tab转换为空格)

  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可

  • #表示注释,从这个字符一直到行尾,都会被解析器忽略

 

yml文件当中常见的两类数据格式:

在这里我们主要介绍最为常见的两类:

  1. 定义对象或Map集合

  2. 定义数组、List或Set集合

对象/Map集合  

 

 

数组/List/Set集合  

 

总结: 

 

4.3 yml配置 

熟悉完了yml文件的基本语法后,我们修改下之前案例中使用的配置文件,变更为application.yml配置方式:  

  • 在application.yml中配置案例相关的配置项,接着删除传统的application.properties配置文件 

对比: 

原有的application.properties配置文件:

#数据库连接
#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的URL
spring.datasource.url=jdbc:mysql://localhost:3306/tlias
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=123456#开启mybatis的日志输出{配置MyBatis的日志,指定输出到控制台}
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#开启数据库表字段 到 实体类属性的驼峰映射 a_column ---> aColumn
mybatis.configuration.map-underscore-to-camel-case=true#PageHelper分页插件的配置
#配置数据库方言
pagehelper.helper-dialect=mysql
#分页合理化参数配置
pagehelper.reasonable=true#配置单个文件最大上传大小的限制,默认是1MB
spring.servlet.multipart.max-file-size=10MB
#配置单个请求最大上传大小的限制(一次请求可以上传多个文件),默认是10MB
spring.servlet.multipart.max-request-size=100MB#自定义的阿里云OSS配置信息
aliyun.oss.endpoint=https://oss-cn-beijing.aliyuncs.com
aliyun.oss.accessKeyId=LTAI5tHGMz3QSEMrwu6wSmSC
aliyun.oss.accessKeySecret=4yBkKaSJvvqobtnK36fTGXiPreqh5P
aliyun.oss.bucketName=gch-web-tlias01

新建的application.yml配置文件:

#注意,yml格式的配置是键值对Key: Value,并且是Key: +空格 + Value
#数据库连接四要素
spring:datasource:#驱动类名称driver-class-name: com.mysql.cj.jdbc.Driver#数据库连接的URLurl: jdbc:mysql://localhost:3306/tlias#连接数据库的用户名username: root#连接数据库的密码password: 123456#文件上传的配置(关键字:multipart)servlet:multipart:#配置单个文件最大上传大小的限制,默认是1MBmax-file-size: 10MB#配置单个请求最大上传的大小的限制(一次请求可以上传多个文件),默认是10MBmax-request-size: 100MB#MyBatis配置(关键字camel、log-impl)
mybatis:configuration:#开启MyBatis的日志输出{配置MyBatis的日志,指定输出到控制台}log-impl: org.apache.ibatis.logging.stdout.StdOutImpl#开启数据库表字段 到 实体类属性的驼峰映射 a_column ---> aColumnmap-underscore-to-camel-case: true#PageHelper分页插件的配置
pagehelper:#配置数据库方言helper-dialect: mysql#分页合理化参数配置reasonable: true#自定义的阿里云OSS配置信息
aliyun:oss:#OSS对象存储服务的域名endpoint: https://oss-cn-beijing:aliyuncs:com#阿里云账号AccessKeyaccessKeyId: LTAI5tHGMz3QSEMrwu6wSmSC#阿里云账号AccessKey对应的密钥accessKeySecret: 4yBkKaSJvvqobtnK36fTGXiPreqh5P#存储空间Bucket的名称bucketName: gch-web-tlias01#配置服务器相关信息
server:port: 8080address: 127.0.0.1#定义对象/Map集合(key:Value)
user:name: Tomage: 18password: 20#数组/List/Set集合(列表):使用短横线-表示列表中的项目
hobby:-java-game-sport

4.4 @ConfigurationProperties

  • 注解@ConfigurationProperties  

学习完了yml配置文件之后,最后再来介绍一个注解@ConfigurationProperties。在介绍注解之前,我们先来看一个场景,分析下代码当中可能存在的问题:  

  • 我们在application.properties或者application.yml中配置了阿里云OSS的四项参数之后如果Java程序中需要这四项参数数据,我们直接通过@Value注解来进行注入,通过@Value注解来注入外部配置文件当中的属性值,并且在@Value注解当中要通过${""}的形式来指定我们要注入的是哪一个配置项的值,这种方式本身没有什么问题问题,但是如果说需要注入的属性较多(例:需要20多个参数数据),每一个属性/成员变量上都需要加上这么一个@Value注解,导致我们整个编码写起来就会比较繁琐,而且比较臃肿。

那么有没有一种方式可以简化这些配置参数的注入呢?我们不用在每一个成员变量上都加上这个@Value注解,就可以自动的将配置文件当中配置项的值直接注入给这个对象的属性当中来呢?

  • 答案是肯定的,在Spring中给我们提供了一种简化方式,可以直接将配置文件中配置项的值自动的注入到对象的属性当中,但是,它是有前提条件的(Spring提供的简化方式套路):
  1. 需要创建一个实体类,并且配置文件当中Key的名字必须要和实体类当中的属性名保持一致(比如:配置文件当中叫endpoints,实体类当中的属性也得叫endpoints ),并且还要为实体类属性提供Getter/Setter方法,所以在实体类上面要加上@Data注解
  2. 需要将实体类的实例交给IOC/Spring容器管理,成为IOC/Spring容器当中的bean对象,所以需要在实体类上面加上@Component注解;
  3. 当前,bean对象当中的属性还不能够完成自动注入,原因是因为现在仅仅是这个bean对象的属性名与配置项的后缀保持一致了,而配置项前面还有一个前缀,所以我们还需要指定一下配置项的前缀,指定前缀我们就可以使用@ConfigurationProperties这个注解来指定,我们只需要在实体类上面加上@ConfigurationProperties注解,并通过prefix属性来指定配置项的前缀,此时就代表我需要将该前缀下面的子属性/子配置项对应的值自动的注入到实体类对象(bean对象)当中的属性当中来。
  • 此时,在其他类当中我们要想获取配置项对应的属性值,那我们只需要注入该实体类的bean对象,然后调用它的get方法就可以获取到对应的属性值了。
  • prefix:前缀  configuration:配置

实体类:AliyunOSSProperties  

package com.gch.utils;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;/**阿里云OSS相关配置:将配置文件当中配置项的值自动的注入到bean对象的属性当中*/
@Data
@Component
@ConfigurationProperties(prefix = "aliyun.oss")
public class AliyunOSSProperties {/** 指定连接的阿里云OSS对象存储服务的域名/地址 */private String endpoint;/** 阿里云OSS账号AccessKey身份ID */private String accessKeyId;/** 阿里云OSS账号AccessKey身份ID对应的密钥 */private String accessKeySecret;/** 存储空间Bucket的名称 */private String bucketName;
}

AliyunOSSUtils:

package com.gch.utils;import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;
import java.util.UUID;/**使用阿里云OSS进行文件存储的工具类*/
@Component // 当前类对象由Spring创建和管理
public class AliyunOSSUtils {/** 注入配置参数实体类对象 */@Autowiredprivate AliyunOSSProperties aliyunOSSProperties;/*** 实现文件上传到OSS* @param multipartFile 在服务端来接收到上传的文件* @return 返回图片访问的URL* @throws IOException*/public String upload(MultipartFile multipartFile) throws IOException {// 获取阿里云OSS参数String endpoint = aliyunOSSProperties.getEndpoint();String accessKeyId = aliyunOSSProperties.getAccessKeyId();String accessKeySecret = aliyunOSSProperties.getAccessKeySecret();String bucketName = aliyunOSSProperties.getBucketName();/** 构造唯一的文件对象名称:UUID + 文件扩展名 */String objectName = UUID.randomUUID().toString() + multipartFile.getOriginalFilename().substring(multipartFile.getOriginalFilename().lastIndexOf("."));// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(endpoint,accessKeyId,accessKeySecret);try {// 创建PutObjectRequest对象。PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, multipartFile.getInputStream());// 上传文件到OSSPutObjectResult result = ossClient.putObject(putObjectRequest);} finally {if (ossClient != null) {// 关闭ossClientossClient.shutdown();}}// 返回文件访问路径return endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + objectName;}
}

重新启动项目: 

总结:

  • 通过@ConfigurationProperties注解就可以自动的将配置文件当中的配置项自动的注入到bean对象的属性当中来。 

在我们添加上注解后,会发现IDEA窗口上面出现一个红色警告:

 

这个警告提示是告知我们还需要引入一个依赖:  

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId>
</dependency>

当我们在pom.xml文件当中配置了这项依赖之后,我们重新启动服务,大家就会看到在properties或者是yml配置文件当中,就会提示阿里云 OSS 相关的配置项。所以这项依赖它的作用就是会自动的识别被@ConfigurationProperties注解标识的bean对象,然后在配置文件当中配置的时候就会自动的提示与这个bean对象的属性名相对应的配置项的名字。

注意:刚才的红色警告,已经变成了一个灰色的提示,提示我们需要重新运行SpringBoot服务  

 

4.5 @ConfigurationProperties 与 @Value 

相同点:都是用来注入外部配置的属性的。

不同点:

  • @Value注解只能一个一个进行外部属性的注入

  • @ConfigurationProperties注解可以批量的将外部的属性配置注入到bean对象的属性中

  • 如果要注入的属性非常的多,并且还想做到复用,就可以定义这么一个bean对象,通过 @ConfigurationProperties 批量的将外部的属性配置直接注入到bean对象的属性当中
  • 在其他的类当中,我要想获取到注入进来的属性,我直接注入bean对象,然后调用 get 方法,就可以获取到对应的属性值了。

总结: 

 

 

相关文章:

SpringBootWeb案例 Part 5

4. 配置文件 员工管理的增删改查功能我们已开发完成&#xff0c;但在我们所开发的程序中还一些小问题&#xff0c;下面我们就来分析一下当前案例中存在的问题以及如何优化解决。 4.1 参数配置化 在我们之前编写的程序中进行文件上传时&#xff0c;需要调用AliOSSUtils工具类&…...

【ES6】Promise.race的用法

Promise.race()方法同样是将多个 Promise 实例&#xff0c;包装成一个新的 Promise 实例。 const p Promise.race([p1, p2, p3]);上面代码中&#xff0c;只要p1、p2、p3之中有一个实例率先改变状态&#xff0c;p的状态就跟着改变。那个率先改变的 Promise 实例的返回值&#…...

PMP - 敏捷 3355

三个核心 产品负责人 负责最大化投资回报&#xff08;ROI&#xff09;&#xff0c;通过确定产品特性&#xff0c;把他们翻译成一个有优先级的列表 为下一个 sprint 决定在这个列表中哪些应该优先级最高&#xff0c;并且不断调整优先级以及调整这个列表 职责是定义需求、定义…...

Mapbox-gl 关闭所有Popup,以及关闭按钮出现黑色边框bug

1.官方示例 var popup new mapboxgl.Popup().addTo(map);popup.remove(); 很明显&#xff0c;需要记录popup对象&#xff0c;管理起来比较麻烦。 2.本人采用div的方式关闭所有的popup&#xff0c;在map对象上新增加方法 map.closePopupmapView.popupClear function(){$(&q…...

RE:从零开始的车载Android HMI(四) - 收音机刻度尺

最近比较忙&#xff0c;研究复杂的东西需要大量集中的时间&#xff0c;但是又抽不出来&#xff0c;就写点简单的东西吧。车载应用开发中有一个几乎避不开的自定义View&#xff0c;就是收音机的刻度条。本篇文章我们来研究如何绘制一个收音机的刻度尺。 本系列文章的目的是在讲…...

评估安全 Wi-Fi 接入:Cisco ISE、Aruba、Portnox 和 Foxpass

在当今不断变化的数字环境中&#xff0c;对 Wi-Fi 网络进行强大访问控制的需求从未像现在这样重要。各组织一直在寻找能够为其用户提供无缝而安全的体验的解决方案。 在本博客中&#xff0c;我们将深入探讨保护 Wi-Fi&#xff08;和有线&#xff09;网络的四种领先解决方案——…...

java 泛型作为方法的返回值的封装

问题背景 业务需要&#xff0c;经常需要http方式调用某服务&#xff0c;然后某服务返回特定类型的返回内容。 类似 String resStr xxxHttpClient.post() &#xff0c;然后它返回一个字符串&#xff0c;你还需要反序列化成某种格式的。 返回值可以反序列化成的形式如下&#…...

ASP.NET Core 中基于 Minimal APIs 的Web API

基于 Minimal APIs 的Web API Minimal APIs 是ASP.NET Core中快速构建 REST API 的方式&#xff0c;可以用最少的代码构建全功能的REST API。比如下面三行代码&#xff1a; var app WebApplication.Create(args); app.MapGet("/", () > "Hello World!&quo…...

Unity ProBuilder SetUVs 不起作用

ProBuilder SetUVs 不起作用 &#x1f41f; 需要设置face.manulUV true public static void Set01UV(this ProBuilderMesh mesh){foreach (var face in mesh.faces){face.manualUV true;//设置为手动uv}var vertices mesh.GetVertices().Select(v > v.position).ToArray(…...

c#接口(interface)

概述&#xff1a; 在C#中&#xff0c;接口是一种定义了一组相关方法、属性和事件的规范。接口可以被类或结构体实现&#xff0c;以提供一种方式来定义类之间的契约或协议。 接口定义了一组成员&#xff0c;这些成员没有具体的实现。实现接口的类必须提供这些成员的具体实现。…...

SSH远程连接macOS服务器:通过cpolar内网穿透技术实现远程访问的设置方法

文章目录 前言1. macOS打开远程登录2. 局域网内测试ssh远程3. 公网ssh远程连接macOS3.1 macOS安装配置cpolar3.2 获取ssh隧道公网地址3.3 测试公网ssh远程连接macOS 4. 配置公网固定TCP地址4.1 保留一个固定TCP端口地址4.2 配置固定TCP端口地址 5. 使用固定TCP端口地址ssh远程 …...

【C++】Visual Studio EditorConfig 格式设置

【C】Visual Studio EditorConfig 格式设置 文章目录 【C】Visual Studio EditorConfig 格式设置I - EditorConfig1.1 - 通用设置indent_styleindent_sizetab_widthend_of_linecharsettrim_trailing_whitespaceinsert_final_newline II - Visual Studio 特定键值缩进设置cpp_in…...

服务器单机大规模数据存储方案

大规模数据存储都需要解决三个核心问题&#xff1a; 1.数据存储容量的问题&#xff0c;既然大数据要解决的是数据 PB 计的数据计算问题&#xff0c;而一般的服务器磁盘容量通常 1&#xff5e;2TB&#xff0c;那么如何存储这么大规模的数据呢&#xff1f; 2.数据读写速度的问题&…...

ElasticSearch-集成ik分词器

本文已收录于专栏 《中间件合集》 目录 背景介绍版本选择优势说明集成过程1.下载安装包2.解压安装包3.重启ElasticSearch服务3.1通过ps -ef | grep elastic查看正在启动的es进程号3.2使用kill -9 xxx 杀死进程3.3使用 ./elasticsearch 启动es服务 分词测试细粒度分词方式分词请…...

c++版opencv求二值图的质心

代码 #include <iostream> #include <opencv2/core.hpp> #include <opencv2/highgui.hpp> #include <opencv2/imgproc.hpp>int main(int argc, char* argv[]) {cv::Mat input_image cv::imread("Untitled.png", cv::IMREAD_GRAYSCALE);cv:…...

6、深入解析Kotlin类与对象:构造、伴生、单例全面剖析

前言 本篇文章将带您了解Kotlin编程中的重要概念&#xff1a;类及构造函数、访问修饰符、伴生对象和单例模式。就像搭积木一样&#xff0c;我们会逐步揭开这些概念的面纱&#xff0c;让您轻松理解它们的作用和用法。无论您是编程新手还是有经验的开发者&#xff0c;本文都将为…...

【开源ESP32谷歌恐龙小游戏】【游戏演示和介绍】LVGL ST7789 适用于Arduino

【源码及教程地址-持续更新】 ESP32 C3 LVGL 迷你小电视 Google谷歌恐龙小游戏 1.9寸LCD显示屏开发板 ST7789 适用于Arduino开发板,教程,资料,程序,代码,PDF手册 【开源 & ESP32谷歌恐龙小游戏】【游戏演示和介绍】LVGL ST7789 适用于Arduin...

openCV实战-系列教程7:轮廓检测2与模板匹配(轮廓检测/轮廓特征/轮廓近似/轮廓边界矩阵/轮廓边界圆/模版匹配)、原理解析、源码解读

&#x1f9e1;&#x1f49b;&#x1f49a;&#x1f499;&#x1f49c;OpenCV实战系列总目录 打印一个图片可以做出一个函数&#xff1a; def cv_show(img,name):cv2.imshow(name,img)cv2.waitKey()cv2.destroyAllWindows() 1、轮廓特征与近似 1.1 轮廓特征 前面我们计算了…...

cs231n_1_IntroToConv

参考的视频来自如下链接https://www.bilibili.com/video/BV1Ed4y1b7bm/ 参考笔记如下https://blog.csdn.net/TeFuirnever/article/details/89059673 x.1 CV历史 生物快速发展于5.4亿年前&#xff0c;那时的化石显示生物进化出了视觉&#xff0c;视觉使得生物多样性大爆炸。 …...

OPENCV实现SURF特征检测

1、SURF优点:SIFT速度慢,一次出现了SURF;2、使用SURF步骤:surf = cv2.xfeatures2d.SURF_create()kp,des = surf.detectAndComputer(img,mask)# -*- coding:utf-8 -*- """ 作者:794919561 日期:2023/8/31 """# -*-...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别

【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而&#xff0c;传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案&#xff0c;能够实现大范围覆盖并远程采集数据。尽管具备这些优势&#xf…...

Web中间件--tomcat学习

Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机&#xff0c;它可以执行Java字节码。Java虚拟机是Java平台的一部分&#xff0c;Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

tomcat入门

1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效&#xff0c;稳定&#xff0c;易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...

【Linux】自动化构建-Make/Makefile

前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具&#xff1a;make/makfile 1.背景 在一个工程中源文件不计其数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;mak…...

在 Spring Boot 中使用 JSP

jsp&#xff1f; 好多年没用了。重新整一下 还费了点时间&#xff0c;记录一下。 项目结构&#xff1a; pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解

进来是需要留言的&#xff0c;先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码&#xff0c;输入的<>当成字符串处理回显到页面中&#xff0c;看来只是把用户输…...