SpringBoot个人梳理

SpringBoot个人梳理

@Bean //给容器中添加一个组件,这个组件的某些值需要从properties中获取

​ 只有一个有参数的构造器,值要到容器中拿

Springboot自动配置原理

@SpringBootApplication

重点关注底下标在@SpringBootApplication里的两个配置

@SpringBootConfiguration
@EnableAutoConfiguration

@SpringBootConfiguration 标注在某个类上,表示这是一个Spring Boot的配置类;

内部:@Configuration:配置类上来标注这个注解;

@EnableAutoConfiguration:开启自动配置功能;@EnableAutoConfiguration告诉SpringBoot开启自动配置功能;这样自动配置才能生效

@EnableAutoConfiguration中重点关注这两个注解

@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)

@AutoConfigurationPackage:自动配置包

@AutoConfigurationPackage内部标有:@Import(AutoConfigurationPackages.Registrar.class)

Spring的底层注解@Import,给容器中导入一个组件;导入的组件由AutoConfigurationPackages.Registrar.class;

将主配置类(@SpringBootApplication标注的类)的所在包及下面所有子包里面的所有组件扫描到Spring容器;

@Import(EnableAutoConfigurationImportSelector.class);

EnableAutoConfigurationImportSelector:导入哪些组件的选择器;

EnableAutoConfigurationImportSelector.class 类中拥有方法:

protected boolean isEnabled(AnnotationMetadata metadata)

会给容器中导入非常多的自动配置类(xxxAutoConfiguration);就是给容器中导入这个场景需要的所有组件,并配置好这些组件;

问题来了,这些自动配置类从何而来:

有据可查:如下

关注EnableAutoConfigurationImportSelector的父类

AutoConfigurationImportSelector

关注其中的一个方法selectImports

public String[] selectImports(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return NO_IMPORTS;}try {AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);AnnotationAttributes attributes = getAttributes(annotationMetadata);List<String> configurations = getCandidateConfigurations(annotationMetadata,attributes);configurations = removeDuplicates(configurations);configurations = sort(configurations, autoConfigurationMetadata);Set<String> exclusions = getExclusions(annotationMetadata, attributes);checkExcludedClasses(configurations, exclusions);configurations.removeAll(exclusions);configurations = filter(configurations, autoConfigurationMetadata);fireAutoConfigurationImportEvents(configurations, exclusions);return configurations.toArray(new String[configurations.size()]);}catch (IOException ex) {throw new IllegalStateException(ex);}
}

该方法重点关注

List<String> configurations = getCandidateConfigurations(annotationMetadata,attributes);

返回List 配置类

该语句重点关注 getCandidateConfigurations的方法内容

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,AnnotationAttributes attributes) {List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), 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;
}

关注getCandidateConfigurations方法中的SpringFactoriesLoader.loadFactoryNames方法

传入了两个参数

List configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());

其中:

第一个参数:getSpringFactoriesLoaderFactoryClass() 返回的是:

protected Class getSpringFactoriesLoaderFactoryClass() {return EnableAutoConfiguration.class;}

第二个参数:getBeanClassLoader() 类加载机制

protected ClassLoader getBeanClassLoader() {return this.beanClassLoader;}

SpringFactoriesLoader.loadFactoryNames()具体实现:

public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {String factoryClassName = factoryClass.getName();try {Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));List<String> result = new ArrayList<String>();while (urls.hasMoreElements()) {URL url = urls.nextElement();Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));String factoryClassNames = properties.getProperty(factoryClassName);result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));}return result;}catch (IOException ex) {throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +"] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);}}

其中:

用类加载器获取一个资源:

classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));

获取完资源以后:它会把这个资源当成一个Properties

Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));

再从:Properties中拿出factoryClassNames

String factoryClassNames = properties.getProperty(factoryClassName);

工厂的名字

分析FACTORIES_RESOURCE_LOCATION

public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

总结:

Spring Boot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到容器中,自动配置类就生效,帮我们进行自动配置工作;

以前我们需要自己配置的东西,自动配置类都帮我们;J2EE的整体整合解决方案和自动配置都在spring-boot-autoconfigure-1.5.9.RELEASE.jar;

META-INF/spring.factories

配置文件

配置文件的作用:修改SpringBoot自动配置的默认值;SpringBoot在底层都给我们自动配置好;

•application.properties

•application.yml

