SpringBoot | 详解SpringBoot配置文件及其原理

文章目录

  • 一、配置文件
  • 二、YAML语法
    • 1、基本语法
    • 2、值的写法
      • (1)、字面量:普通的值(数字,字符串,布尔)
      • (2)、对象、Map(属性和值)
      • (3)、数组(List、Set)
  • 三、配置文件值注入
    • 1、一个简单的示例
    • 2、@Value获取值和@ConfigurationProperties获取值比较
    • 3、数据校验
    • 4、使用`@PropertySource`加载指定的配置文件
    • 5、使用`@ImportResource`导入Spring的配置文件
    • 6、使用配置类及`@Bean`注解来给容器添加组件
  • 四、配置文件占位符
    • 1、随机数
    • 2、占位符获取之前配置的值
  • 五、Profile
    • 1、多Profile文件
    • 2、yml支持多文档块形式
    • 3、激活指定Profile
      • (1)、在配置文件中指定`spring.profiles.active`属性来激活
      • (2)、使用命令行来激活
      • 3、虚拟机参数
  • 六、配置文件的加载位置
  • 七、外部配置加载顺序
    • (1)、命令行参数
    • (2)、关于jar包外、jar包内的配置文件以及带不带profiles的顺序区别
    • (3)、`@Configuration`注解类上的`@PropertySource`
  • 八、SpringBoot配置的原理
    • 1、Springboot启动的时候加载主配置类时开启自动配置功能
    • 2、`@EnableAutoConfiguration`作用
    • 3、每一个自动配置类进行自动配置
    • 4、我们以`HttpEncodingAutoConfiguration`为例来解释自动配置原理
      • (1)、@Configuration
      • (2)、@EnableConfigurationProperties
      • (3)、@ConditionalOnWebApplication
      • (4)、@ConditionalOnClass
      • (5)、@ConditionalOnProperty
      • (6)、总结
    • 5、结论
  • 九、@Conditional及其自动配置报告


一、配置文件

springboot使用一个全局的配置文件,配置文件名是固定的,一般有两种写法:

  • application.properties
  • application.yml

配置文件的作用:SpringBoot在底层都给我们自动配置了,而配置文件的作用就是修改SpringBoot自动配置的默认值。

之前的配置文件,都是使用的xml文件格式,但是YAML也可以做配置文件,YAML是以数据为中心,比JSON、XML等等更适合做配置文件。
配置示例(将端口号设置为8081)

server:port: 8081

二、YAML语法

1、基本语法

k: v:表示一对键值对(空格必须有)。以空格的缩进来控制层级关系,只要是左对齐的一列数据,都是同一个层级的。并且其属性和值都是大小写敏感的。

示例:

server:port: 8081path: /hello

2、值的写法

(1)、字面量:普通的值(数字,字符串,布尔)

使用k: v:
对于字符串,默认不用加上单引号或者双引号,""双引号不会转义字符串里面的特殊字符,特殊字符会作为本身想表示的意思;''单引号就会转义字符,特殊字符最终只是一个普通的字符串数据。

(2)、对象、Map(属性和值)

还是使用k:v:方式,在下一行来写对象的属性和值的关系,注意缩进,例如:

friend:lastName: zhangsanage: 20

这样表示lastName和age是friend对象的属性。
也可以写成行内写法:friend: {lastName: zhangsan,age: 18}

(3)、数组(List、Set)

-表示数组中的一个元素

pets:- cat,- dog,- pig

也可以写成:pets: [cat,dog,pig]


三、配置文件值注入

在JavaBean类中加入@ConfigurationProperties注解将配置文件中配置的每一个属性的值映射到这个组件中,并且要将这个类加入到IOC容器中。要注意的是@ConfigurationProperties默认是从全局配置文件中获取值的。

1、一个简单的示例

yml文件:

person:lastName: zhangsanage: 18boss: falsebirth: 2019/12/12map: {k1: 1,k2: 2}list:- lisi- zhaoliudog:name: 小狗age: 2

JavaBean(省略getter、setter、toString方法):

