【JavaEE】深入浅出:Spring Boot配置文件全解析

news2024/11/14 15:30:08

目录

    • SpringBoot 配置⽂件
      • 配置⽂件作⽤
        • SpringBoot配置⽂件
      • 配置⽂件快速⼊⼿
      • 配置⽂件的格式
      • properties 配置⽂件说明
        • properties 基本语法
        • 读取配置⽂件
        • properties 缺点分析
      • yml 配置⽂件说明
        • yml 基本语法
        • yml 使⽤进阶
          • yml 配置不同数据类型及 null
          • 配置对象
          • 配置集合
          • 配置Map
        • yml优缺点
      • 练习
        • 验证码案例
          • Kaptcha 插件介绍
          • 需求
          • 准备工作
          • 约定前后端交互接口
          • 实现服务器代码
          • 调整前端⻚⾯代码
      • 总结


SpringBoot 配置⽂件

  1. 学习SpringBoot配置⽂件的格式以及对应的语法
  2. 了解两个配置⽂件格式的差异

配置⽂件作⽤

热加载:写的代码,立即就被加载进来,生效了

热部署:如果代码发生了变动,就会重新部署

计算机上有数以千计的配置⽂件, 我们使⽤的绝⼤多数软件, ⽐如浏览器, 微信, Idea, 甚⾄电脑, ⼿机, 都离不开配置⽂件. 我们可能永远不会直接与其中的⼤部分⽂件打交道,但它们确实以不同的形式散落在我们的计算机上, ⽐如 C:\Users, C:\Windows⽂件夹, 以及各种 *.config, *.xml ⽂件