YAML:以数据为中心

配置文件值注入

第一种

配置文件

person:lastName: helloage: 18boss: falsebirth: 2017/12/12maps: {k1: v1,k2: 12}lists:- lisi- zhaoliudog:name: 小狗age: 12

javaBean:

/*** 将配置文件中配置的每一个属性的值,映射到这个组件中* @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定;*      prefix = "person":配置文件中哪个下面的所有属性进行一一映射   注意:不能大写** 只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能;**/
@Component
@ConfigurationProperties(prefix = "person")
public class Person {private String lastName;private Integer age;private Boolean boss;private Date birth;private Map<String,Object> maps;private List<Object> lists;private Dog dog;

这边:1.@ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定; 注意:不能大写

  1. @Component

可选项:导入配置文件处理器

以后编写配置就有提示了

这边提示。比如lastName 提示 last-name 一样的写法

<dependency><groupId>org.springframework.bootgroupId><artifactId>spring-boot-configuration-processorartifactId><optional>trueoptional>dependency>

这边需要注意:

properties配置文件在idea中默认utf-8可能会乱码

调整

properties文件用的asc码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2UjN42iX-1591248106394)(./images/搜狗截图20180130161620.png)]

第二种 @Value获取值
/*** 将配置文件中配置的每一个属性的值,映射到这个组件中* @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定;*      prefix = "person":配置文件中哪个下面的所有属性进行一一映射** 只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能;*  @ConfigurationProperties(prefix = "person")默认从全局配置文件中获取值;**/
//@PropertySource(value = {"classpath:person.properties"})
@Component
//@ConfigurationProperties(prefix = "person")
//@Validated
public class Person {/*** *      * *///lastName必须是邮箱格式// @Email@Value("${person.last-name}") //从环境变量、配置文件中获取值private String lastName;@Value("#{11*2}")     //SpELprivate Integer age;    @Value("true")       //字面量private Boolean boss;

第三种 @PropertySource(value = {“classpath:person.properties”})

​ 加载指定的配置文件;