package com.cerr.springboot.bean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
/*** 将配置文件中配置的每一个属性的值映射到这个组件中* @ConfigurationProperties告诉Springboot将本类中的所有属性和配置文件中相关的配置进行绑定*      prefix:配置文件中哪个下面的所有属性进行配置**  只有这个组件是容器中的组件,才能使用容器提供的ConfigurationProperties功能*/
@Component
@ConfigurationProperties(prefix = "person")
public class Person {private String lastName;private Integer age;private Boolean boss;private Date birth;private Map<String,Object> map;private List<Object> list;private Dog dog;
}

我们可以导入配置文件处理器,以后编写配置就有提示:

        <!-- 导入配置文件处理器,配置文件进行绑定就会有提示 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency>

刚刚在yml中的配置也可以在properties中配置:

person.last-name=张三
person.age=14
person.birth=2019/12/2
person.boss=false
person.map.k1=11
person.map.k2=22
person.list=a,b,c
person.dog.name=dog
person.dog.age=15

2、@Value获取值和@ConfigurationProperties获取值比较

对于yml或者properties配置文件,这两个注解都可以获取到配置文件的值,但是它们有以下的区别:

@ConfigurationProperties@Value
功能批量注入配置文件中的属性必须一个一个属性的指定
松散语法(松散绑定)支持不支持
SpEL不支持支持
JSR303数据校验支持不支持
复杂类型封装支持不支持

如果我们只是在某个业务逻辑中需要获取一下配置文件的某个值时,我们使用@Value比较方便;如果我们专门编写了一个JavaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties

3、数据校验

在类上标注@Validated注解,并在你需要校验的字段标注上对应的注解即可,假设我们在lastName字段要使用@Eamil校验,则代码如下:

@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {@Emailprivate String lastName;private Integer age;private Boolean boss;private Date birth;private Map<String,Object> map;private List<Object> list;private Dog dog;
}

4、使用@PropertySource加载指定的配置文件

@PropertySource这个注解可以加载指定的配置文件。
我们定义一个局部的配置文件,文件的位置位于类路径下,如图所示:

13424350-28eec232afc4ad1a.png

使用@PropertySource(value = {"classpath:person.properties"})将该配置文件加载进来:

@PropertySource(value = {"classpath:person.properties"})
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {private String lastName;private Integer age;private Boolean boss;private Date birth;private Map<String,Object> map;private List<Object> list;private Dog dog;
}

5、使用@ImportResource导入Spring的配置文件

@ImportResource的作用是导入Spring的配置文件,让配置文件里面的内容生效。

我们编写了一个spring的配置文件,位于类路径下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"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.xsd"><bean class="com.cerr.springboot.service.HelloService" id="helloService"></bean>
</beans>

然后我们在Spring的单元测试中测试ioc容器中是否有helloService这个bean:

@SpringBootTest
class Springboot01DemoApplicationTests {@AutowiredApplicationContext ioc;@Testpublic void testHelloService(){boolean b = ioc.containsBean("helloService");System.out.println(b);}
}

结果却是没有这个bean,因为此时这个配置文件并没有被加载,因此我们需要使用@ImportResource注解让该文件加载进来,在主配置类中我们使用该注解:

//导入Spring的配置文件并让其生效
@ImportResource(locations = {"classpath:bean.xml"})
@SpringBootApplication
public class Springboot01DemoApplication {public static void main(String[] args) {SpringApplication.run(Springboot01DemoApplication.class, args);}
}

然后我们再一次在Spring的单元测试中测试,现在结果是有包含这个bean。

但是我们不推荐这种形式来给容器添加组件,Spring比较推荐使用以下这种方式:

6、使用配置类及@Bean注解来给容器添加组件

Spring比较推荐使用配置类来给容器添加组件,首先我们先定义一个配置类:

package com.cerr.springboot.config;
import com.cerr.springboot.service.HelloService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/*** 指明当前类是一个配置类,用来替代之前的Spring配置文件*/
@Configuration
public class AppConfig {//将方法的返回值添加到容器中,容器中这个组件默认的id就是方法名@Beanpublic HelloService helloService(){System.out.println("给容器中添加组件了");return new HelloService();}
}