配置⽂件主要是为了解决硬编码带来的问题, 把可能会发⽣改变的信息, 放在⼀个集中的地⽅, 当我们启动某个程序时, 应⽤程序从配置⽂件中读取数据, 并加载运⾏.(简单一句话:解决硬编码的问题

硬编码是将数据直接嵌⼊到程序或其他可执⾏对象的源代码中, 也就是我们常说的"代码写死"。

⽐如⼿机字体⼤⼩

如果采⽤硬编码的⽅式, 就直接在程序中指定字体⼤⼩, 所有的⽤⼾使⽤的都是同⼀个字体⼤⼩,但是不同的⽤⼾有不同的偏好, 我们可以把⼿机字体的⼤⼩放在配置⽂件中, 当程序启动时, 读取配置, 以⽤⼾设置的字体⼤⼩来显⽰

使⽤配置⽂件, 可以使程序完成⽤⼾和应⽤程序的交互, 或者应⽤程序与其他应⽤程序的交互

SpringBoot配置⽂件

SpringBoot的配置文件只有application后缀可以是.yml或者是.properties

不过这个名字可以改,但没必要改

SpringBoot⽀持并定义了配置⽂件的格式, 也在另⼀个层⾯达到了规范其他框架集成到SpringBoot的⽬的.

很多项⽬或者框架的配置信息也放在配置⽂件中, ⽐如:

  • 项⽬的启动端⼝
  • 数据库的连接信息(包含⽤⼾名和密码的设置)
  • 第三⽅系统的调⽤密钥等信息
  • ⽤于发现和定位问题的普通⽇志和异常⽇志等

项⽬的启动端⼝

SpringBoot内置了Tomcat服务器, 默认端⼝号是8080, 但是⽤⼾电脑上8080端⼝号有可能就被其他应⽤程序占⽤了, 所以SpringBoot需要⽀持让⽤⼾⾃定义端⼝号数据库连接信息

为了更⽅便简单的访问数据库, 出现了⼀些持久层框架, 其实就是对JDBC进⾏了更深层次的封装.让⽤⼾通过简单⼏⾏代码就可完成数据库的访问. 但是不同的应⽤程序访问的数据库不同, 这些持久层框架就需要⽀持⽤⼾可以⾃定义配置数据库的连接信息.

运行SpringBoot程序

  1. 打jar包

在这里插入图片描述

  1. 通过 java -jarXXX.jar

配置⽂件快速⼊⼿

我们在前⾯讲了Tocmat 默认端⼝号是8080, 所以我们程序访问时的端⼝号也是8080

但是如果8080端⼝号已经被其他进程使⽤了呢? 我们可以通过配置⽂件来修改服务的端⼝号

SpringBoot 在创建项⽬时, 就已经帮我们创建了配置⽂件

在这里插入图片描述

修改 application.properties ⽂件

server.port=9090

重新运⾏程序, 观察⽇志

在这里插入图片描述

访问程序: http://127.0.0.1:9090/login.html

在这里插入图片描述

此时: http://127.0.0.1:8080/login.html 就不能再访问了

配置⽂件的格式

Spring Boot 配置⽂件有以下三种:

  • application.properties
  • application.yml
  • application.yaml

其实是事实是:SpringBoot只支持3个文件

yml 为yaml的简写, 实际开发中出现频率最⾼. yaml 和yml 的使⽤⽅式⼀样, 下面只讲yml⽂件的使用

当应⽤程序启动时, Spring Boot会⾃动从classpath路径找到并加载application.propertiesapplication.yaml 或者 application.yml ⽂件.

也可以通过spring.config.name指定⽂件路径和名称, 参考 https://docs.spring.io/springboot/docs/current/reference/html/features.html#features.external-config.files

在这里插入图片描述

类似商品的包装⼀样, 有新⽼两款包装. properties 类型的配置⽂件就属于⽼款包装,也是创建Spring Boot 项⽬时默认的⽂件格式(主要是因为仓库⾥还有库存),⽽ yml 属于新版包装,如果⽤⼾了解情况直接指定要新款包装,那么就直接发给他

特殊说明

  1. 理论上讲 .properties.yml 可以并存在于⼀个项⽬中,当 .properties.yml并存时,两个配置都会加载. 如果配置⽂件内容有冲突, 则以 .properties 为主, 也就是 .properties 优先级更⾼。并不是.yml会不生效

  2. 虽然理论上来讲 .properties 可以和 .yml 共存,但实际的业务当中,我们通常会采取⼀种统⼀的配置⽂件格式(也就是只用其中一个文件就行),这样可以更好的维护(降低故障率)。现在都是用.yml更多

properties 配置⽂件说明

properties 配置⽂件是最早期的配置⽂件格式,也是创建 SpringBoot 项⽬默认的配置⽂件

properties 基本语法

properties 是以键值的形式配置的,key 和 value 之间是以"="连接的,如:

# 配置项⽬端⼝号
server.port=8080
# 配置数据库连接信息	
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/testdb?characterEncoding=utf8&
spring.datasource.username=root
spring.datasource.password=123456

# 自定义配置
demo.key1=hello.properties

key 的格式建议小写,单词之间用 . 进行分割

PS:⼩技巧:配置⽂件中使⽤“#”来添加注释信息

更多可参考官网:https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html#application-properties

读取配置⽂件

如果在项⽬中,想要主动的读取配置⽂件中的内容,可以使⽤ @Value 注解来实现。@Value 注解使⽤" ${} "的格式读取,如下代码所⽰:

properties 配置如下:

# 自定义配置
demo.key1=hello.properties
@RestController
public class PropertiesController {
    //读取配置文件
    @Value("${demo.key1}")
    private String key1;

    @RequestMapping("/readKey")
    public String readKey(){
        return "读取到的配置项key1:"+key1;
    }
}

最终执⾏效果:

在这里插入图片描述

${demo.key1}如果去到$就会把双引号的值赋给当前变量

properties 缺点分析

properties 配置是以 key-value 的形式配置的,如下图所⽰:

在这里插入图片描述

从上述配置key看出,properties 配置⽂件中会有很多的冗余的信息,⽐如这些:

在这里插入图片描述

想要解决这个问题,就可以使⽤ yml 配置⽂件的格式化了.

yml 配置⽂件说明

yml 是 YAML 是缩写,它的全称 Yet Another Markup Language 翻译成中⽂就是“另⼀种标记语⾔”.

我们先来学习yml的语法

yml 基本语法

yml 是树形结构的配置⽂件,它的基础语法是"key: value".

key 和 value 之间使⽤英⽂冒号加空格的⽅式组成空格不可省略

基础语法如下:

第⼀项的配置为正确的,key 也是⾼亮显⽰的. 第⼆项没有空格是错误的使⽤⽅式,第⼆项的 key 也没有⾼亮显⽰

使⽤ yml 连接数据库

yml 使⽤⽰例:

# 修改端口号
server:
  port: 9092
# 数据库相关配置
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/testdb?characterEncoding=utf8&useSSL=false
    username: root
    password: 123456

yml 和 properties 连接数据库的配置对⽐

在这里插入图片描述

在这里插入图片描述

yml 使⽤进阶
yml 配置不同数据类型及 null
# 字符串
string.value: Hello
# 布尔值,true或false
boolean.value: true
boolean.value1: false
# 整数
int.value: 10
# 浮点数
float.value: 3.14159
# Null,~代表null
null.value: ~
# "" 空字符串
#, 直接后⾯什么都不加就可以了, 但这种⽅式不直观, 更多的表⽰是使⽤引号括起来
empty.value: ''

yml 配置读取

yml 读取配置的⽅式和 properties 相同,使⽤ @Value 注解即可,实现代码如下:

yml配置:

demo:
  key1: hello,yml
@RestController
public class YmlController {
    @Value("${demo.key1}")
    public String key1;

    @RequestMapping("/readYml")
    public String readYml(){
        return key1;
    }
}

访问: http://127.0.0.1:8080/readYml

运⾏结果:

在这里插入图片描述

demo:
  key1: hello,yml
  key2: hello,key2
  key3: hello,key3

这里用了这个**@PostConstruct注解,修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次**

@RestController
public class YmlController {
    @Value("${demo.key1}")
    public String key1;
    @Value("${demo.key2}")
    public String key2;
    @Value("${demo.key3}")
    public String key3;

    @RequestMapping("/readYml")
    public String readYml(){
        return key1;
    }

    @PostConstruct
    public void init(){
        System.out.println("key1:"+key1);
        System.out.println("key2:"+key2);
        System.out.println("key3:"+key3);
    }
}

在这里插入图片描述

注意事项:value 值加单双引号

字符串默认不⽤加上单引号或者双引号,如果加英⽂的单双引号可以表⽰特殊的含义。

尝试在 application.yml 中配置如下信息:

string:
	str1: Hello \n Spring Boot.
	str2: 'Hello \n Spring Boot.'
    str3: "Hello \n Spring Boot."

读取程序实现代码如下:

@RestController
public class ReadYml {
    @Value("${string.str1}")
    private String str1;
    @Value("${string.str2}")
    private String str2;
    @Value("${string.str3}")
    private String str3;

    @RequestMapping("/yml")
    public String readYml() {
        System.out.println(str1);
        System.out.println(str2);
        System.out.println(str3);
        return "yml";
    }
}

以上程序的执⾏结果如下图所⽰:

在这里插入图片描述

从上述结果可以看出:

  • 字符串默认不⽤加上单引号或者双引号
  • 单引号会转义特殊字符,使其失去特殊功能, 始终是⼀个普通的字符串
  • 双引号不会转义字符串⾥⾯的特殊字符, 特殊字符会表⽰本⾝的含义

此处的转义理解起来会有些拗⼝, \n 本意表⽰的是换⾏

使⽤单引号会转义, 就是说, \n 不再表⽰换⾏了, ⽽是表⽰⼀个普通的字符串

使⽤双引号不会转义, 表⽰ \n 表⽰的是它本⾝的含义, 就是换⾏

配置对象
  1. 配置
  2. 配置内容读取
  3. 注入

我们还可以在 yml 中配置对象,如下配置:

  1. 配置
Student:
  id: 18
  name: zhangsan
  age: 12

或者是使⽤⾏内写法(与上⾯的写法作⽤⼀致):但可读性差

Student: {id: 18,name: zhangsan,age: 12}

这个时候就不能⽤ @Value 来读取配置中的对象了,此时要使⽤另⼀个注解@ConfigurationProperties 来读取,具体实现如下:

  1. 配置内容读取
@Component
@ConfigurationProperties(prefix = "student")
@Data
public class Student {
    private Integer id;
    private String name;
    private Integer age;
}

调⽤类的实现如下:

  1. 注入
	@Autowired
    public Student student;
	@PostConstruct
    public void init(){
        System.out.println("student:"+student);
    }

运⾏结果如下:

在这里插入图片描述

配置集合
  1. 配置
  2. 配置内容读取
  3. 注入

配置⽂件也可以配置 list 集合,如下所⽰:

  1. 配置
dbtypes:
  name:
    - mysql
    - sqlserver
    - db2

记得一定要加空格,如果不加,这部分内容就会变成一个整体,统一赋值给对应属性

集合的读取和对象⼀样,也是使⽤ @ConfigurationProperties 来读取的,具体实现如下:

  1. 配置内容读取

注意这里的name要和配置里的name要对应上,dbtypes也要对应上

@Component
@ConfigurationProperties(prefix = "dbtypes")
@Data
public class DBType {
    private List<String> name;
}

访问集合的实现如下:

  1. 注入
	@Autowired
    public DBType dbType;
	@PostConstruct
    public void init(){
        System.out.println("dbtype:"+dbType);
    }

运⾏结果如下:

在这里插入图片描述

配置Map
  1. 配置
  2. 配置内容读取
  3. 注入

配置⽂件也可以配置 map,如下所⽰:

  1. 配置
dbtypes:
  name:
    - mysql
    - sqlserver
    - db2
  map:
    k1: kk1
    k2: kk2
    k3: kk3

Map的读取和对象⼀样,也是使@ConfigurationProperties 来读取的,具体实现如下:

  1. 配置内容读取

注意这里的map要和配置里的map要对应上,dbtypes也要对应上

@Component
@ConfigurationProperties(prefix = "dbtypes")
@Data
public class DBType {
    private List<String> name;

    private HashMap<String,String> map;
}

打印类的实现如下:

  1. 注入
	@Autowired
    public DBType dbType;
	@PostConstruct
    public void init(){
        System.out.println("dbtype:"+dbType);
    }

运⾏结果如下:

在这里插入图片描述

yml优缺点

优点:

  1. 可读性⾼,写法简单, 易于理解
  2. ⽀持更多的数据类型, 可以简单表达对象, 数组, List,Map等数据形态.
  3. ⽀持更多的编程语⾔, 不⽌是Java中可以使⽤, 在Golang, Python, Ruby, JavaScript中也可以使⽤

缺点:

  1. 不适合写复杂的配置⽂件

⽐如properties格式如下

keycloak.realm = demo
keycloak.resource = fm-cache-cloud
keycloak.credentials.secret = d4589683-Oce7-4982-bcd3
keycloak.security[0].authRoles[0]= user
keycloak.security[0].collections[0].name = ssologinurl
keycloak.security[0].collections[0].patterns[0] = /login/*

转换成yml

keycloak:
realm: demo
resource: fm-cache-cloud
credentials:
 secret: d4589683-Oce7-4982-bcd3
security:
    - authRoles:
      - user
      collections:
        - name: ssologinurl
          patterns:
            - /login/*

转换的过程也⽐较花费精⼒, 如果配置更复杂⼀点, 可读性会更差, 代码也会更难写

  1. 对格式有较强的要求(⼀个空格可能会引起⼀场⾎案)

练习

验证码案例

随着安全性的要求越来越⾼, ⽬前项⽬中很多都使⽤了验证码, 验证码的形式也是多种多样, 更复杂的图形验证码和⾏为验证码已经成为了更流⾏的趋势.

在这里插入图片描述

验证码的实现⽅式很多, ⽹上也有⽐较多的插件或者⼯具包可以使⽤, 咱们选择使⽤Google的开源项⽬Kaptcha来实现.

Kaptcha 插件介绍

Kaptcha 是Google的⼀个⾼度可配置的实⽤验证码⽣成⼯具. 代码:http://code.google.com/p/kaptcha/

⽹上有很多⼈甚⾄公司基于Google的kaptcha进⾏了⼆次开发. 我们选择⼀个直接适配SpringBoot的开源项⽬

https://github.com/oopsguy/kaptcha-spring-boot

由于作者的⽂档写的不是很全, 下⾯简单介绍下插件的使⽤

  1. 原理

验证码可以客⼾端⽣成, 也可以服务器⽣成. 对于普通的字符验证码, 后端通常分两部分.

⼀是⽣成验证码内容, 根据验证码内容和⼲扰项等, ⽣成图⽚, 返回给客⼾端

⼆是把验证码内容存储起来, 校验时取出来进⾏对⽐.

kaptcha插件选择把验证码存储在Session

  1. 引⼊依赖
<dependency>
	<groupId>com.oopsguy.kaptcha</groupId>
	<artifactId>kaptcha-spring-boot-starter</artifactId>
	<version>1.0.0-beta-2</version>
</dependency>
  1. ⽣成验证码

插件提供了两种⽅式⽣成验证码

  • 通过代码来⽣成(参考⽂档: https://github.com/oopsguy/kaptcha-springboot/blob/master/README_zh-CN.md, 不再介绍)

  • 仅通过配置⽂件来⽣成验证码(推荐)

Kaptcha详细配置

配置项配置说明默认值
kaptcha.border图⽚边框,合法值:yes , noyes
kaptcha.border.color边框颜⾊,合法值: r,g,b (and optional alpha) 或者 white,black,blue.black
kaptcha.image.width图⽚宽200
kaptcha.image.height图⽚⾼50
kaptcha.producer.impl图⽚实现类com.google.code.kaptcha.impl.DefaultKaptcha
kaptcha.textproducer.impl⽂本实现类com.google.code.kaptcha.text.impl.DefaultTextCreator
kaptcha.textproducer.char.string⽂本集合,验证码值从此集合中获取abcde2345678gfynmnpwx
kaptcha.textproducer.char.length验证码⻓度5
kaptcha.textproducer.font.names字体Arial, Courier
kaptcha.textproducer.font.size字体大小40px.
kaptcha.textproducer.font.color字体颜⾊,合法值: r,g,b 或者white,black,blue.black
kaptcha.textproducer.char.space⽂字间隔2
kaptcha.noise.impl干扰实现类com.google.code.kaptcha.impl.DefaultNoise
kaptcha.noise.color⼲扰 颜⾊,合法值: r,g,b 或者white,black,blue.black
kaptcha.obscurificator.impl图⽚样式:⽔纹com.google.code.kaptcha.impl.WaterRipoke⻥眼com.google.code.kaptcha.impl.FishEyeGimpy阴影com.google.code.kaptcha.impl.ShadowGimpycom.google.code.kaptcha.impl.WaterRipple
kaptcha.background.impl背景实现类com.google.code.kaptcha.impl.DefaultBackground
kaptcha.background.clear.from背景颜⾊渐变,开始颜⾊light grey
kaptcha.background.clear.to背景颜⾊渐变, 结束颜⾊white
kaptcha.word.impl⽂字渲染器com.google.code.kaptcha.text.impl.DefaultWordRenderer
kaptcha.session.keysession keyKAPTCHA_SESSION_KEY
kaptcha.session.datesession dateKAPTCHA_SESSION_DATE

⽂档没有介绍, 感兴趣的同学翻看源码:

com.oopsguy.kaptcha.autoconfigure.KaptchaProperties

也可以使⽤ kaptcha.items 配置多个验证码⽣成器

kaptcha.items 是⼀个Map, key为验证码⽣成器名称, value为验证码⽣成器的配置

kaptcha:
  items:
    # home captcha
    home:
      path: /home/captcha
      session:
        key: HOME_KAPTCHA_SESSION_KEY
        date: HOME_KAPTCHA_SESSION_DATE
    # admin captcha
    admin:
      path: /admin/captcha
      session:
        key: ADMIN_KAPTCHA_SESSION_KEY
        date: ADMIN_KAPTCHA_SESSION_DATE

配置说明:

在这里插入图片描述

配置后, 可以直接访问 http://XXXX:port/home/captcha 即可⽣成验证码

需求

界⾯如下图所⽰

  1. ⻚⾯⽣成验证码
  2. 输⼊验证码, 点击提交, 验证⽤⼾输⼊验证码是否正确, 正确则进⾏⻚⾯跳转

在这里插入图片描述

准备工作

创建项⽬, 引⼊SpringMVC的依赖包, 把前端⻚⾯放在项⽬中

在这里插入图片描述

约定前后端交互接口

需求分析

后端需要提供两个服务

  1. ⽣成验证码, 并返回验证码
  2. 校验验证码是否正确: 校验验证码是否正确.

接⼝定义

  1. ⽣成验证码

请求:

GET /admin/captcha

响应: 图⽚内容

在这里插入图片描述

浏览器给服务器发送⼀个 GET /admin/captcha 这样的请求, 服务器返回⼀个图⽚, 浏览器显⽰在⻚⾯上

  1. 校验验证码是否正确

请求: /admin/check

POST /admin/check

captcha=xn8d

captcha : ⽤⼾输⼊的验证码

响应:

true

根据⽤⼾输⼊的验证码, 校验验证码是否正确. true: 验证成功. false: 验证失败.

实现服务器代码
  1. 引⼊依赖
<dependency>
	<groupId>com.oopsguy.kaptcha</groupId>
	<artifactId>kaptcha-spring-boot-starter</artifactId>
	<version>1.0.0-beta-2</version>
</dependency>
  1. 通过配置创建验证码⽣成器
kaptcha:
  image:
    width: 220
    height: 160
  textproducer:
    font:
      size: 40
  items:
    # home captcha
    admin:
      path: /admin/captcha
      session:
        key: HOME_KAPTCHA_SESSION_KEY
        date: HOME_KAPTCHA_SESSION_DATE

启动项⽬, 访问 http://127.0.0.1:8080/admin/captcha , 显⽰验证码

  1. 验证码校验
@RequestMapping("/admin")
@RestController
public class CaptchaController {
    //这个是从配置文件复制的
    //企业标准:
    //常量定义:key:全部大写,单词之间用下划线分隔 value:通常是小写,以下划线分隔,但这里特殊
    private static final String KAPTCHA_SESSION_KEY = "HOME_KAPTCHA_SESSION_KEY";
    private static final String KAPTCHA_SESSION_DATE = "HOME_KAPTCHA_SESSION_DATE";
    //验证码的有效时间,这里是以毫秒为单位,上限是60s
    private static final Long SESSION_TIMEOUT = 60 * 1000L;
    //验证成功:true
    //验证失败:false

    /**
     * 1.从session中获取到生成的验证码
     * 2.比对前端传递的验证码和session中存储的是否一致
     *
     * @param captcha
     * @param session
     * @return
     */
    @RequestMapping("/check")
    public Boolean check(String captcha, HttpSession session) {
        if (!StringUtils.hasLength(captcha)) {
            return false;
        }
        //从session中获取验证码
        String saveCaptcha = (String) session.getAttribute(KAPTCHA_SESSION_KEY);
        Date saveData = (Date) session.getAttribute(KAPTCHA_SESSION_DATE);
        //比对验证码
        if (captcha.equals(saveCaptcha)) {
            //比对日期
            if (saveData == null || System.currentTimeMillis() - saveData.getTime() < SESSION_TIMEOUT) {
                return true;
            }
        }
        return false;
    }
}