  • @ConfigurationProperties(prefix = “person”)默认从全局配置文件中获取值;
  • @PropertySource(value = {“classpath:person.properties”}) 写在resource文件夹里的其他配置类

比较

松散绑定:

属性名匹配规则(Relaxed binding)

key的写法 松散绑定

– person.firstName:使用标准方式

– person.first-name:大写用-

– person.first_name:大写用_

– PERSON_FIRST_NAME:

• 推荐系统属性使用这种写法

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

配置文件yml还是properties他们都能获取到值;

如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value;

如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties;

配置文件注入值数据校验

@Validated

@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {/*** *      * *///lastName必须是邮箱格式@Email//@Value("${person.last-name}")private String lastName;//@Value("#{11*2}")private Integer age;//@Value("true")private Boolean boss;private Date birth;private Map<String,Object> maps;private List<Object> lists;private Dog dog;

比较:@PropertySource&@ImportResource&@Bean

@PropertySource:加载指定的配置文件;

@ImportResource:导入Spring的配置文件,让配置文件里面的内容生效;

​ Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别;想让Spring的配置文件生效,加载进来;@ImportResource标注在一个配置类上

@ImportResource(locations = {"classpath:beans.xml"})
导入Spring的配置文件让其生效

<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 id="helloService" class="com.atguigu.springboot.service.HelloService">bean>
beans>

目前:SpringBoot推荐给容器中添加组件的方式;推荐使用全注解的方式

1、配置类**@Configuration**------>Spring配置文件

2、使用**@Bean**给容器中添加组件

/*** @Configuration:指明当前类是一个配置类;就是来替代之前的Spring配置文件** 在配置文件中用标签添加组件**/
@Configuration
public class MyAppConfig {//将方法的返回值添加到容器中;容器中这个组件默认的id就是方法名@Beanpublic HelloService helloService02(){System.out.println("配置类@Bean给容器中添加组件了...");return new HelloService();}
}

容器中这个组件默认的id就是方法名

配置文件占位符

1、随机数

${random.value}、${random.int}、${random.long}
${random.int(10)}、${random.int[1024,65536]}

2、占位符获取之前配置的值,如果没有可以是用:指定默认值

person.last-name=张三${random.uuid}
person.age=${random.int}
person.birth=2017/12/15
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
person.dog.name=${person.hello:hello}_dog
person.dog.age=15
Profile

1、多Profile文件

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

默认使用application.properties的配置;

2、yml支持多文档块方式

server:port: 8081
spring:profiles:active: prod---
server:port: 8083
spring:profiles: dev---server:port: 8084
spring:profiles: prod  #指定属于哪个环境

3.激活指定profile

1、在配置文件中指定 spring.profiles.active=dev

2、命令行:

​ java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev;

​ 可以直接在测试的时候,配置传入命令行参数

​ 3、虚拟机参数;

​ -Dspring.profiles.active=dev

配置文件加载位置

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

–file:./config/ 
–file:./                             spring-boot-01-quick 项目下  项目路径
–classpath:/config/
–classpath:/                         resources包下     类路径优先级由高到底,高优先级的配置会覆盖低优先级的配置;
SpringBoot会从这四个位置全部加载主配置文件;互补配置;

通过spring.config.location来改变默认的配置文件位置,项目非打包时 配置无效

项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;指定配置文件和默认加载的这些配置文件共同起作用形成互补配置;

例如:

java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.location=G:/application.properties
配置文件加载顺序

SpringBoot也可以从以下位置加载配置; 优先级从高到低;高优先级的配置覆盖低优先级的配置,所有的配置会形成互补配置

1.命令行参数 空格 区分 各个参数

所有的配置都可以在命令行上进行指定

java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087  --server.context-path=/abc

多个配置用空格分开; --配置项=值

2.来自java:comp/env的JNDI属性

3.Java系统属性(System.getProperties())

4.操作系统环境变量

5.RandomValuePropertySource配置的random.*属性值

由jar包外向jar包内进行寻找;

优先加载带profile

6.jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件

7.jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件

再来加载不带profile

8.jar包外部的application.properties或application.yml(不带spring.profile)配置文件

9.jar包内部的application.properties或application.yml(不带spring.profile)配置文件

10.@Configuration注解类上的@PropertySource

11.通过SpringApplication.setDefaultProperties指定的默认属性

所有支持的配置加载来源;

参考官方文档

注意:外部修改配置 配置文件 可以直接放在jar包的同级目录 运行时不用指定参数 直接生效

自动配置原理

配置文件到底能写什么?怎么写?自动配置原理;

配置文件能配置的属性参照

自动配置原理详细过程

1)、SpringBoot启动的时候加载主配置类,开启了自动配置功能                    @EnableAutoConfiguration2)、@EnableAutoConfiguration 作用:- 利用EnableAutoConfigurationImportSelector给容器中导入一些组件?- 可以查看selectImports()方法的内容;- List<String> configurations =       getCandidateConfigurations(annotationMetadata,attributes);获取候选的配置- SpringFactoriesLoader.loadFactoryNames()扫描所有jar包类路径下  META-INF/spring.factories把扫描到的这些文件的内容包装成properties对象从properties中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把他们添加在容器中( configurations 包含  交给容器的所有组件)其中:EnableAutoConfigurationImportSelector ,从 spring boot 1.5 以后,EnableAutoConfigurationImportSelector已经不再被建议使用,而是推荐使用 AutoConfigurationImportSelector。

将 类路径下 META-INF/spring.factories 里面配置的所有EnableAutoConfiguration的值加入到了容器中;

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\
org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,\
org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,\
org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration

每一个这样的 xxxAutoConfiguration类都是容器中的一个组件,都加入到容器中;用他们来做自动配置;

这样容器里就有非常多自动配置类,接着对每一个自动配置类进行自动配置

3)、每一个自动配置类进行自动配置功能;

4)、以**HttpEncodingAutoConfiguration(Http编码自动配置)**为例解释自动配置原理;