该配置类使用了@Configuration注解,表示其是一个配置类,然后在方法中使用了@Bean注解,该注解的作用是将方法的返回值添加到ioc容器中,并且这个组件的id就是方法名
我们还是使用刚刚的那个测试类来测试ioc容器中是否包含了这个bean:

13424350-da711113e3225f2d.png


四、配置文件占位符

1、随机数

例如在配置文件中给lastNameage字段加上随机数:

person.last-name=张三${random.uuid}
person.age=${random.int}

2、占位符获取之前配置的值

person.last-name=张三${random.uuid}
person.dog.name=${person.last-name:hello}_dog

person.dog.name的值就是person.last-name的值拼上_dog,然后后面的:hello的意思是,如果我们没有在配置文件中指定person.last-name的值,那么那个占位符的默认值就是hello。


五、Profile

1、多Profile文件

我们在编写主配置文件的时候,文件名可以是application-{profile}.properties/yml,默认使用application.properties文件的配置。

我们新建了application-dev.properties,application-prod.properties文件,分别指定其port为8083和80,然后在application.properties文件中:

server.port=8080
spring.profiles.active=dev

第一句表示默认的环境配置(没指定是哪种环境时)为端口号是8080,第二句表示指定dev环境,即使用我们配置的application-dev.properties文件。

2、yml支持多文档块形式

yml中使用---可以将文件分为多文档,在不同的文档中定义即可:

server:port: 8081path: /hello
spring:profiles:active: dev
---
server:port: 8083
spring:profiles: dev---
server:port: 80
spring:profiles: prod

上述代码中,在文档2中我们定义了dev环境下的配置,文档3中定义了prod环境下的配置,然后在文档1中我们先定义了默认的配置,并且使用了如下格式来配置环境:

spring:profiles:active: dev

因此当前使用的环境是dev环境,所以此时的端口号应该是8083,我们启动主启动类:

13424350-057b940cfa6a2ff0.png

3、激活指定Profile

(1)、在配置文件中指定spring.profiles.active属性来激活

  • 对于properties文件,我们可以这样激活:
spring.profiles.active=dev

(2)、使用命令行来激活

在终端中使用--spring.profiles.active=xxx来激活,比如我们在配置yml配置文件中指定激活dev环境:

server:port: 8081path: /hello
spring:profiles:active: dev

但是我们在idea中加上命令行参数--spring.profiles.active=prod表示我们想激活prod环境:

13424350-6215b8daf577035b.png

13424350-fd1141e74f35c382.png

最后启动之后发现使用的是prod的环境配置:

13424350-cf874b11cd3e598a.png

或者是将项目打包为jar包后,在终端中运行该jar包且指定命令行参数也行:

命令行输入:
java -jar springboot-01-demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod

13424350-8be5d74984eb9448.png

13424350-5505037aa344d238.png

3、虚拟机参数

在IDEA中设置虚拟机参数:-Dspring.profiles.active=prod

13424350-6c249d36646cf3f8.png

然后启动:

13424350-ac79640b1d42527f.png


六、配置文件的加载位置

Springboot启动会扫描以下位置的application.properties或者application.yml文件作为Springboot的默认配置文件:

  • file:../config/:根目录下的config文件夹下
  • file:../:根目录下
  • classpath:/config/:类路径下的config文件夹下
  • classpath:/:类路径下

以上是按照优先级从高到低的顺序,所有位置的文件都会被加载,高优先级配置内容会覆盖低优先级配置内容,称为互补配置

例如我们在根目录下新建一个config文件夹,并且新建一个application.properties文件,配置port为8082:

server.port=8082

在类路径下的application.properties文件中配置如下:

server.port=8081#配置项目的访问路径
server.servlet.context-path=/boot1

因为配置文件遵循高优先级配置内容覆盖低优先级配置内容,所以这类路径下文件的port配置会被第一个文件覆盖,而第一个文件都没配置server.servlet.context-path,所以这个属性的值还是第二个配置文件的值,我们访问后:

13424350-af7371eac07c0e63.png