⽐对Session中存储的验证码是否和⽤⼾输⼊的⼀致

如果⼀致,并且时间在⼀分钟以为就认为成功

调整前端⻚⾯代码

修改 index.html

  1. 补充ajax代码, 点击提交按钮, 发送请求去服务端进⾏校验
$("#checkCaptcha").click(function () {
      $.ajax({
        type:"get",
        url:"/admin/check",
        data:{
          captcha: $("#inputCaptcha").val()
        },
        success:function(result){
          if(result){
            location.href="success.html";
            //location.assign("success.html");
          }else{
            alert("验证码错误");
          }
        }
      });
});

运⾏测试

通过 URL http://127.0.0.1:8080/index.html 访问服务

在这里插入图片描述

在这里插入图片描述

总结

  1. properties 是以 key=value 的形式配置的键值类型的配置⽂件, yml 使⽤的是树形配置⽅式.

  2. 读取配置⽂件内容, 使⽤ @Value 注解, 注解内使⽤" ${} "的格式读取.

  3. yml 层级之间使⽤换⾏缩进的⽅式配置, key 和 value 之间使⽤": "(英⽂冒号)加空格的⽅式设置, 并且空格不可省略.

  4. properties 为早期并且默认的配置⽂件格式, 其配置存在⼀定的冗余数据, 使⽤ yml 可以很好的解决数据冗余的问题, 但不适合复杂配置.

  5. yml 可以和 properties 共存,但⼀个项⽬中建议使⽤⼀种配置类型⽂件.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2044279.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

