-
主程序
-
@SpringBootApplication来标注一个springboot主程序类
- @Configuration:标记配置类,也是一个容器(@Component)
- @EnableAutoConfiguration:开启自动配置功能
- @AutoConfigurationPackage:自动配置包
- @Import,spring底层组件,给容器中导入一个组件
- Spring Boot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值,将
这些值作为自动配置类导入到容器中,自动配置类就生效,帮我们进行自动配置工作;以前我们需要自己配置的东
西,自动配置类都帮我们;J2EE的整体整合解决方案和自动配置都在spring-boot-autoconfigure-1.5.9.RELEASE.jar;
-
-
yml语法
- 基本语法k: v --> 表示一对键值对
name: jiyu
- 对象/map
- 换行写法
person: name: jiyu age: 22
- 行内写法
person: {name: jiyu, age: 22}
- 换行写法
- 数组(List, Set)
- 换行写法
animal: - dog - pig - flog
- 行内写法
animal: [dog, pig, flog]
- 换行写法
- 基本语法k: v --> 表示一对键值对
-
@Value和@ConfigurationProperties的区别
@ConfigurationProperties
@Value
配置方式
批量指定
单个指定属性
松散绑定
支持
不支持
SpEL
不支持
支持
JSR303数据校验
支持
不支持
复杂类型封装
支持
不支持
-
@value用于简单获取配置文件,@ConfigurationProperties用于复杂配置
-
松散绑定
-
JSR303校验: @Validated @NotNull
-
复杂类型封装: map, list, set等
-
-
@PropertySource和@ImportResource和@Bean
- @PropertySource读取指定的配置文件(不能读取yml文件,如需要须配置)
- @ImportResource导入spring的xml配置文件
- @Bean将方法的返回值添加到容器中,在容器的id默认是方法名,配合@Configuration使用
-
配置文件占位符
- 随机数: ${random.int},${random.int(10)},${random.int[1,2,33,444]}
- 冒号指定默认值:${server.port:8080}
-
多profile文件
- 主配置文件写成application-{profile}.yml/properties,默认使用application.properties配置文件
- 使用spring.profiles.active=profile激活
- yml使用---作为文档块,文档块可指定profile,可在第一个文档块中指定profile
- 可使用--spring.profiles.active=profile命令行指定
- 可使用-Dspring.profiles.active=profile虚拟机参数指定
-
配置文件路径的优先级
- 优先级从高到底
- file:./config/application.properties
- file:./application.properties
- classpath:/config/application.properties
- classpath:/application.properties
- 这四个文件位置会形成互补配置
- 命令行参数使用--spring.config.location=filePath指定配置文件
- 优先级从高到底
-
外部配置文件加载顺序
- 优先级从高到低
- 命令行
- 来自Java:comp/env的JNDI属性
- Java系统属性(System.getProperties())
- 操作系统环境变量
- RandomValuePropertySource配置的random.*属性值
- jar包外部application-profile.yml/properties,带profile
- jar包内部application-profile.yml/properties,带profile
- jar包外部application.yml/properties,不带profile
- jar包内部application.yml/properties,不带profile
- 通过@Configuration注解类上的@PropertySource指定
- 通过SpringApplication.setDefaultProperties()指定默认属性
- 优先级从高到低
-
自动配置原理
- springboot启动的时候开启了自动配置功能@EnableAutoConfiguration
- @EnableAutoConfiguration的作用
- 使用AutoConfigurationImportSelector给容器中导入了一些组件
- 导入的组件由selectImports()方法决定
- List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);获取候选配置
- loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader);扫描META-INF/spring.factories文件,并封装成properties对象
- 从properties中获取到EnableAutoConfiguration.class类(类名)对应的值,然后将其加入到容器中
- META-INF/spring.factories中的内容
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.CassandraReactiveDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\ 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.MongoReactiveDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\ 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.RedisReactiveAutoConfiguration,\ 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.flyway.FlywayAutoConfiguration,\ 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.http.HttpMessageConvertersAutoConfiguration,\ org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\ org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\ 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.groovy.template.GroovyTemplateAutoConfiguration,\ org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\ org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\ org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\ 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.mongo.embedded.EmbeddedMongoAutoConfiguration,\ org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\ org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\ org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\ org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\ org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\ org.springframework.boot.autoconfigure.reactor.core.ReactorCoreAutoConfiguration,\ org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\ org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\ org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\ org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\ org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\ org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\ org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\ org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientAutoConfiguration,\ 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.client.RestTemplateAutoConfiguration,\ org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\ org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\ org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\ org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\ org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\ org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\ org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\ org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\ org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
-
每一个xxxAutoConfiguration都是容器中的一个组件,都加入到容器中用来做自动配置
-
以HttpEncodingAutoConfiguration为例解读自动配置
@Configuration//配置类 //启动指定类的ConfigurationProperties功能,映射HttpEncodingProperties和配置文件并加入ioc容器中 @EnableConfigurationProperties(HttpEncodingProperties.class) //@Conditional满足条件才会生效,是否web应用 @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) //是否有CharacterEncodingFilter类 @ConditionalOnClass(CharacterEncodingFilter.class) //配置文件中是否有spring.http.encoding为enabled的配置,matchIfMissing 如果判断不存在也是成立的 @ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true) public class HttpEncodingAutoConfiguration { //此配置已和配置文件映射 private final HttpEncodingProperties properties; //只有一个有参构造器,参数的值会从容器中获取 public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) { this.properties = properties; } //给容器中添加组件,这个组件的某些值需要从properties中获取 @Bean @ConditionalOnMissingBean 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; } } //从配置文件中获取指定的值和bean的属性绑定 @ConfigurationProperties(prefix = "spring.http.encoding") public class HttpEncodingProperties { }
-
配置文件能配置的东西参照对应功能的xxxProperties类
-
精髓
-
springboot启动时会加载大量配置类
-
如果我们需要的功能springboot已经写好配置类,则默认,如果没有则自定义
-
再看自动配置类中定义了哪些组件,如果有我们需要的则不需要配置,如果没有则自定义配置
-
springboot给容器加组件时,会从properties中读取某些,如果有需要自定义的属性,则从配置文件中自定义
-
-
@Conditional
@Conditional扩展注解
作用(判断是否满足当前指定条件)
@ConditionalOnJava 系统的java版本是否符合要求 @ConditionalOnBean 容器中存在指定Bean @ConditionalOnMissingBean 容器中不存在指定Bean @ConditionalOnExpression 满足SpEL表达式指定 @ConditionalOnClass 系统中有指定的类 @ConditionalOnMissingClass 系统中没有指定的类 @ConditionalOnSingleCandidate 容器中只有一个指定的Bean,或者这个Bean是首选Bean @ConditionalOnProperty 系统中指定的属性是否有指定的值 @ConditionalOnResource 类路径下是否存在指定资源文件 @ConditionalOnWebApplication 当前是web环境 @ConditionalOnNotWebApplication 当前不是web环境 @ConditionalOnJndi JNDI存在指定项 -
配置文件debug=true启动时可打印自动配置报告
-
面向接口编程
- 代码里使用接口里定义的方法
- 接口里定义的方法通过具体类实现(可插拔)
-
日志框架
- 日志门面(接口)
- slf4j(simple logging facade for Java): 流行
- jcl(jakarta commons logging): 停止更新
- jboss-jboss-loggin: 使用少
- 日志实现
- logback: log4j的升级版
- log4j: slf4j的实现,性能不太好
- log4j2: apache的,使用少
- jul(Java utils logging): Java原生日志
- slf4j的使用
- 兼容log4j,导入log4j-to-slf4j包
- 兼容其它日志,排除其它框架里的日志框架,增加替代的jar包
- 日志门面(接口)
-
springboot对静态资源的映射规则
@Configuration @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class }) @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,ValidationAutoConfiguration.class }) public class WebMvcAutoConfiguration { public static final String DEFAULT_PREFIX = ""; public static final String DEFAULT_SUFFIX = ""; private static final String[] SERVLET_LOCATIONS = { "/" }; @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { } }
@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false) public class ResourceProperties { //设置映射规则,缓存时间等 private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/" }; }
- /webjars/**会到classpath:/META-INF/resources/webjars/寻找资源
- /**没有匹配的情况会到一下路径寻找资源(静态资源文件夹)
"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/", "/"
- 欢迎页,静态资源文件夹下的所有index.html页面
- 图标,**/favicon.ico都在静态资源文件夹下查找
-
springboot thymeleaf模板引擎
- 引入starter
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
- 导入名称空间(非必须):<html lang="en" xmlns:th="http://www.thymeleaf.org">
- 语法
- th:html属性: 改变html的属性
- 基础标签
标签 功能 类比jsp标签 1 th:insert 插入子片段 jsp:include 2 th:replace 替换当前节点片段 jsp:include 3 th:each 遍历 c:forEach 4 th:if 条件判断 c:if 5 th:unless 条件判断 c:if 6 th:switch 条件判断 c:when 7 th:case 条件判断 c:choose 8 th:object 申明变量 c:set 9 th:with 申明变量 c:set 10 th:attr 属性修改 11 th:attrprepend 任意属性修改 12 th:attrappend 任意属性修改 13 th:value 修改value属性 14 th:href 修改href属性 15 th:src 修改src属性 16 th:text 修改text属性(不转意),行内写法[[...]] 17 th:utext 修改text属性(转义)行内写法[(...)] 18 th:fragment 申明片段 19 th:remove 移除片段 - 表达式
- ${...}获取变量值,底层是ognl表达式
- 获取对象的属性,调用方法
- 可使用字面变量,文本操作,数学运算,逻辑判断,条件运算
- 内置基本对象
- #ctx
- #vars
- #locale
- #request
- #response
- #session
- #servletContext
- param
- session
- application
- -代表无操作
- 内置工具对象
- #number
- #string
- *{...}和${..}功能一样,可配合th:object提出共有部分
- #{...}获取国际化内容
- @{...}定义url链接
- <a class="form-signin" th:action="@{localhost:8080/version/login/login}">
- <a class="form-signin" th:action="@{/login/login(user=${user}, pass=${pass})}">
- ~{...}片段引用表达式:<div th:insert=~{commons :: main}>...</div>
- ${...}获取变量值,底层是ognl表达式
- 引入starter
-
springmvc auto-configuration
- ContentNegotiatingViewResolver和BeanNameViewResolver
- 自动配置了ViewResolver(视图解析器),视图解析对象决定如何渲染(重定向还是转发)
- ContentNegotiatingViewResolver组合所有的视图解析器
- 定制视图解析器: 给容器中添加一个自定义的ViewResolver(视图解析器),自定义的ViewResolver实现ViewResolver接口
- webjars
- 静态首页index.html访问
- favicon.ico
- 自动注册了Converter,GenericConverter,Formatter组件
- Converter:转换器,view和controller类型转换时使用
- Formatter:格式化器,转换日期格式时使用,生效条件
- 添加格式化器,转换器的方法,如果自定义,则需要往容器里添加Converter的实现
@Override public void addFormatters(FormatterRegistry registry) { for (Converter<?, ?> converter : getBeansOfType(Converter.class)) { registry.addConverter(converter); } for (GenericConverter converter : getBeansOfType(GenericConverter.class)) { registry.addConverter(converter); } for (Formatter<?> formatter : getBeansOfType(Formatter.class)) { registry.addFormatter(formatter); } }
- HttpMessageConverter
- springmvc用来转换http请求和响应的
- @ResponseBody时Object-->Json
- @RequestBody时json-->Object
- 自定义HttpMessageConverter转换器:@Bean或@Component加入HttpMessageConverters到容器中
- springmvc用来转换http请求和响应的
- MessageCodesResolver:定义错误代码生成规则的(jsr303校验)
- ConfigurableWebBindingInitializer:初始化WebDataBinder组件
- 自定义:往容器中加入一个ConfigurableWebBindingInitializer组件
- WebDataBinder的作用:请求数据-->JavaBean
- ContentNegotiatingViewResolver和BeanNameViewResolver
-
修改springboot的默认的自动配置
- springboot在自动配置时,会先查看容器中是否有用户自定义的配置(@Bean或@Component注入),如果有则使用用户自定义的,如果没有则使用默认配置的;如果该组件是一个列表(ViewResolver),则将用户定义的和默认的组合起来
- springboot中会有很多xxxConfigurer帮助我们扩展自动配置
-
扩展springmvc
- 编写一个WebMvcConfigurer或WebMvcConfigurerAdapter类型的配置类(@Configuration),并且不能标注@EnableWebMvc
- 原理
- WebMvcAutoConfiguration是springmvc的自动配置类
- 在做其它配置时,会导入@Import(EnableWebMvcConfiguration.class)
@Configuration public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration { } @Configuration public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport { private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite(); //@Autowired标注会从容器中获取参数的值 @Autowired(required = false) public void setConfigurers(List<WebMvcConfigurer> configurers) { if (!CollectionUtils.isEmpty(configurers)) { this.configurers.addWebMvcConfigurers(configurers); //将WebMvcConfiguration相关配置一起调用 //public void addWebMvcConfigurers(List<WebMvcConfigurer> configurers) { // if (!CollectionUtils.isEmpty(configurers)) { // this.delegates.addAll(configurers); // } //} } } }
- 所有的WebMvcConfiguration一起起作用
- 我们的配置类也会起作用
- 配置添加@EnableWebMvc会全面接管springmvc,springmvc的自动配置全部失效(最好不要用),原理如下
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Import(DelegatingWebMvcConfiguration.class) public @interface EnableWebMvc { }
@Configuration public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport { }
@Configuration @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class }) @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) @AutoConfigureAfter({DispatcherServletAutoConfiguration.class,ValidationAutoConfiguration.class }) public class WebMvcAutoConfiguration { }
-
@EnableWebMvc将WebMvcConfigurationSupport导入进来,只具有springmvc的基础功能
-
国际化
- 编辑国际化配置文件
- 使用ResourceBundleMessageSource管理国际化资源文件
- springboot自动配置
@Configuration @ConditionalOnMissingBean(value = MessageSource.class, search = SearchStrategy.CURRENT) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) @Conditional(ResourceBundleCondition.class) @EnableConfigurationProperties public class MessageSourceAutoConfiguration { @Bean public MessageSource messageSource() { MessageSourceProperties properties = messageSourceProperties(); ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); if (StringUtils.hasText(properties.getBasename())) { //设置基础名(去掉国家代码) messageSource.setBasenames(StringUtils.commaDelimitedListToStringArray( StringUtils.trimAllWhitespace(properties.getBasename()))); } if (properties.getEncoding() != null) { messageSource.setDefaultEncoding(properties.getEncoding().name()); } messageSource.setFallbackToSystemLocale(properties.isFallbackToSystemLocale()); Duration cacheDuration = properties.getCacheDuration(); if (cacheDuration != null) { messageSource.setCacheMillis(cacheDuration.toMillis()); } messageSource.setAlwaysUseMessageFormat(properties.isAlwaysUseMessageFormat()); messageSource.setUseCodeAsDefaultMessage(properties.isUseCodeAsDefaultMessage()); return messageSource; } }
- springboot自动配置
- 在页面使用fmt:message取出国际化内容
- 使用#{common.loginUser}获取
- 根据用户选择获取,使用LocalResolver设置,默认根据请求头信息里的语言设置
@Configuration @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class }) @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class }) public class WebMvcAutoConfiguration { @Bean @ConditionalOnMissingBean @ConditionalOnProperty(prefix = "spring.mvc", name = "locale") public LocaleResolver localeResolver() { if (this.mvcProperties .getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) { return new FixedLocaleResolver(this.mvcProperties.getLocale()); } AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver(); localeResolver.setDefaultLocale(this.mvcProperties.getLocale()); return localeResolver; } }
-
restfulCRUD
- URL格式: /资源名称/资源标识 HTTP请求方式区分对资源的crud操作
- 请求方式
查询 GET 增加 POST 修改 PUT 删除 DELETE
-
thymeleaf布局
- 抽取公共片段
- 引入片段
- ~{模板名::选择器名(变量1,变量2...)}
- ~{模板名::片段名(变量1=值1,变量2=值2)}
- 模板名遵循thymeleaf规则
- th:insert是在当前节点下插入一个子节点,子节点的内容就是该片段
- th:replace是用该片段的内容替换当前节点的内容
- th:include是将该片段的内容包含到当前节点中(不包含片段的最外层标签)
- th:insert可使用[[~{...}]]和[(...)]行内写法
-
springboot发送其它请求方式
- springmvc中配置HiddenHttpMethodFilter,已自动配置好
- form表单使用post方式
- 创建一个input项,name为_method,value为put,不区分大小写
-
错误处理机制
- 浏览器默认返回一个错误页面
- 其它客户端默认返回json数据
- 原理
- ErrorMvcAutoConfiguration配置
public class DefaultErrorAttributes implements ErrorAttributes { @Override public Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) { Map<String, Object> errorAttributes = new LinkedHashMap<>(); errorAttributes.put("timestamp", new Date()); errorAttributes.put("path", request.path()); Throwable error = getError(request); HttpStatus errorStatus = determineHttpStatus(error); errorAttributes.put("status", errorStatus.value()); errorAttributes.put("error", errorStatus.getReasonPhrase()); errorAttributes.put("message", determineMessage(error)); handleException(errorAttributes, determineException(error), includeStackTrace); return errorAttributes; } }
- 给容器中添加了以下组件
- DefaultErrorAttributes: 响应错误数据,json格式
- BasicErrorController: 处理/error请求
@Controller @RequestMapping("${server.error.path:${error.path:/error}}") public class BasicErrorController extends AbstractErrorController { @RequestMapping(produces = "text/html")//html数据,响应浏览器 public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { HttpStatus status = getStatus(request); Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes( request, isIncludeStackTrace(request, MediaType.TEXT_HTML))); response.setStatus(status.value()); //响应的页面地址 ModelAndView modelAndView = resolveErrorView(request, response, status, model); /** protected ModelAndView resolveErrorView(HttpServletRequest request, HttpServletResponse response, HttpStatus status, Map<String, Object> model) { for (ErrorViewResolver resolver : this.errorViewResolvers) { ModelAndView modelAndView = resolver.resolveErrorView(request, status, model); if (modelAndView != null) { return modelAndView; } } return null; } */ return (modelAndView != null) ? modelAndView : new ModelAndView("error", model); } @RequestMapping @ResponseBody//json数据,响应其它客户端 public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) { Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL)); HttpStatus status = getStatus(request); return new ResponseEntity<>(body, status); } }
- ErrorPageCustomizer: 发生错误就会来到/error请求
public class ErrorProperties { /** * Path of the error controller. */ @Value("${error.path:/error}") private String path = "/error"; }
- DefaultErrorViewResolver: 决定去哪个页面
public class DefaultErrorViewResolver implements ErrorViewResolver, Ordered { @Override public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) { ModelAndView modelAndView = resolve(String.valueOf(status), model); if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) { modelAndView = resolve(SERIES_VIEWS.get(status.series()), model); } return modelAndView; } private ModelAndView resolve(String viewName, Map<String, Object> model) { //去到/error/4xx页面 String errorViewName = "error/" + viewName; //模板引擎解析 TemplateAvailabilityProvider provider = this.templateAvailabilityProviders .getProvider(errorViewName, this.applicationContext); //解析成功 if (provider != null) { return new ModelAndView(errorViewName, model); } //解析失败,就去静态资源文件夹下找errorViewName页面,error/4xx.html return resolveResource(errorViewName, model); } }
- ErrorMvcAutoConfiguration配置
-
定制错误响应
-
定制错误页面
-
有模板引擎: 去到error/状态码页面,可使用error/4xx和error/5xx表示,精确匹配优先
-
页面能获取到信息DefaultErrorAttributes决定
-
timestamp: 时间戳
-
status: 状态码
-
error: 错误提示
-
exception: 异常对象
-
message: 异常信息
-
errors: jsr303数据校验错误的信息
-
-
没有模板引擎: 在静态资源文件夹下查找
-
以下页面都没有,则返回springboot默认的页面
-
-
定制错误json数据
-
方式一: 编写一个ErrorController实现,放容器中
-
方式二: 自定义一个ErrorAttributes放入到容器中
-
-
-
配置嵌入式的servlet容器
- 修改容器相关的配置: server.xxx修改通用配置,servlet.tomcat.xxx修改和tomcat相关的配置
- 切换容器: 排除默认的tomcat,引入需要的容器
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <!--排除默认的tomcat容器--> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <!--性能较高,不支持jsp页面--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> </dependency>
- 容器自动配置原理
//自动配置类 @Configuration @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) @ConditionalOnClass(ServletRequest.class) @ConditionalOnWebApplication(type = Type.SERVLET) @EnableConfigurationProperties(ServerProperties.class) @Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class, ServletWebServerFactoryConfiguration.EmbeddedTomcat.class, ServletWebServerFactoryConfiguration.EmbeddedJetty.class, ServletWebServerFactoryConfiguration.EmbeddedUndertow.class }) public class ServletWebServerFactoryAutoConfiguration { public static class BeanPostProcessorsRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware { } } //根据导包选择使用的容器 @Configuration class ServletWebServerFactoryConfiguration { @Configuration @ConditionalOnClass({ Servlet.class, Undertow.class, SslClientAuthMode.class }) @ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT) public static class EmbeddedUndertow { @Bean public UndertowServletWebServerFactory undertowServletWebServerFactory() { return new UndertowServletWebServerFactory(); } } } //undertow容器工厂 public class UndertowServletWebServerFactory extends AbstractServletWebServerFactory implements ConfigurableUndertowWebServerFactory, ResourceLoaderAware { protected UndertowServletWebServer getUndertowWebServer(Builder builder, DeploymentManager manager, int port) { return new UndertowServletWebServer(builder, manager, getContextPath(), isUseForwardHeaders(), port >= 0, getCompression(), getServerHeader()); } } //undertow容器 public class UndertowServletWebServer implements WebServer { public UndertowServletWebServer(Builder builder, DeploymentManager manager, String contextPath, boolean useForwardHeaders, boolean autoStart, Compression compression, String serverHeader) { this.builder = builder; this.manager = manager; this.contextPath = contextPath; this.useForwardHeaders = useForwardHeaders; this.autoStart = autoStart; this.compression = compression; this.serverHeader = serverHeader; } @Override public void start() throws WebServerException { synchronized (this.monitor) { if (this.started) { return; } try { if (!this.autoStart) { return; } if (this.undertow == null) { this.undertow = createUndertowServer(); } this.undertow.start(); this.started = true; UndertowServletWebServer.logger .info("Undertow started on port(s) " + getPortsDescription() + " with context path '" + this.contextPath + "'"); } catch (Exception ex) { try { if (findBindException(ex) != null) { List<Port> failedPorts = getConfiguredPorts(); List<Port> actualPorts = getActualPorts(); failedPorts.removeAll(actualPorts); if (failedPorts.size() == 1) { throw new PortInUseException( failedPorts.iterator().next().getNumber()); } } throw new WebServerException("Unable to start embedded Undertow", ex); } finally { stopSilently(); } } } } }
-
注册三大组件
- servlet使用ServletRegistrationBean注册
- filter使用FilterRegistrationBean注册
- listener使用ServletListenerRegistrationBean注册
- 三大组件的注册方式相同
- springboot自动注册DispatcherServlet前端控制器
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) @Configuration @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass(DispatcherServlet.class) @AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class) public class DispatcherServletAutoConfiguration { @Configuration @Conditional(DispatcherServletRegistrationCondition.class) @ConditionalOnClass(ServletRegistration.class) @EnableConfigurationProperties(WebMvcProperties.class) @Import(DispatcherServletConfiguration.class) protected static class DispatcherServletRegistrationConfiguration { @Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME) @ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME) public DispatcherServletRegistrationBean dispatcherServletRegistration( DispatcherServlet dispatcherServlet) { DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean( dispatcherServlet, this.webMvcProperties.getServlet().getPath()); //默认拦截所有请求(/),不包括jsp,/*包含jsp请求 registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME); registration.setLoadOnStartup( this.webMvcProperties.getServlet().getLoadOnStartup()); if (this.multipartConfig != null) { registration.setMultipartConfig(this.multipartConfig); } return registration; } } }
-
使用外置容器
- 创建war项目,并使用idea生成目录结构
- 配置jsp模板规则
spring.mvc.view.prefix=/WEB-INF/views/ spring.mvc.view.suffix=.jsp
- 将嵌入式的容器指定为provider方式
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provider</scope> </dependency>
- 和ServiceApplication(springboot主程序)同级必须有一个SpringBootServletInitializer类
//运行springboot主程序类 public class ServletInitializer extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(ServiceApplication.class); } }
-
springboot运行原理
- jar包: 执行springboot主程序的主方法,启动ioc容器,创建嵌入式的servlet容器
- war包: 启动servlet容器,servlet容器启动springboot的主程序方法,启动ioc容器
-
整合mybatis框架
- 导入mybatis包
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency>
- 写*Mapper接口,需要使用@mapper标注或主程序上使用@MapperScan("*Mapper接口所在包")
- 注解版: 直接在写的接口上使用@Select,@Delete,@Insert,@Update写sql语句
- 配置文件版: 写一个全局配置文件和sql映射文件,并在springboot配置文件中指定mybatis配置文件所在地点
- 注解版可通过ConfigurationCustomizer自定义mybatis配置
- 配置文件版直接在mybatis配置文件中自定义mybatis配置
- 导入mybatis包
-
springboot运行流程
- 几个重要的事件回调机制
- ApplicationContextInitializer,配置在类路径下的META-INF/spring.factories中
- SpringApplicationRunListener,配置在类路径下的META-INF/spring.factories中
- ApplicationRunner,加入到ioc容器中,使用@Component注解
- CommandLineRunner,加入到ioc容器中,使用@Component注解
- 创建SpringApplication对象
public class SpringApplication { public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { this.resourceLoader = resourceLoader; Assert.notNull(primarySources, "PrimarySources must not be null"); //保存主配置类 this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); 判断是否web应用 this.webApplicationType = WebApplicationType.deduceFromClasspath(); //从类路径下找到META-INF/spring.factories配置的所有ApplicationContextInitializer,然后保存起来 setInitializers((Collection) getSpringFactoriesInstances( ApplicationContextInitializer.class)); //从类路径下找到META-INF/spring.factories配置的所有ApplicationListener,然后保存起来 setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); //找到主配置类 this.mainApplicationClass = deduceMainApplicationClass(); } }
- 运行run方法
public class SpringApplication { public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); configureHeadlessProperty(); //获取SpringApplicationRunListeners,从类路径下找到META-INF/spring.factories获取 SpringApplicationRunListeners listeners = getRunListeners(args); //回调SpringApplicationRunListener.starting()方法 listeners.starting(); try { //封装命令行参数 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); /** *准备环境 *创建环境,完成后回调SpringApplicationRunListener.environmentPrepared()方法,环境准备完成 */ ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment); //打印banner图形 Banner printedBanner = printBanner(environment); //创建ioc容器 context = createApplicationContext(); exceptionReporters = getSpringFactoriesInstances( SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context); /** *准备上下文环境 *将environment保存到ioc中 *通过applyInitializers(context)回调所有的ApplicationContextInitializer.initialize()方法 *通过listeners.contextPrepared(context);回调SpringApplicationRunListener.contextPrepared(context)方法 *最后回调SpringApplicationRunListener.contextLoaded(context)方法 */ prepareContext(context, environment, listeners, applicationArguments, printedBanner); //刷新容器,ioc容器初始化 refreshContext(context); //从ioc容器中依次获取ApplicationRunner和CommandLineRunner回调 afterRefresh(context, applicationArguments); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } //回调所有SpringApplicationRunListener.started(context)方法 listeners.started(context); callRunners(context, applicationArguments); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, listeners); throw new IllegalStateException(ex); } try { listeners.running(context); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, null); throw new IllegalStateException(ex); } //启动完成,返回ioc容器 return context; } }
- 几个重要的事件回调机制
-
自定义starter启动器
- 编写自动配置
@Configuration //指定该类是一个配置类 @ConditionalOnWebApplication(type = Type.SERVLET) //判断web应用 @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class }) //有Servlet类 @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) //没有WebMvcConfigurationSupport类 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) //指定顺序 @AutoConfigureAfter({DispatcherServletAutoConfiguration.class,ValidationAutoConfiguration.class }) //指定顺序 public class WebMvcAutoConfiguration { @Configuration @Import(EnableWebMvcConfiguration.class) //让xxxProperties生效并加入到容器中 @EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class }) @Order(0) public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ResourceLoaderAware { } } @ConfigurationProperties(prefix = "spring.mvc") //结合xxxProperties绑定相关配置 public class WebMvcProperties { } //自定配置类需要放在类路径下的META-INF/spring.factories中才能自动加载 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
- 模式
- 启动器starter是一个空的jar文件,紧提供辅助性的依赖管理
- 名称约定
- 启动器
- 官方: spring-boot-starter-web
- 自定义: mybatis-spring-boot-starter
- 自动配置: xxx-autoconfigurer
- 启动器
- 步骤
- 编写一个[模块名-spring-boot-starter]模块,引用[模块名-spring-boot-starter-autoconfigurer]模块
- 编写一个[模块名-spring-boot-starter-autoconfigurer]模块
- 编写xxxService处理业务逻辑
public class HelloService { HelloProperties helloProperties; public String sayHello(String name){ return helloProperties.getPrefix() + "==>" + name + "<==" + helloProperties.getSuffix(); } public HelloProperties getHelloProperties() { return helloProperties; } public void setHelloProperties(HelloProperties helloProperties) { this.helloProperties = helloProperties; } }
- 编写xxxServiceAutoConfiguration
@Configuration @ConditionalOnWebApplication @EnableConfigurationProperties(HelloProperties.class) public class HelloServiceAutoConfiguration { @Autowired HelloProperties helloProperties; @Bean public HelloService helloService(){ HelloService helloService = new HelloService(); helloService.setHelloProperties(helloProperties); return helloService; } }
- 编写xxxServiceProperties绑定配置文件
@ConfigurationProperties(prefix = "jiyu.hello") public class HelloProperties { private String prefix = ""; private String suffix = ""; public String getPrefix() { return prefix; } public void setPrefix(String prefix) { this.prefix = prefix; } public String getSuffix() { return suffix; } public void setSuffix(String suffix) { this.suffix = suffix; } }
- 在类路径下的META-INF/spring.factories加入HelloServiceAutoConfiguration类
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.version.starter.HelloServiceAutoConfiguration
-
在需要使用地点引用该starter即可使用
- 编写xxxService处理业务逻辑
- 编写自动配置