我们可以通过配置spring.config.location来改变默认配置
在项目打包好后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件得新位置。

我们在E盘中新建一个application.properties文件,然后设置port为80:

server.port=80

我们将项目打包后,在IDEA的控制台中运行该jar包:

13424350-b7d4658a12ea1590.png

默认端口为80,因此localhost会省略80:

13424350-3dbd88c04c336601.png


七、外部配置加载顺序

Springboot可以从以下位置加载配置,优先级从高到低,高优先级的配置覆盖低优先级的配置:

(1)、命令行参数

语法:--配置项=值,多个参数使用空格分隔

打包后并在命令行输入:
java -jar springboot-01-demo-0.0.1-SNAPSHOT.jar --server.port=8087
运行jar包并且修改server.port=8087

启动后访问8087端口能正常运行,访问原来的8082端口不能用:

13424350-bd988c38b39ac9ff.png

(2)、关于jar包外、jar包内的配置文件以及带不带profiles的顺序区别

由jar包外向jar包内进行寻找,优先加载带profiles,再来加载不带profiles

此时我们项目内配置文件最高优先级的应该是端口为8082,我们将项目打包,然后新建一个boot文件夹,将打包好的jar包放入文件夹中:

13424350-7ed8ee665bf83a70.png

然后我们在该文件夹下新建一个application.properties文件(在jar包外),里面的配置如下:

server.port=8089
在命令行中输入:
java -jar springboot-01-demo-0.0.1-SNAPSHOT.jar

13424350-d7a12a97dc43431d.png

此时的端口号为8089,因此证明了我们定义在jar包外的这个配置文件是最高优先级的,我们访问:

13424350-bb1d5f031e953d49.png

因为访问的路径中有/boot2,因此说明我们jar包内定义的配置文件也有起作用,只是有一部分被jar包外的覆盖而已。

(3)、@Configuration注解类上的@PropertySource


八、SpringBoot配置的原理

1、Springboot启动的时候加载主配置类时开启自动配置功能

主配置类中有@EnableAutoConfiguration注解,我们下面来研究其作用:

2、@EnableAutoConfiguration作用

利用AutoConfigurationImportSelector给容器中导入一些组件。可以查看selectImports()的内容:

    public String[] selectImports(AnnotationMetadata annotationMetadata) {if (!this.isEnabled(annotationMetadata)) {return NO_IMPORTS;} else {AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());}}protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {if (!this.isEnabled(annotationMetadata)) {return EMPTY_ENTRY;} else {AnnotationAttributes attributes = this.getAttributes(annotationMetadata);List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);configurations = this.removeDuplicates(configurations);Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);this.checkExcludedClasses(configurations, exclusions);configurations.removeAll(exclusions);configurations = this.filter(configurations, autoConfigurationMetadata);this.fireAutoConfigurationImportEvents(configurations, exclusions);return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);}}

selectImports方法中调用了getAutoConfigurationEntry(),其方法中的一句代码List configurations = this.getCandidateConfigurations(annotationMetadata, attributes);是获取候选的配置,我们进入该方法:

    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");return configurations;}

该方法扫描所有jar包类路径下META-INF/spring.factories文件,并把扫描到的这些文件的内容包装成properties对象。从properties中获取到EnableAutoConfiguration.class类名对应的值,然后把他们添加到容器中。

总结来说其作用就是将类路径下META-INF/spring.factories里面配置的所有EnableAutoConfiguration的值加入到容器中
每一个xxxAutoConfiguration类都是容器中的一个组件,都加入到容器中,用他们来做自动配置。

3、每一个自动配置类进行自动配置

4、我们以HttpEncodingAutoConfiguration为例来解释自动配置原理

首先这个类上有如下的注解:

@Configuration(proxyBeanMethods = false
)
@EnableConfigurationProperties({HttpProperties.class})
@ConditionalOnWebApplication(type = Type.SERVLET
)
@ConditionalOnClass({CharacterEncodingFilter.class})
@ConditionalOnProperty(prefix = "spring.http.encoding",value = {"enabled"},matchIfMissing = true
)

我们来逐一分析这些注解:

(1)、@Configuration

表示这是一个配置类。和以前编写的配置文件一样,也可以给容器添加组件

(2)、@EnableConfigurationProperties

这个注解表示启动指定类的ConfigurationProperties功能,我们点进去HttpProperties类,有如下注解:

@ConfigurationProperties(prefix = "spring.http"
)
public class HttpProperties{
}

@ConfigurationProperties注解的作用是从配置文件中获取指定的值和bean的属性来进行绑定。

因此所有在配置文件中能配置的属性都是在xxxProperties类中封装着,如果我们想要知道该配置文件能够配置什么功能,我们就可以参考某个功能对应的Properties类

对于这个例子,我们这个注解最后就是让配置文件中对应的值和HttpProperties绑定起来了,并加入到ioc容器中,为后面我们要向容器中添加组件服务。

(3)、@ConditionalOnWebApplication

在Spring底层中有一个@Conditional注解,判断如果满足指定的条件,整个配置类里面的配置会生效。
因此这个@ConditionalOnWebApplication就是判断当前应用是否是web应用,如果是,则当前配置类生效。

(4)、@ConditionalOnClass

判断当前项目有没有这个类。
@ConditionalOnClass({CharacterEncodingFilter.class})表示判断当前项目中有没有CharacterEncodingFilter这个类,这个类是SpringMVC中进行乱码解决的过滤器。

(5)、@ConditionalOnProperty

判断配置文件中是否存在某个配置,在这个例子中:

@ConditionalOnProperty(prefix = "spring.http.encoding",value = {"enabled"},matchIfMissing = true
)

表示判断配置文件夹是否有spring.http.encoding.enabled这个配置,而matchIfMissing = true表示如果不存在这个配置,这个配置也是默认生效的。

(6)、总结

因此AutoConfiguration配置类的作用就是不断的判断,最终决定这个配置类是否生效,如果生效的话,则给容器添加各种组件,这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的

HttpEncodingAutoConfiguration类中的一部分源码如下:

public class HttpEncodingAutoConfiguration {//通过@EnableConfigurationProperties注解,和SpringBoot的配置文件进行了映射private final Encoding properties;//只有一个有参构造器的情况下,参数的值就会从容器中拿public HttpEncodingAutoConfiguration(HttpProperties properties) {this.properties = properties.getEncoding();}@Bean@ConditionalOnMissingBeanpublic CharacterEncodingFilter characterEncodingFilter() {CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();filter.setEncoding(this.properties.getCharset().name());filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.REQUEST));filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.RESPONSE));return filter;}
}

5、结论

  • SpringBoot启动会加载大量的自动配置类。
  • 我们看我们需要的功能有没有SpringBoot默认写好的自动配置类
  • 我们再来看这个自动配置类中配置了哪些组件(如果我们要用的组件有,那我们就不需要再来配置)
  • 给容器中自动配置类添加属性的时候,会从properties类中获取某些属性,我们就可以在配置文件中指定这些属性的值
  • 本质上SpringBoot的各种Properties类就封装了配置文件中的相关属性,然后各种AutoConfiguration自动配置类就会给容器添加各种组件。

九、@Conditional及其自动配置报告

@Conditional作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效;

@Conditional扩展注解作用(判断是否满足当前指定条件)
@ConditionalOnJava系统的java版本是否符合要求
@ConditionalOnBean容器中存在指定Bean;
@ConditionalOnMissingBean容器中不存在指定Bean;
@ConditionalOnExpression满足SpEL表达式指定
@ConditionalOnClass系统中有指定的类
@ConditionalOnMissingClass系统中没有指定的类
@ConditionalOnSingleCandidate容器中只有一个指定的Bean,或者这个Bean是首选Bean
@ConditionalOnProperty系统中指定的属性是否有指定的值
@ConditionalOnResource类路径下是否存在指定资源文件
@ConditionalOnWebApplication当前是web环境
@ConditionalOnNotWebApplication当前不是web环境
@ConditionalOnJndiJNDI存在指定项