clickhouse集群+Zk优化-解决只读模式,主节点磁盘增长快

问题1&#xff1a;数据库进入只读模式 最近在项目中使用clickhouse的时候&#xff0c;遇到了一个批量插入后报错的问题。报错的内容是数据库进入了只读模式&#xff0c;导致数据写不进去。发现有大量的批量写入报错日志信息。&#xff08;关键异常信息&#xff1a;DB::Exceptio…

数据库行转列

一、行转列 1、使用case…when…then 2、使用SUM(IF()) 生成列 3、使用SUM(IF()) 生成列 WITH ROLLUP 生成汇总行 4、使用SUM(IF()) 生成列&#xff0c;直接生成汇总结果&#xff0c;不再利用子查询 5、使用SUM(IF()) 生成列 UNION 生成汇总行,并利用 IFNULL将汇总行标题…

【安卓】Service生命周期与前台活动

文章目录 Service生命周期使用前台Service 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。 点击跳转到网站。 Service生命周期 在项目的任何位置调用了Context的startService()方法&#xff0c;相应的Se…

安卓好软-----开源的跳开屏广告工具 无需root 权限

GKD 开源项目。 目前最新版本是1.8.0 这款工具是一款免费开源简洁多规则的自动跳过广告的软件。简而言之&#xff0c;基于预设的定时更新订阅规则快照功能&#xff0c;实现识别并自动点击跳过任何开屏广告及点击关闭应用内部任何弹窗广告&#xff0c;如关闭某些APP开屏和内含推…