@Configuration   //表示这是一个配置类,以前编写的配置文件一样,也可以给容器中添加组件
@EnableConfigurationProperties(HttpEncodingProperties.class)  //启动指定类的ConfigurationProperties功能;将配置文件中对应的值和HttpEncodingProperties绑定起来;并把HttpEncodingProperties加入到ioc容器中@ConditionalOnWebApplication //Spring底层@Conditional注解(Spring注解版),根据不同的条件,如果满足指定的条件,整个配置类里面的配置就会生效;    判断当前应用是否是web应用,如果是,当前配置类生效@ConditionalOnClass(CharacterEncodingFilter.class)  //判断当前项目有没有这个类CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器;@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)  //判断配置文件中是否存在某个配置  spring.http.encoding.enabled;如果不存在,判断也是成立的
//即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的;
public class HttpEncodingAutoConfiguration {//他已经和SpringBoot的配置文件映射了private final HttpEncodingProperties properties;//只有一个有参构造器的情况下,参数的值就会从容器中拿public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {this.properties = properties;}@Bean   //给容器中添加一个组件,这个组件的某些值需要从properties中获取@ConditionalOnMissingBean(CharacterEncodingFilter.class) //判断容器没有这个组件?public CharacterEncodingFilter characterEncodingFilter() {CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();filter.setEncoding(this.properties.getCharset().name());filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));return filter;}

根据当前不同的条件判断,决定这个配置类是否生效?

一但这个配置类生效;这个配置类就会给容器中添加各种组件;这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的;

5)、所有在配置文件中能配置的属性都是在xxxxProperties类中封装者‘;配置文件能配置什么就可以参照某个功能对应的这个属性类

@ConfigurationProperties(prefix = "spring.http.encoding")  //从配置文件中获取指定的值和bean的属性进行绑定
public class HttpEncodingProperties {public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

精髓:

1)、SpringBoot启动会加载大量的自动配置类

2)、我们看我们需要的功能有没有SpringBoot默认写好的自动配置类;

3)、我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件有,我们就不需要再来配置了)

4)、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们就可以在配置文件中指定这些属性的值;

xxxxAutoConfigurartion:自动配置类;

给容器中添加组件

xxxxProperties:封装配置文件中相关属性;

日志框架

市面上的日志框架;

JUL、JCL、Jboss-logging、logback、log4j、log4j2、slf4j…

日志门面 (日志的抽象层)日志实现
JCL(Jakarta Commons Logging) SLF4j(Simple Logging Facade for Java) jboss-loggingLog4j JUL(java.util.logging) Log4j2 Logback

左边选一个门面(抽象层)、右边来选一个实现;

日志门面: SLF4J;

日志实现:Logback;

SpringBoot:底层是Spring框架,Spring框架默认是用JCL;‘

SpringBoot选用 SLF4j和logback;

SLF4J

如何在系统中使用SLF4j https://www.slf4j.org

以后开发的时候,日志记录方法的调用,不应该来直接调用日志的实现类,而是调用日志抽象层里面的方法;

导了日志的抽象

又导了日志的实现

给系统里面导入slf4j的jar和 logback的实现jar

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class HelloWorld {public static void main(String[] args) {Logger logger = LoggerFactory.getLogger(HelloWorld.class);logger.info("Hello World");}
}

图示;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z1E0VCHA-1591248106396)(…/images/concrete-bindings.png)]

每一个日志的实现框架都有自己的配置文件。使用slf4j以后,配置文件还是做成日志实现框架自己本身的配置文件;

其他日志:需要面向slf4j 加入: slf4j适配层 承上启下

日志遗留问题

如何让系统中所有的日志都统一到slf4j;

1、将系统中其他日志框架先排除出去;

2、用中间包来替换原有的日志框架;

3、我们导入slf4j其他的实现

日志使用

SpringBoot默认帮我们配置好了日志;

	//记录器Logger logger = LoggerFactory.getLogger(getClass());@Testpublic void contextLoads() {//System.out.println();//日志的级别;//由低到高   trace//可以调整输出的日志级别;日志就只会在这个级别以以后的高级别生效logger.trace("这是trace日志...");logger.debug("这是debug日志...");//SpringBoot默认给我们使用的是info级别的,没有指定级别的就用SpringBoot默认规定的级别;root级别logger.info("这是info日志...");logger.warn("这是warn日志...");logger.error("这是error日志...");}
    日志输出格式:%d表示日期时间,%thread表示线程名,%-5level:级别从左显示5个字符宽度%logger{50} 表示logger名字最长50个字符,否则按照句点分割。 %msg:日志消息,%n是换行符-->%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n

SpringBoot修改日志的默认配置