自动配置类必须在一定的条件下才能生效;
我们可以通过设置debug=true属性,来让控制台打印自动配置报告,我们通过配置报告就知道哪些自动配置生效。

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

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

相关文章

【深入理解JVM】:Java内存模型JMM

多任务和高并发的内存交互 多任务和高并发是衡量一台计算机处理器的能力重要指标之一。一般衡量一个服务器性能的高低好坏&#xff0c;使用每秒事务处理数&#xff08;Transactions Per Second&#xff0c;TPS&#xff09;这个指标比较能说明问题&#xff0c;它代表着一秒内服…

You may use special comments to disable some warnings.Use // eslint-disable-next-line to ignore...

vue没写什么爆红 错误原因 ESLint] 对语法的要求过于严格导致编译的时候报上图那些错误。 要知道&#xff0c;这并不是代码有异常&#xff0c;而是代码格式有问题&#xff0c;这些错误并不会影响代码的执行结果。 解决方法 很简单&#xff0c;既然是ESLint 语法错误&#xff…

java jni 原理_JNI的实现原理

JNI接口函数和指针Java虚拟机访问本机代码通过调用JNI的功能特性。JNI的功能都可以通过一个接口指针。一个接口指针是一个指向指针的指针。这个指针指向一个一个指针数组&#xff0c;这个数组中的每一个成员指向一个函数入口。每个接口的功能是在一个预定义的内部数组的偏移量。…

jQuery ajax读取本地json文件_jQuery请求本地JSON文件,在谷歌浏览器运行时报跨域错误_Vscode使用Live Server