ITSS服务经理与ITSS服务工程师的岗位职责分析

信息技术服务标准&#xff08;ITSS&#xff09;是一套全面而系统的规范&#xff0c;旨在指导和标准化信息技术服务的提供。 由信息技术服务标准工作组精心制定&#xff0c;这些标准不仅总结了行业的最佳实践&#xff0c;还提升了从事信息技术服务研发与应用的各类组织自主创新…

iOS的App启动详细过程(底层知识)

1.虚拟内存 & ASLR 在早期计算机中数据是直接通过物理地址访问的&#xff0c;这就造成了下面两个问题 1.内存不够用 2.数据安全问题 内存不够 ---> 虚拟内存 虚拟内存就是通过创建一张物理地址和虚拟地址的映射表来管理内存&#xff0c;提高了CPU利用率&#xff0c;…

【Python快速入门和实践012】Python常用脚本-目标检测之查看数据集标签类别及对应数量

一、功能介绍 这段代码的功能是从指定的目录中读取所有的XML文件&#xff0c;并统计这些文件中特定标签&#xff08;<object>标签内的<name>标签&#xff09;的内容和出现次数。 二、代码 import os import xml.etree.ElementTree as ET import globdef count_nu…

SAK-TC277TP-64F200N DC:32位RAM微控制器、常用于消费者应用