logging.level.com.atguigu=trace#logging.path=
# 不指定路径在当前项目下生成springboot.log日志
# 可以指定完整的路径;
#logging.file=G:/springboot.log# 在当前磁盘的根路径下创建spring文件夹和里面的log文件夹;使用 spring.log 作为默认文件
logging.path=/spring/log#  在控制台输出的日志的格式
logging.pattern.console=%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n
# 指定文件中日志输出的格式
logging.pattern.file=%d{yyyy-MM-dd} === [%thread] === %-5level === %logger{50} ==== %msg%n
logging.filelogging.pathExampleDescription
(none)(none)只在控制台输出
指定文件名(none)my.log输出日志到my.log文件. 默认当前项目下,能指定完整的路径 进行生成输出
(none)指定目录/var/log用来指定输出目录,输出文件为默认的文件名 spring.log 文件中
指定配置

给类路径下放上每个日志框架自己的配置文件即可;SpringBoot就不使用他默认配置的了

Logging SystemCustomization
Logbacklogback-spring.xml, logback-spring.groovy, logback.xml or logback.groovy
Log4j2log4j2-spring.xml or log4j2.xml
JDK (Java Util Logging)logging.properties

logback.xml:直接就被日志框架识别了;

logback-spring.xml:日志框架就不直接加载日志的配置项,由SpringBoot解析日志配置,可以使用SpringBoot的高级Profile功能

<springProfile name="staging">可以指定某段配置只在某个环境下生效
springProfile>

如:

<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">//按照是否是开发环境 来调<layout class="ch.qos.logback.classic.PatternLayout"><springProfile name="dev"><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ----> [%thread] ---> %-5level %logger{50} - %msg%npattern>springProfile><springProfile name="!dev"><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ==== [%thread] ==== %-5level %logger{50} - %msg%npattern>springProfile>layout>appender>

如果使用logback.xml作为日志配置文件,还要使用profile功能,会有以下错误

no applicable action for [springProfile]

切换日志框架

可以按照slf4j的日志适配图,进行相关的切换;

slf4j+log4j的方式;

<dependency><groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-webartifactId><exclusions><exclusion><artifactId>logback-classicartifactId><groupId>ch.qos.logbackgroupId>exclusion><exclusion><artifactId>log4j-over-slf4jartifactId><groupId>org.slf4jgroupId>exclusion>exclusions>
dependency><dependency><groupId>org.slf4jgroupId><artifactId>slf4j-log4j12artifactId>
dependency>

切换为log4j2

   <dependency><groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-webartifactId><exclusions><exclusion><artifactId>spring-boot-starter-loggingartifactId><groupId>org.springframework.bootgroupId>exclusion>exclusions>dependency><dependency><groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-log4j2artifactId>
dependency>

web开发

思考

自动配置原理?

这个场景SpringBoot帮我们配置了什么?能不能修改?能修改哪些配置?能不能扩展?xxx

xxxxAutoConfiguration:帮我们给容器中自动配置组件;
xxxxProperties:配置类来封装配置文件的内容;
静态资源映射

SpringMVC配置

在WebMvcAuotConfiguration中

分析:

@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {if (!this.resourceProperties.isAddMappings()) {logger.debug("Default resource handling disabled");return;}Integer cachePeriod = this.resourceProperties.getCachePeriod();if (!registry.hasMappingForPattern("/webjars/**")) {customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/").setCachePeriod(cachePeriod));}String staticPathPattern = this.mvcProperties.getStaticPathPattern();//静态资源文件夹映射if (!registry.hasMappingForPattern(staticPathPattern)) {customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern).addResourceLocations(this.resourceProperties.getStaticLocations()).setCachePeriod(cachePeriod));}}//配置欢迎页映射@Beanpublic WelcomePageHandlerMapping welcomePageHandlerMapping(ResourceProperties resourceProperties) {return new WelcomePageHandlerMapping(resourceProperties.getWelcomePage(),this.mvcProperties.getStaticPathPattern());}//配置喜欢的图标@Configuration@ConditionalOnProperty(value = "spring.mvc.favicon.enabled", matchIfMissing = true)public static class FaviconConfiguration {private final ResourceProperties resourceProperties;public FaviconConfiguration(ResourceProperties resourceProperties) {this.resourceProperties = resourceProperties;}@Beanpublic SimpleUrlHandlerMapping faviconHandlerMapping() {SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();mapping.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);//所有  **/favicon.ico mapping.setUrlMap(Collections.singletonMap("**/favicon.ico",faviconRequestHandler()));return mapping;}@Beanpublic ResourceHttpRequestHandler faviconRequestHandler() {ResourceHttpRequestHandler requestHandler = new ResourceHttpRequestHandler();requestHandler.setLocations(this.resourceProperties.getFaviconLocations());return requestHandler;}}

1)、所有 /webjars/** ,都去 classpath:/META-INF/resources/webjars/ 找资源;

​ webjars:以jar包的方式引入静态资源;

http://www.webjars.org/

例如:

localhost:8080/webjars/abc

会到

classpath:/META-INF/resources/webjars/中找

abc

2)、"/**" 访问当前项目的任何资源,都去(静态资源的文件夹)找映射 没人处理

"classpath:/META-INF/resources/", 
"classpath:/resources/",
"classpath:/static/", 
"classpath:/public/" 
"/":当前项目的根路径

localhost:8080/abc === 去静态资源文件夹里面找abc

3)、欢迎页; 静态资源文件夹下的所有index.html页面;被"/**"映射;

​ localhost:8080/ 找index页面

4)、所有的 **/favicon.ico 都是在静态资源文件下找; 图标

改变静态资源文件夹: spring.resources.static.locations = classpath:/hello/, class path:/icoder/

模版引擎

JSP、Velocity、Freemarker、Thymeleaf

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qMr37X3d-1591248106398)(/Users/test/Desktop/Spring Boot 笔记/images/template-engine.png)]