json文件 {"first":[{"name":"张三","sex":"男"},{"name":"李四","sex":"男"},{"name":"王武","sex":"男"},{"name":"李…

Vue打包并发布项目

一、 打包vue项目步骤&#xff1a; 1、对当前vue项目进行打包的命令如下&#xff1a; npm run build2、打包完成&#xff0c;会输出Build complete并且在vue项目中会生成一个名字为dist的打包文件。如下图&#xff1a; 二、 使用静态服务器工具包发布打包的vue项目 1、首先…

Grammarly:最优秀的日常英文写作辅助工具——论文英文校验

使用Grammarly也有一些心得&#xff0c;在此分享给大家。 1&#xff0c;Grammarly是什么&#xff1f; Grammarly是一款在线语法纠正和校对工具&#xff0c;支持Windows、Mac、iOS和Android等多个平台。它能够检查单词拼写、纠正标点符号、修正语法错误、调整语气以及给出风格…

SpringMVC @RequestBody和@ResponseBody原理解析

SpringMVC RequestBody和ResponseBody原理解析 前言 RequestBody作用是将http请求解析为对应的对象。例如&#xff1a; http请求的参数&#xff08;application/json格式&#xff09;&#xff1a; {"accountId": 10,"adGroupId": "12345678",…

java 高性能缓存_高性能Java缓存----Caffeine

简单介绍Caffeine是新出现的一个高性能的Java缓存&#xff0c;有了它完全可以代替Guava Cache&#xff0c;来实现更加高效的缓存&#xff1b;Caffeine采用了W-TinyLFU回收策略&#xff0c;集合了LRU和LFU的优点&#xff0c;提供了一个最佳的命中率&#xff0c;在效率上可以秒杀…

@ResponseBody 转化成json后与实体类字段名不一致_SpringMVC字符串解析成json对象(@RequestBody注解和@ResponseBody注解)

ResponseBody 转化成json后与实体类字段名不一致 实体类A字段名由B改成C后&#xff0c;Controller 中返回的List中字段名仍然是C 经过ResponseBody返回到前台后又变成了B 后来发现公司项目采用的是阿里的fastjson&#xff0c; 是开源的Json格式化工具库 此工具库是根据实体类…

java togglebutton_ToggleButton和Switch使用大全

本文转载自&#xff1a;Android零基础入门第21节&#xff1a;ToggleButton和Switch使用大全http://www.apkbus.com/blog-205190-68463.html(出处: 安卓巴士 - 安卓开发 - Android开发 - 安卓 - 移动互联网门户)&#xff0c;转载应备注出处&#xff0c;尊重原创上期学习了CheckB…

MyBatis之工作原理,简单实体的增加、修改、删除、查询_Mybatis-原理总结

一、MyBatis之工作原理 MyBatis是一个半自动映射框架。所谓半自动&#xff0c;是相对Hibernate全表映射而言的&#xff0c;MyBatis需要手动匹配提供POJO、SQL和映射关系。 我们知道&#xff0c;JDBC有四个核心对象&#xff1a; &#xff08;1&#xff09;DriverManager&#…

MySQL优化:如何避免回表查询?_什么是索引覆盖?

数据库表结构&#xff1a; create table user (id int primary key,name varchar(20),sex varchar(5),index(name) )engineinnodb;select id,name where nameshenjianselect id,name,sex where nameshenjian多查询了一个属性&#xff0c;为何检索过程完全不同&#xff1f; 什…

mysql提示Column count doesn‘t match value count at row 1错误

我们在对数据库进行添加信息时可能会遇到如下错误&#xff1a; Column count doesn’t match value count at row 1 该错误的意思是传入表的字段数和values值的个数不一样 我总结了一下&#xff0c;主要有3个易错点&#xff1a; 1.要传入表中的字段数和values后面的值的个数不…

java 阅发布模式_redis发布订阅模式

一 前言虽然有消息队列&#xff0c;我们还是要了解一下redis发布订阅模式哟&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;二发布订阅模式PUBLISH 命令向通道发送信息&#xff0c;此客户端称为publisher 发布者&#xff1b;SUBSCRIBE 向命令通道订阅信息&#…

把实体 转为json 数据格式---jackson 的详细用法_Jackson快速入门

首先介绍三个注解&#xff1a; JsonAutoDetect (method/field):作用于方法或字段&#xff0c;用来表明&#xff0c;当生成json的时候忽略有该annotation的方法或字段 JsonIgnore 过滤不需要转成json的属性 JsonIgnoreProperties 主要用于过滤掉一些不需要的属性 以上三个注…

java 类的加载顺序_Java 中类的加载顺序

这其实是去年校招时我遇到的一道阿里巴巴的笔试题(承认有点久远了-。-)&#xff0c;嗯&#xff0c;如果我没记错的话&#xff0c;当时是作为Java方向的一道选做大题。当然题意没有这么直白&#xff0c;题目只要求你写出程序运行后所有System.out.println的输出结果&#xff0c;…

Jackson转换json大写_关于jackson转化json的原理_jackson序列化和反序列化Json

背景 web工程中&#xff0c;数据交互是不可避免的&#xff0c;相比xml&#xff0c;json是现在流行的数据交互。 在调试接口中&#xff0c;发现返回字段的大小写不是我所期望的&#xff0c;原本应该返回的nNum字段变成了nnum&#xff0c;这样就导致和前端约定的有出入了。 ja…

svn利用TortoiseSVN忽略文件或文件夹(目录)

忽略已经版本控制的文件 如果你不小心添加了一些应该被忽略的文件&#xff0c;你如何将它们从版本控制中去除而不会丢失它们&#xff1f;或许你有自己的IDE配置文件&#xff0c;不是项目的一部分&#xff0c;但将会花费很多时间使之按照自己的方式工作。 如果你还没有提交&am…

SpringMVC 参数绑定详解

概述 记得之前跟前端同事联调接口的时候&#xff0c;后端SpringMVC需要接收数组类型的参数&#xff0c;然后跟前端说需要传数组类型过来。后来前端童鞋传了数组&#xff0c;但是后端接收不成功&#xff0c;联调失败。那时候由于时间关系没有仔细研究这块&#xff0c;当时想了个…

java 连接远程服务器_java实现连接远程服务器并执行命令的基本原理

一、所需jar包需要借助Ganymed SSH的jar包: ganymed-ssh2-build210.jar二、实现原理Ganymed SSH-2 java在整个访问过程中担当SSH的客户端&#xff0c;由于Linux系统自带SSH服务&#xff0c;所以可以直接访问Linux系统并执行相关命令&#xff0c;而 Windows系统则需要首先安装S…