描述&#xff1a; SAK-TC277TP-64F200N DC属于第一代Aurix TC27xT产品。其创新多核心架构基于多达三个独立32位TriCore CPU&#xff0c;专为满足极高的安全标准&#xff0c;同时大幅提高性能而设计。TC27xT系列产品配备200 MHz TriCore、5V 或3.3V 单电压供电和强大的通用定时器…

【Linux】中的软件安装:深入探索RPM、SRPM与YUM

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Linux &#xff1a;从菜鸟到飞鸟的逆袭》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、Linux的起源与发展 2、RPM、SRPM与YUM的简要介…

【Redis】数据类型详解及其应用场景

目录 Redis 常⻅数据类型预备知识基本全局命令小结 数据结构和内部编码单线程架构引出单线程模型为什么单线程还能这么快 Redis 常⻅数据类型 Redis 提供了 5 种数据结构&#xff0c;理解每种数据结构的特点对于 Redis 开发运维⾮常重要&#xff0c;同时掌握每种数据结构的常⻅…

【大数据】智慧园区大数据云平台整体建设方案(Word原件)

第一章 项目建设背景及现状 第二章 园区创新发展趋势 第三章 工业园区大数据存在的问题 第四章 智慧工业园区大数据建设目的 第五章 智慧园区总体构架 第六章 系统核心组件 第七章 智慧工业园区大数据平台规划设计 获取方式&#xff1a;本文末个人名片直接获取。 软件资料清单列…