SpringBoot推荐的Thymeleaf;

语法更简单,功能更强大;

默认:2.1.6

改成3

		org.springframework.bootspring-boot-starter-thymeleaf2.1.6
切换thymeleaf版本
3.0.9.RELEASE2.2.2

使用:

默认规则:

@ConfigurationProperties(prefix = "spring.thymeleaf")
public class ThymeleafProperties {private static final Charset DEFAULT_ENCODING = Charset.forName("UTF-8");private static final MimeType DEFAULT_CONTENT_TYPE = MimeType.valueOf("text/html");public static final String DEFAULT_PREFIX = "classpath:/templates/";public static final String DEFAULT_SUFFIX = ".html";//

只要我们把HTML页面放在classpath:/templates/,thymeleaf就能自动渲染;

使用:

1、导入thymeleaf的名称空间

<html lang="en" xmlns:th="http://www.thymeleaf.org">

2、使用thymeleaf语法;


<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Titletitle>
head>
<body><h1>成功!h1><div th:text="${hello}">这是显示欢迎信息div>
body>
html>

替换

重点:th:each=""  写在那个标签 就循环输出那个标签行內写法:    [ ]


[[${user}]] //行内写法

Springmvc自动配置原理
项目注意点

1.清除模版引擎的缓存

2.注意优先级的高低 思考 为什么th:if 不生效 th:text就不起作用 标签就不会生成

th:text;改变当前元素里面的文本内容;

th:任意html属性;来替换原生属性的值 th:id th:class

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YDHv4SpQ-1591248106400)(/Users/test/Desktop/Spring Boot 笔记/images/2018-02-04_123955.png)]

公共资源:th:src="@{/webjars/popper.js/1.11.1/dist/popper.js}"

个人资源:th:src="@{/asserts/js/Chart.min.js}"

4.Controller 返回值

都已经完成了 前缀 后缀 需要进行一个拼装

方法明确:处理什么请求 参数 过程 返回值

return “” 由模版引擎进行渲染解析 跳到页面

重定向:redirect

转发:forward

​ // redirect: 表示重定向到一个地址 /代表当前项目路径
​ // forward: 表示转发到一个地址 RequestDispatcher
​ return “redirect:/emps”

6添加员工时

员工表格:每一个项 的name项,需要和javabean的对象的属性名相同

SpringMVC就会进行自动绑定

  1. th:href="@{/emp/}+${emp.id}"

    使用拼串的方式

    采用路径变量的方式带上id

    //来到修改页面,查出当前员工,在页面回显

    路径变量:@PathVariable(“id”)

     @GetMapping("/emp/{id}")    public String toEditPage(@PathVariable("id") Integer id,Model model){Employee employee = employeeDao.get(id);model.addAttribute("emp",employee);//页面要显示所有的部门列表Collection<Department> departments = departmentDao.getDepartments();model.addAttribute("depts",departments);//回到修改页面(add是一个修改添加二合一的页面);return "emp/add";
    }
    

表单属性思考:

绑定 自动映射 name属性

回显 value 填值

个人思考

https://www.cnblogs.com/cyhbyw/p/8618747.html


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部