springboot使用aop或Jackson进行数据脱敏

1.aop 启动类加EnableAspectJAutoProxy 自定义注解&#xff0c;在实体类中使用表示被脱敏字段 建立aop切面类 可能这里gpt会建议你用Pointcut("execution(public * com.xx.aop..*.get*(..))")这种方式拦截&#xff0c;这种我试了&#xff0c;拦截不住。猜测在mvc返…

灵办AI免费ChatGPT4人工智能浏览器插件快速便捷(多功能)

灵办AI就是您所需的最佳助手&#xff01;我们为您带来了一款多功能AI工具&#xff0c;不仅能为您提供精准翻译&#xff0c;还能满足您的对话需求、智能续写、AI搜索、文档阅读、代码生成与修正等多种需求。灵办 AI&#xff0c;真正让工作和学习变得轻松高效&#xff01; 推荐使…

Android高版本抓包总结

方案1 CharlesVirtualXposedJustTrustMe 推荐使用三星手机此方案 VirtualXposed下载链接&#xff1a;https://github.com/android-hacker/VirtualXposed/releases JustTrustMe下载链接&#xff1a;https://github.com/Fuzion24/JustTrustMe/releases/ 下载完成后使用adb命令…

我的吃鸡日志 中2 从菜鸟到专家

hey&#xff0c;我又来啦&#xff01; 我的吃鸡日志中1之复仇计划见这个。 &#xff08;游戏入口&#xff1a;和平精英38.0 快乐星空&#xff09; 苦学两年半。。。。。。 hey hey hey&#xff0c;这次我必须赢&#xff01; 打开游戏ing。。。。。。 作战ing。。。。 先在…

43-设计规则:铺铜规则

1、铺铜规则设置 铺铜规则[plane]&#xff1a; PowerPlane Connect Style[负片层连接方式]: PlaneConnect&#xff1a;Direct Connect/ 高级设置->过孔改成完全连接 Power Plane Clearance[负片层间距设置]: PlaneClearance&#xff1a; 8mil Polygon Connect Style[正片层…

电动汽车和混动汽车DC-DC转换器的创新设计与测试方法

汽车 DC-DC 转换器市场规模将达到187亿美元&#xff0c;年复合增长率为10%。 DC-DC 转换器是汽车的重要组成部分&#xff0c;它可以通过电压转换为各种车载系统供电&#xff0c;例如日益复杂的车载信息娱乐系统、使用驾驶辅助系统&#xff08;ADAS&#xff09;实现的增强安全功…

VMware虚拟机H群晖7.2懒人包

目录 0. 准备 1. 下载 2. 解压 3. 导入VMware 4.开机 5.查找设备 6.登录初始化 随着DSM系统的升级,群辉NAS很多组件变哈很大,有的已经放弃不再支持,有的与其它功能合并,甚至新开发的组件仅仅支持DSM7以上。为了体验新的组件,因此有必要再安装依噶DSM7.x以上的群辉,…

领域自适应

领域自适应 迁移学习的核心思想在于&#xff0c;一个任务上训练得到的模型所包含的知识可以部分或全部地转移到另一个任务上。这种知识转移可以是网络参数、特征表示、数据间的关系等。通过迁移学习&#xff0c;我们可以利用已有的知识和经验来加速新任务的学习过程&#xff0…

【项目】多设计模式下的同步异步日志系统(二)

继上文对日志系统的介绍&#xff0c;并且实现了日志等级、日志消息的定义、以及格式化消息等。由这三个模块就能完整的输出一条消息。但是考虑到日志消息不可能全部都通过显示器展示。本项目针对落地方式&#xff0c;也进行多种编写&#xff0c;以供使用。 消息落地类(简单工厂…