本篇文章给大家谈谈SpringBoot2.0系列002--运行流程分析,以及springboot的运行流程的知识点,同时本文还将给你拓展001-快速搭建Springweb应用【springboot2.
本篇文章给大家谈谈SpringBoot 2.0 系列002 --运行流程分析,以及springboot的运行流程的知识点,同时本文还将给你拓展001-快速搭建Spring web应用【springboot 2.0.4】-gradle、springboot的启动过程分析、gradle多模块构建、16. SpringBoot自动配置流程分析、spring boot http接口单元测试运行流程分析、spring boot 自动配置与启动流程分析等相关知识,希望对各位有所帮助,不要忘了收藏本站喔。
本文目录一览:- SpringBoot 2.0 系列002 --运行流程分析(springboot的运行流程)
- 001-快速搭建Spring web应用【springboot 2.0.4】-gradle、springboot的启动过程分析、gradle多模块构建
- 16. SpringBoot自动配置流程分析
- spring boot http接口单元测试运行流程分析
- spring boot 自动配置与启动流程分析
SpringBoot 2.0 系列002 --运行流程分析(springboot的运行流程)
SpringBoot 2.0 系列002 --运行流程分析
SpringBoot 2.0 系列001 -- 入门介绍以及相关概念
1. SpringBoot运行的几种方式
1.1 开发环境,右键配置类main方法运行
配置如下,引入相关pom依赖,运行main方法即可启动简单的SpringBoot web应用。
//开启SpringBoot自动注入配置 等价于原来的SpringBootApplication @EnableAutoConfiguration //开启RestController注解 含有ResponseBody 即非页面形式 @RestController public class SpringBootApplication { @GetMapping("/") public String home() { return "Hello World!"; } /** * 开启SpringBoot服务 * @param args */ public static void main(String[] args) { //等价于 new SpringApplication(SpringBootApplication.class).run(args); SpringApplication.run(SpringBootApplication.class,args); } }
1.2 jar文件运行
其他部分与上述相同,需要注意的是pom文件需要加入
<plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins>
打包方式选择为jar
<packaging>jar</packaging>
最后mvn package打包 ,idea里面如下
运行方式1,如下
运行方式2,如下
D:\work\ideawork\SpringBootLearn\chapter02\target>java -jar chapter02-2.0.1.RELEASE.jar . ____ _ __ _ _ /\\ / ___''_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | ''_ | ''_| | ''_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) '' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.0.1.RELEASE) 2018-05-11 09:42:52.870 INFO 9720 --- [ main] com.ricky.SpringBootApplication : Starting SpringBootApplication v2.0.1.RELEASE on jsb-bgt with PID 9720 (D:\work\ideawork\SpringBootLearn\chapter02\target\chapter02-2.0.1.RELEASE.jar started by zdwljs in D:\work\ideawork\SpringBootLearn\chapter02\target) 2018-05-11 09:42:52.877 INFO 9720 --- [ main] com.ricky.SpringBootApplication : No active profile set, falling back to default profiles: default 2018-05-11 09:42:52.979 INFO 9720 --- [ main] ConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@5f8ed237: startup date [Fri May 11 09:42:52 CST 2018]; root of context hierarchy 2018-05-11 09:42:55.596 INFO 9720 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http) 2018-05-11 09:43:01.810 INFO 9720 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2018-05-11 09:43:01.811 INFO 9720 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.29 2018-05-11 09:43:01.827 INFO 9720 --- [ost-startStop-1] o.a.catalina.core.AprLifecycleListener : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [D:\Program Files\Java\jdk1.8.0_161\bin;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;d:\work\Git\cmd;C:\Program Files (x86)\MySQL\MySQL Server 5.5\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\Users\zdwljs\AppData\Local\Microsoft\WindowsApps;D:\Program Files\Java\jdk1.8.0_161\bin;;.] 2018-05-11 09:43:01.988 INFO 9720 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2018-05-11 09:43:01.991 INFO 9720 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 9018 ms 2018-05-11 09:43:02.238 INFO 9720 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Servlet dispatcherServlet mapped to [/] 2018-05-11 09:43:02.263 INFO 9720 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: ''characterEncodingFilter'' to: [/*] 2018-05-11 09:43:02.264 INFO 9720 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: ''hiddenHttpMethodFilter'' to: [/*] 2018-05-11 09:43:02.267 INFO 9720 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: ''httpPutFormContentFilter'' to: [/*] 2018-05-11 09:43:02.271 INFO 9720 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: ''requestContextFilter'' to: [/*] 2018-05-11 09:43:02.437 INFO 9720 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2018-05-11 09:43:02.877 INFO 9720 --- [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@5f8ed237: startup date [Fri May 11 09:42:52 CST 2018]; root of context hierarchy 2018-05-11 09:43:03.069 INFO 9720 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/],methods=[GET]}" onto public java.lang.String com.ricky.SpringBootApplication.home() 2018-05-11 09:43:03.079 INFO 9720 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest) 2018-05-11 09:43:03.083 INFO 9720 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) 2018-05-11 09:43:03.139 INFO 9720 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2018-05-11 09:43:03.140 INFO 9720 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2018-05-11 09:43:03.386 INFO 9720 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup 2018-05-11 09:43:03.457 INFO 9720 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '''' 2018-05-11 09:43:03.466 INFO 9720 --- [ main] com.ricky.SpringBootApplication : Started SpringBootApplication in 11.232 seconds (JVM running for 11.882)
通过ctrl-c可以退出
1.3 war包方式
1.3.1 war形式基本是使用外部tomcat,则需要将内置tomcat依赖过滤掉,且需要添加开发servlet依赖。
<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> <!--引入servlet支持--> <!--servlet依赖--> <!--httpServletRequest等相关文件--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <!--引入servlet支持结束-->
1.3.2 注意将打包方式改为war形式
<packaging>war</packaging>
1.3.3 两种加载方式
- 需要配置启动类 ,如下
继承SpringBootServletInitializer,重写configure方法。
//开启SpringBoot自动注入配置 等价于原来的SpringBootApplication @EnableAutoConfiguration //开启RestController注解 含有ResponseBody 即非页面形式 @RestController public class SpringBootApplicationServletInitializer extends SpringBootServletInitializer{ @GetMapping("/") public String home(HttpServletRequest request) { return "Hello World!"; } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return builder.sources(SpringBootApplicationServletInitializer.class); } }
- 另一种则是不需要继承SpringBootServletInitializer。保持与jar文件方式一致即可。 虽然也可以正常访问。但是application.yml中的配置不生效。需要通过其他方式进行参数配置。
1.3.3 打包运行
-
1、 mvn package打包,生成chapter02-2.0.1.RELEASE.war 文件。
-
2、将war文件放到webapp目录下
-
3、启动tomcat。(注意:测试发现是没有spring的日志,但是访问正常)
11-May-2018 11:53:34.687 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Server version: Apache Tomcat/8.5.29 11-May-2018 11:53:34.694 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Server built: Mar 5 2018 13:11:12 UTC 11-May-2018 11:53:34.697 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Server number: 8.5.29.0 11-May-2018 11:53:34.698 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name: Windows 10 11-May-2018 11:53:34.698 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log OS Version: 10.0 11-May-2018 11:53:34.698 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Architecture: amd64 11-May-2018 11:53:34.699 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Java Home: D:\Program Files\Java\jdk1.8.0_161\jre 11-May-2018 11:53:34.703 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version: 1.8.0_161-b12 11-May-2018 11:53:34.704 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Vendor: Oracle Corporation 11-May-2018 11:53:34.706 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE: D:\work\apache-tomcat-8.5.29 11-May-2018 11:53:34.708 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME: D:\work\apache-tomcat-8.5.29 11-May-2018 11:53:34.708 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.config.file=D:\work\apache-tomcat-8.5.29\conf\logging.properties 11-May-2018 11:53:34.709 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager 11-May-2018 11:53:34.710 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djdk.tls.ephemeralDHKeySize=2048 11-May-2018 11:53:34.714 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.protocol.handler.pkgs=org.apache.catalina.webresources 11-May-2018 11:53:34.718 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dignore.endorsed.dirs= 11-May-2018 11:53:34.723 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.base=D:\work\apache-tomcat-8.5.29 11-May-2018 11:53:34.725 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.home=D:\work\apache-tomcat-8.5.29 11-May-2018 11:53:34.731 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.io.tmpdir=D:\work\apache-tomcat-8.5.29\temp 11-May-2018 11:53:34.739 信息 [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent Loaded APR based Apache Tomcat Native library [1.2.16] using APR version [1.6.3]. 11-May-2018 11:53:34.740 信息 [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true]. 11-May-2018 11:53:34.741 信息 [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR/OpenSSL configuration: useAprConnector [false], useOpenSSL [true] 11-May-2018 11:53:35.865 信息 [main] org.apache.catalina.core.AprLifecycleListener.initializeSSL OpenSSL successfully initialized [OpenSSL 1.0.2m 2 Nov 2017] 11-May-2018 11:53:36.129 信息 [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["http-nio-8080"] 11-May-2018 11:53:36.509 信息 [main] org.apache.tomcat.util.net.NioSelectorPool.getSharedSelector Using a shared selector for servlet write/read 11-May-2018 11:53:36.519 信息 [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["ajp-nio-8009"] 11-May-2018 11:53:36.532 信息 [main] org.apache.tomcat.util.net.NioSelectorPool.getSharedSelector Using a shared selector for servlet write/read 11-May-2018 11:53:36.533 信息 [main] org.apache.catalina.startup.Catalina.load Initialization processed in 2548 ms 11-May-2018 11:53:36.584 信息 [main] org.apache.catalina.core.StandardService.startInternal Starting service [Catalina] 11-May-2018 11:53:36.584 信息 [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet Engine: Apache Tomcat/8.5.29 11-May-2018 11:53:36.629 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployWAR Deploying web application archive [D:\work\apache-tomcat-8.5.29\webapps\chapter02-2.0.1.RELEASE.war] 11-May-2018 11:53:40.555 信息 [localhost-startStop-1] org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time. 11-May-2018 11:53:41.025 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployWAR Deployment of web application archive [D:\work\apache-tomcat-8.5.29\webapps\chapter02-2.0.1.RELEASE.war] has finished in [4,393] ms 11-May-2018 11:53:41.148 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [D:\work\apache-tomcat-8.5.29\webapps\docs] 11-May-2018 11:53:41.258 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [D:\work\apache-tomcat-8.5.29\webapps\docs] has finished in [119] ms 11-May-2018 11:53:41.266 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [D:\work\apache-tomcat-8.5.29\webapps\examples] 11-May-2018 11:53:41.987 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [D:\work\apache-tomcat-8.5.29\webapps\examples] has finished in [721] ms 11-May-2018 11:53:42.048 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [D:\work\apache-tomcat-8.5.29\webapps\host-manager] 11-May-2018 11:53:42.114 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [D:\work\apache-tomcat-8.5.29\webapps\host-manager] has finished in [66] ms 11-May-2018 11:53:42.116 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [D:\work\apache-tomcat-8.5.29\webapps\manager] 11-May-2018 11:53:42.175 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [D:\work\apache-tomcat-8.5.29\webapps\manager] has finished in [59] ms 11-May-2018 11:53:42.176 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [D:\work\apache-tomcat-8.5.29\webapps\ROOT] 11-May-2018 11:53:42.240 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [D:\work\apache-tomcat-8.5.29\webapps\ROOT] has finished in [64] ms 11-May-2018 11:53:42.254 信息 [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"] 11-May-2018 11:53:42.274 信息 [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-nio-8009"] 11-May-2018 11:53:42.284 信息 [main] org.apache.catalina.startup.Catalina.start Server startup in 5749 ms
查看tomcat的App服务 http://localhost:8080/manager/html
-
4、点击chapter02-2.0.1.RELEASE访问 我们部署的项目。
2. SpringBoot是怎么运行起来的?
我们以jar文件方式为例进行讲解。
2.1 jar文件目录结构
- 切入jar文件所在目录,执行命令:
D:\work\xxxxx\SpringBootLearn\chapter02\target>jar tf chapter02-2.0.1.RELEASE.jar META-INF/ META-INF/MANIFEST.MF org/ org/springframework/ org/springframework/boot/ org/springframework/boot/loader/ org/springframework/boot/loader/util/ org/springframework/boot/loader/util/SystemPropertyUtils.class org/springframework/boot/loader/PropertiesLauncher$1.class org/springframework/boot/loader/PropertiesLauncher$PrefixMatchingArchiveFilter.class org/springframework/boot/loader/Launcher.class org/springframework/boot/loader/PropertiesLauncher$ArchiveEntryFilter.class org/springframework/boot/loader/PropertiesLauncher.class org/springframework/boot/loader/jar/ org/springframework/boot/loader/jar/JarURLConnection.class org/springframework/boot/loader/jar/JarURLConnection$1.class org/springframework/boot/loader/jar/Bytes.class org/springframework/boot/loader/jar/JarURLConnection$JarEntryName.class org/springframework/boot/loader/jar/JarFileEntries$1.class org/springframework/boot/loader/jar/JarEntry.class org/springframework/boot/loader/jar/JarFileEntries.class org/springframework/boot/loader/jar/JarEntryFilter.class org/springframework/boot/loader/jar/ZipInflaterInputStream.class org/springframework/boot/loader/jar/StringSequence.class org/springframework/boot/loader/jar/JarFile$1.class org/springframework/boot/loader/ExecutableArchiveLauncher.class org/springframework/boot/loader/archive/ org/springframework/boot/loader/archive/JarFileArchive$JarFileEntry.class org/springframework/boot/loader/archive/ExplodedArchive$FileEntryIterator.class org/springframework/boot/loader/archive/ExplodedArchive$FileEntry.class org/springframework/boot/loader/archive/ExplodedArchive.class org/springframework/boot/loader/archive/ExplodedArchive$1.class org/springframework/boot/loader/archive/JarFileArchive$EntryIterator.class org/springframework/boot/loader/archive/Archive$Entry.class org/springframework/boot/loader/archive/Archive.class org/springframework/boot/loader/archive/Archive$EntryFilter.class org/springframework/boot/loader/archive/ExplodedArchive$FileEntryIterator$EntryComparator.class org/springframework/boot/loader/archive/JarFileArchive.class org/springframework/boot/loader/data/ org/springframework/boot/loader/data/RandomAccessDataFile$FileAccess.class org/springframework/boot/loader/data/RandomAccessDataFile$DataInputStream.class org/springframework/boot/loader/JarLauncher.class org/springframework/boot/loader/jar/JarFile.class org/springframework/boot/loader/jar/CentralDirectoryParser.class org/springframework/boot/loader/jar/AsciiBytes.class org/springframework/boot/loader/jar/FileHeader.class org/springframework/boot/loader/jar/JarFile$JarFileType.class org/springframework/boot/loader/jar/Handler.class org/springframework/boot/loader/jar/JarFileEntries$EntryIterator.class org/springframework/boot/loader/jar/CentralDirectoryVisitor.class org/springframework/boot/loader/jar/CentralDirectoryEndRecord.class org/springframework/boot/loader/jar/CentralDirectoryFileHeader.class org/springframework/boot/loader/jar/JarFile$2.class org/springframework/boot/loader/LaunchedURLClassLoader.class org/springframework/boot/loader/MainMethodRunner.class org/springframework/boot/loader/data/RandomAccessDataFile.class org/springframework/boot/loader/WarLauncher.class org/springframework/boot/loader/data/RandomAccessDataFile$1.class org/springframework/boot/loader/data/RandomAccessData.class org/springframework/boot/loader/LaunchedURLClassLoader$UseFastConnectionExceptionsEnumeration.class BOOT-INF/ BOOT-INF/classes/ BOOT-INF/classes/com/ BOOT-INF/classes/com/ricky/ META-INF/maven/ META-INF/maven/chapter02/ META-INF/maven/chapter02/chapter02/ BOOT-INF/classes/com/ricky/SpringBootApplication.class META-INF/maven/chapter02/chapter02/pom.properties META-INF/maven/chapter02/chapter02/pom.xml BOOT-INF/lib/ BOOT-INF/lib/spring-boot-starter-web-2.0.1.RELEASE.jar BOOT-INF/lib/spring-boot-starter-2.0.1.RELEASE.jar BOOT-INF/lib/spring-boot-2.0.1.RELEASE.jar BOOT-INF/lib/spring-boot-autoconfigure-2.0.1.RELEASE.jar BOOT-INF/lib/spring-boot-starter-logging-2.0.1.RELEASE.jar BOOT-INF/lib/logback-classic-1.2.3.jar BOOT-INF/lib/logback-core-1.2.3.jar BOOT-INF/lib/slf4j-api-1.7.25.jar BOOT-INF/lib/log4j-to-slf4j-2.10.0.jar BOOT-INF/lib/log4j-api-2.10.0.jar BOOT-INF/lib/jul-to-slf4j-1.7.25.jar BOOT-INF/lib/javax.annotation-api-1.3.2.jar BOOT-INF/lib/spring-core-5.0.5.RELEASE.jar BOOT-INF/lib/spring-jcl-5.0.5.RELEASE.jar BOOT-INF/lib/snakeyaml-1.19.jar BOOT-INF/lib/spring-boot-starter-json-2.0.1.RELEASE.jar BOOT-INF/lib/jackson-databind-2.9.5.jar BOOT-INF/lib/jackson-annotations-2.9.0.jar BOOT-INF/lib/jackson-core-2.9.5.jar BOOT-INF/lib/jackson-datatype-jdk8-2.9.5.jar BOOT-INF/lib/jackson-datatype-jsr310-2.9.5.jar BOOT-INF/lib/jackson-module-parameter-names-2.9.5.jar BOOT-INF/lib/spring-boot-starter-tomcat-2.0.1.RELEASE.jar BOOT-INF/lib/tomcat-embed-core-8.5.29.jar BOOT-INF/lib/tomcat-embed-el-8.5.29.jar BOOT-INF/lib/tomcat-embed-websocket-8.5.29.jar BOOT-INF/lib/hibernate-validator-6.0.9.Final.jar BOOT-INF/lib/validation-api-2.0.1.Final.jar BOOT-INF/lib/jboss-logging-3.3.2.Final.jar BOOT-INF/lib/classmate-1.3.4.jar BOOT-INF/lib/spring-web-5.0.5.RELEASE.jar BOOT-INF/lib/spring-beans-5.0.5.RELEASE.jar BOOT-INF/lib/spring-webmvc-5.0.5.RELEASE.jar BOOT-INF/lib/spring-aop-5.0.5.RELEASE.jar BOOT-INF/lib/spring-context-5.0.5.RELEASE.jar BOOT-INF/lib/spring-expression-5.0.5.RELEASE.jar
- 打开MANIFEST.MF文件
Manifest-Version: 1.0 Implementation-Title: chapter01 Maven Webapp Implementation-Version: 2.0.1.RELEASE Built-By: zdwljs Implementation-Vendor-Id: chapter02 Spring-Boot-Version: 2.0.1.RELEASE Main-Class: org.springframework.boot.loader.JarLauncher Start-Class: com.ricky.SpringBootApplication Spring-Boot-Classes: BOOT-INF/classes/ Spring-Boot-Lib: BOOT-INF/lib/ Created-By: Apache Maven 3.3.9 Build-Jdk: 1.8.0_161 Implementation-URL: http://www.example.com
Start-class是我们的SpringBootApplication类,即jar文件方式启动 跟开发环境右键main方法运行方式一致
Main-Class则是JarLauncher。如果打包方式是war的话则是WarLauncher。此类工作内容是讲字节码文件加载到jvm中。
2.2 SpringBoot执行
由上述分析可知,com.ricky.SpringBootApplication是我们加载SB的入口。
- 入口
SpringApplication 的静态run方法。也可以手动new SpringApplication
SpringApplication.run(SpringBootApplication.class,args);
-
- 入口调用链1
/** * 调用run方法 返回ConfigurableApplicationContext对象 此对象用法在03章节做讲解 */ public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) { return run(new Class<?>[] { primarySource }, args); }
-
- 入口调用链1
/** * 此处有两步处理 * 1. 创建SpringApplication 对象 * 2. 执行该对象的run方法 */ public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) { return new SpringApplication(primarySources).run(args); }
-
创建SpringApplication 对象的过程
-
第一步 调用构造方法
//调用构造方法 public SpringApplication(Class<?>... primarySources) { this(null, primarySources); }
-
第2步 调用构造方法
//调用构造方法 public SpringApplication(Class<?>... primarySources) { this(null, primarySources); }
-
第3步 具体构造方法解析
//调用构造方法 public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { //默认resourceLoader 为null this.resourceLoader = resourceLoader; //校验primarySources不为空 Assert.notNull(primarySources, "PrimarySources must not be null"); //赋值primarySources集合对象 说明此处是可以传递多个.class对象 当我们的启动类不在同一级包中 // com.ricky/ricky02 我们的启动类在ricky中,默认是只扫描ricky包中的类,如果想扫描ricky02中 可以将需要扫描的类放到此处。 this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); //加载webApplicationType 对象 推断是web环境 还是非web环境 this.webApplicationType = deduceWebApplicationType(); //设置实例为ApplicationContextInitializer的Spring工厂实例 //可以通过spring.factories文件注入 继承自ApplicationContextInitializer的类 //也可以调用addInitializer方法手动注入 setInitializers((Collection) getSpringFactoriesInstances( ApplicationContextInitializer.class)); //注入ApplicationListener实例的监听 实现方式类似上边 通过文件或者add方法都可以 setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); // 通过堆栈里获取的方式,判断main函数,找到原始启动的main函数 this.mainApplicationClass = deduceMainApplicationClass(); }
-
第4步 run方法说明
//执行run方法 返回ConfigurableApplicationContext 对象 public ConfigurableApplicationContext run(String... args) { //开启执行时间记录器 StopWatch stopWatch = new StopWatch(); stopWatch.start(); //定义context ConfigurableApplicationContext context = null; //定义exceptionReporters Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); //设置java.awt.headless模式 主要是在缺少显示设备和键盘鼠标等下的支持 设置系统变量为true configureHeadlessProperty(); //根据传递的参数 加载spirng.factories中的SpringApplicationRunListener实例监听对象 SpringApplicationRunListeners listeners = getRunListeners(args); //启动监听 listeners.starting(); try { // 将传入的参数转换为ApplicationArguments格式 ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); // 根据applicationArguments准备基础环境变量 监听listeners变量 绑定到Spring中 //如果webApplicationType是0则做下转换处理 最后 attach做些检查判断处理 ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); // 从环境变量中检查和设置spring.beaninfo.ignore的状态 true或false configureIgnoreBeanInfo(environment); // 从环境变量中检查和设置banner.mode的模式 OFF时不打印 // 这部分是sb项目启动时显示几行springboot字符串头像 //自定义配置可参阅 SpringApplicationBannerPrinter Banner printedBanner = printBanner(environment); //创建应用上下文环境 检查是web环境还是默认环境等生成相对应环境 context = createApplicationContext(); // 从spring.factories中获取SpringBootExceptionReporter类型的实例 exceptionReporters = getSpringFactoriesInstances( SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context); //准备context // 参阅第五步 prepareContext(context, environment, listeners, applicationArguments, printedBanner); //刷新上下文context 注意根据ServletWeb和ReactiveWeb以及默认的applicationContext的不同来进行具体刷新 refreshContext(context); // 刷新后的操作 现在是保留方法 afterRefresh(context, applicationArguments); //结束执行时间记录器 stopWatch.stop(); // 是否开启启动日志 if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } // 发布事件 context.publishEvent(ApplicationStartedEvent) listeners.started(context); // 将ApplicationRunner和CommandLineRunner类型的回调处理 callRunners(context, applicationArguments); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, listeners); throw new IllegalStateException(ex); } try { // context.publishEvent(ApplicationReadyEvent) 发布监听 listeners.running(context); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, null); throw new IllegalStateException(ex); } return context; }
-
第5步 准备context
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { // 设置context环境变量 context.setEnvironment(environment); // 注册internalConfigurationBeanNameGenerator实例 setResourceLoader 或者setClassLoader postProcessApplicationContext(context); // 执行ApplicationContextInitializer.initialize方法 applyInitializers(context); // 设置监听上下文 listeners.contextPrepared(context); // 如果启动日志开的话 则启动日志实例 if (this.logStartupInfo) { logStartupInfo(context.getParent() == null); logStartupProfileInfo(context); } // Add boot specific singleton beans // 通过bean工厂注册springApplicationArguments的单例对象 context.getBeanFactory().registerSingleton("springApplicationArguments", applicationArguments); // 如果 printedBanner 不为空则通过bean工厂注册springBootBanner的单例对象 if (printedBanner != null) { context.getBeanFactory().registerSingleton("springBootBanner", printedBanner); } // Load the sources 加载sources Set<Object> sources = getAllSources(); Assert.notEmpty(sources, "Sources must not be empty"); //通过 createBeanDefinitionLoader方法 获取lBeanDefinitionLoader 并设置beanNameGenerator、environment、resourceLoader // 最后根据类型进行装载registerbean 常见的类型有xml ,annotation,package,resouces等等 最后返回bean数量 load(context, sources.toArray(new Object[0])); // 通过SimpleApplicationEventMulticaster的Executor 去invoke是ApplicationListener类型的listener // 循环执行listener.onApplicationEvent(event); listeners.contextLoaded(context); }
-
2.3 总结
通过分析,我们发现sb在启动的时候会校验执行环境(web或者其他),根据args传入参数的不同执行不同逻辑,同时扫描的方式有包类型、resource、注解、xml等(load方法装载bean实例)。 还可以根据spring.factories注入listener 、Initializers、event等等对象。
演示项目地址,欢迎fork和star
码云:SpringBootLearn
最后
- 作者ricky
- 交流群:244930845
001-快速搭建Spring web应用【springboot 2.0.4】-gradle、springboot的启动过程分析、gradle多模块构建
一、概述
学习《精通Spring MVC4》书籍笔记
二、笔记
1、快速构建Spring starter web项目几种方式
1》使用Spring Tool Suite生成Starter代码;sts是集成的eclipse工具,下载地址:https://spring.io/tools3/sts/all
2》使用 idea 14版本以上
3》使用站点:https://start.spring.io/ 配置后下载zip文件
4》使用https://start.spring.io/站点的curl命令
2、其他 gradle或maven,spring 4 ,java8 lambda,heroku,git
git:需要安装,git交互式教程:http://try.github.io/;git交互学习界面:https://learngitbranching.js.org/
gradle构建:Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建开源工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,抛弃了基于XML的各种繁琐配置。
mac上使用:参看官网即可:https://gradle.org/
1、安装java,检测java:javas -version
2、支持手动安装和包安装(推荐),手动的参看官网
brew install gradle
注:brew是一个软件包管理工具,类似于centos下的yum或者ubuntu下的apt-get,非常方便,免去了自己手动编译安装的不便
安装brew:/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
查看版本:gradle -v;配置idea路径:/usr/local/Cellar/gradle/5.1/libexec
3、可以基于上面的第4创建一个springboot项目,尝试使用gradle
gradle的dependencies
Configuration name | Role | Consumable? | Resolvable? | Description |
---|---|---|---|---|
|
Declaring API dependencies |
no |
no |
This is where you should declare dependencies which are transitively exported to consumers, for compile. |
|
Declaring implementation dependencies |
no |
no |
This is where you should declare dependencies which are purely internal and not meant to be exposed to consumers. 在这里,您应该声明纯粹内部的依赖关系,而不是要向消费者公开。 |
|
Declaring compile only dependencies |
yes |
yes |
This is where you should declare dependencies which are only required at compile time, but should not leak into the runtime. This typically includes dependencies which are shaded when found at runtime. 这是您应该声明仅在编译时需要的依赖项,但不应泄漏到运行时。这通常包括在运行时找到时被着色的依赖项。 |
|
Declaring runtime dependencies |
no |
no |
This is where you should declare dependencies which are only required at runtime, and not at compile time. |
|
Test dependencies |
no |
no |
This is where you should declare dependencies which are used to compile tests. |
|
Declaring test compile only dependencies |
yes |
yes |
This is where you should declare dependencies which are only required at test compile time, but should not leak into the runtime. This typically includes dependencies which are shaded when found at runtime. |
|
Declaring test runtime dependencies |
no |
no |
This is where you should declare dependencies which are only required at test runtime, and not at test compile time. |
参看地址:https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_separation
3、spring boot
3.1、spring mvc初始步骤
1》初始化Spring MVC的DIspatchServlet;
2》搭建转码过滤器,保证客户端请求进行正确地转码;
3》搭建视图解析器(View resolver),告诉Spring去哪里查找视图,以及他们是使用哪种前端模板编写的(jsp、thymeleaf、freemarker模板等)
4》配置静态资源的位置(css,js);
5》配置所支持的地域以及资源bundle;
6》配置multipart解析器,保证文件上传能够正常工作;
7》将tomcat或jetty包含进来,从而能够在we服务器上运行我们的应用
8》建立错误页面
spring boot主要是基于约定,默认会在项目中使用上述约定。
3.2、分发器和multipart配置
在application.properties中添加:
debug=true
查看在springboot启动时候究竟发生了什么


============================
CONDITIONS EVALUATION REPORT
============================
Positive matches:
-----------------
CodecsAutoConfiguration matched:
- @ConditionalOnClass found required class ''org.springframework.http.codec.CodecConfigurer''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
CodecsAutoConfiguration.JacksonCodecConfiguration matched:
- @ConditionalOnClass found required class ''com.fasterxml.jackson.databind.ObjectMapper''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
CodecsAutoConfiguration.JacksonCodecConfiguration#jacksonCodecCustomizer matched:
- @ConditionalOnBean (types: com.fasterxml.jackson.databind.ObjectMapper; SearchStrategy: all) found bean ''jacksonObjectMapper'' (OnBeanCondition)
DispatcherServletAutoConfiguration matched:
- @ConditionalOnClass found required class ''org.springframework.web.servlet.DispatcherServlet''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
- found ConfigurableWebEnvironment (OnWebApplicationCondition)
DispatcherServletAutoConfiguration.DispatcherServletConfiguration matched:
- @ConditionalOnClass found required class ''javax.servlet.ServletRegistration''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
- Default DispatcherServlet did not find dispatcher servlet beans (DispatcherServletAutoConfiguration.DefaultDispatcherServletCondition)
DispatcherServletAutoConfiguration.DispatcherServletRegistrationConfiguration matched:
- @ConditionalOnClass found required class ''javax.servlet.ServletRegistration''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
- DispatcherServlet Registration did not find servlet registration bean (DispatcherServletAutoConfiguration.DispatcherServletRegistrationCondition)
DispatcherServletAutoConfiguration.DispatcherServletRegistrationConfiguration#dispatcherServletRegistration matched:
- @ConditionalOnBean (names: dispatcherServlet; types: org.springframework.web.servlet.DispatcherServlet; SearchStrategy: all) found bean ''dispatcherServlet'' (OnBeanCondition)
EmbeddedWebServerFactoryCustomizerAutoConfiguration.TomcatWebServerFactoryCustomizerConfiguration matched:
- @ConditionalOnClass found required classes ''org.apache.catalina.startup.Tomcat'', ''org.apache.coyote.UpgradeProtocol''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
ErrorMvcAutoConfiguration matched:
- @ConditionalOnClass found required classes ''javax.servlet.Servlet'', ''org.springframework.web.servlet.DispatcherServlet''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
- found ConfigurableWebEnvironment (OnWebApplicationCondition)
ErrorMvcAutoConfiguration#basicErrorController matched:
- @ConditionalOnMissingBean (types: org.springframework.boot.web.servlet.error.ErrorController; SearchStrategy: current) did not find any beans (OnBeanCondition)
ErrorMvcAutoConfiguration#errorAttributes matched:
- @ConditionalOnMissingBean (types: org.springframework.boot.web.servlet.error.ErrorAttributes; SearchStrategy: current) did not find any beans (OnBeanCondition)
ErrorMvcAutoConfiguration.DefaultErrorViewResolverConfiguration#conventionErrorViewResolver matched:
- @ConditionalOnBean (types: org.springframework.web.servlet.DispatcherServlet; SearchStrategy: all) found bean ''dispatcherServlet''; @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.web.servlet.error.DefaultErrorViewResolver; SearchStrategy: all) did not find any beans (OnBeanCondition)
ErrorMvcAutoConfiguration.WhitelabelErrorViewConfiguration matched:
- @ConditionalOnProperty (server.error.whitelabel.enabled) matched (OnPropertyCondition)
- ErrorTemplate Missing did not find error template view (ErrorMvcAutoConfiguration.ErrorTemplateMissingCondition)
ErrorMvcAutoConfiguration.WhitelabelErrorViewConfiguration#beanNameViewResolver matched:
- @ConditionalOnMissingBean (types: org.springframework.web.servlet.view.BeanNameViewResolver; SearchStrategy: all) did not find any beans (OnBeanCondition)
ErrorMvcAutoConfiguration.WhitelabelErrorViewConfiguration#defaultErrorView matched:
- @ConditionalOnMissingBean (names: error; SearchStrategy: all) did not find any beans (OnBeanCondition)
GenericCacheConfiguration matched:
- Cache org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration automatic cache type (CacheCondition)
HttpEncodingAutoConfiguration matched:
- @ConditionalOnClass found required class ''org.springframework.web.filter.CharacterEncodingFilter''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
- found ConfigurableWebEnvironment (OnWebApplicationCondition)
- @ConditionalOnProperty (spring.http.encoding.enabled) matched (OnPropertyCondition)
HttpEncodingAutoConfiguration#characterEncodingFilter matched:
- @ConditionalOnMissingBean (types: org.springframework.web.filter.CharacterEncodingFilter; SearchStrategy: all) did not find any beans (OnBeanCondition)
HttpMessageConvertersAutoConfiguration matched:
- @ConditionalOnClass found required class ''org.springframework.http.converter.HttpMessageConverter''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
HttpMessageConvertersAutoConfiguration#messageConverters matched:
- @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.http.HttpMessageConverters; SearchStrategy: all) did not find any beans (OnBeanCondition)
HttpMessageConvertersAutoConfiguration.StringHttpMessageConverterConfiguration matched:
- @ConditionalOnClass found required class ''org.springframework.http.converter.StringHttpMessageConverter''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
HttpMessageConvertersAutoConfiguration.StringHttpMessageConverterConfiguration#stringHttpMessageConverter matched:
- @ConditionalOnMissingBean (types: org.springframework.http.converter.StringHttpMessageConverter; SearchStrategy: all) did not find any beans (OnBeanCondition)
JacksonAutoConfiguration matched:
- @ConditionalOnClass found required class ''com.fasterxml.jackson.databind.ObjectMapper''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
JacksonAutoConfiguration.Jackson2ObjectMapperBuilderCustomizerConfiguration matched:
- @ConditionalOnClass found required class ''org.springframework.http.converter.json.Jackson2ObjectMapperBuilder''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
JacksonAutoConfiguration.JacksonObjectMapperBuilderConfiguration matched:
- @ConditionalOnClass found required class ''org.springframework.http.converter.json.Jackson2ObjectMapperBuilder''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
JacksonAutoConfiguration.JacksonObjectMapperBuilderConfiguration#jacksonObjectMapperBuilder matched:
- @ConditionalOnMissingBean (types: org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; SearchStrategy: all) did not find any beans (OnBeanCondition)
JacksonAutoConfiguration.JacksonObjectMapperConfiguration matched:
- @ConditionalOnClass found required class ''org.springframework.http.converter.json.Jackson2ObjectMapperBuilder''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
JacksonAutoConfiguration.JacksonObjectMapperConfiguration#jacksonObjectMapper matched:
- @ConditionalOnMissingBean (types: com.fasterxml.jackson.databind.ObjectMapper; SearchStrategy: all) did not find any beans (OnBeanCondition)
JacksonAutoConfiguration.ParameterNamesModuleConfiguration matched:
- @ConditionalOnClass found required class ''com.fasterxml.jackson.module.paramnames.ParameterNamesModule''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
JacksonAutoConfiguration.ParameterNamesModuleConfiguration#parameterNamesModule matched:
- @ConditionalOnMissingBean (types: com.fasterxml.jackson.module.paramnames.ParameterNamesModule; SearchStrategy: all) did not find any beans (OnBeanCondition)
JacksonHttpMessageConvertersConfiguration.MappingJackson2HttpMessageConverterConfiguration matched:
- @ConditionalOnClass found required class ''com.fasterxml.jackson.databind.ObjectMapper''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
- @ConditionalOnProperty (spring.http.converters.preferred-json-mapper=jackson) matched (OnPropertyCondition)
- @ConditionalOnBean (types: com.fasterxml.jackson.databind.ObjectMapper; SearchStrategy: all) found bean ''jacksonObjectMapper'' (OnBeanCondition)
JacksonHttpMessageConvertersConfiguration.MappingJackson2HttpMessageConverterConfiguration#mappingJackson2HttpMessageConverter matched:
- @ConditionalOnMissingBean (types: org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; SearchStrategy: all) did not find any beans (OnBeanCondition)
JmxAutoConfiguration matched:
- @ConditionalOnClass found required class ''org.springframework.jmx.export.MBeanExporter''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
- @ConditionalOnProperty (spring.jmx.enabled=true) matched (OnPropertyCondition)
JmxAutoConfiguration#mbeanExporter matched:
- @ConditionalOnMissingBean (types: org.springframework.jmx.export.MBeanExporter; SearchStrategy: current) did not find any beans (OnBeanCondition)
JmxAutoConfiguration#mbeanServer matched:
- @ConditionalOnMissingBean (types: javax.management.MBeanServer; SearchStrategy: all) did not find any beans (OnBeanCondition)
JmxAutoConfiguration#objectNamingStrategy matched:
- @ConditionalOnMissingBean (types: org.springframework.jmx.export.naming.ObjectNamingStrategy; SearchStrategy: current) did not find any beans (OnBeanCondition)
MultipartAutoConfiguration matched:
- @ConditionalOnClass found required classes ''javax.servlet.Servlet'', ''org.springframework.web.multipart.support.StandardServletMultipartResolver'', ''javax.servlet.MultipartConfigElement''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
- found ConfigurableWebEnvironment (OnWebApplicationCondition)
- @ConditionalOnProperty (spring.servlet.multipart.enabled) matched (OnPropertyCondition)
MultipartAutoConfiguration#multipartConfigElement matched:
- @ConditionalOnMissingBean (types: javax.servlet.MultipartConfigElement,org.springframework.web.multipart.commons.CommonsMultipartResolver; SearchStrategy: all) did not find any beans (OnBeanCondition)
MultipartAutoConfiguration#multipartResolver matched:
- @ConditionalOnMissingBean (types: org.springframework.web.multipart.MultipartResolver; SearchStrategy: all) did not find any beans (OnBeanCondition)
NoOpCacheConfiguration matched:
- Cache org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration automatic cache type (CacheCondition)
PropertyPlaceholderAutoConfiguration#propertySourcesPlaceholderConfigurer matched:
- @ConditionalOnMissingBean (types: org.springframework.context.support.PropertySourcesPlaceholderConfigurer; SearchStrategy: current) did not find any beans (OnBeanCondition)
RestTemplateAutoConfiguration matched:
- @ConditionalOnClass found required class ''org.springframework.web.client.RestTemplate''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
RestTemplateAutoConfiguration#restTemplateBuilder matched:
- @ConditionalOnMissingBean (types: org.springframework.boot.web.client.RestTemplateBuilder; SearchStrategy: all) did not find any beans (OnBeanCondition)
ServletWebServerFactoryAutoConfiguration matched:
- @ConditionalOnClass found required class ''javax.servlet.ServletRequest''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
- found ConfigurableWebEnvironment (OnWebApplicationCondition)
ServletWebServerFactoryAutoConfiguration#tomcatServletWebServerFactoryCustomizer matched:
- @ConditionalOnClass found required class ''org.apache.catalina.startup.Tomcat''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
ServletWebServerFactoryConfiguration.EmbeddedTomcat matched:
- @ConditionalOnClass found required classes ''javax.servlet.Servlet'', ''org.apache.catalina.startup.Tomcat'', ''org.apache.coyote.UpgradeProtocol''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
- @ConditionalOnMissingBean (types: org.springframework.boot.web.servlet.server.ServletWebServerFactory; SearchStrategy: current) did not find any beans (OnBeanCondition)
SimpleCacheConfiguration matched:
- Cache org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration automatic cache type (CacheCondition)
SpringApplicationAdminJmxAutoConfiguration matched:
- @ConditionalOnProperty (spring.application.admin.enabled=true) matched (OnPropertyCondition)
SpringApplicationAdminJmxAutoConfiguration#springApplicationAdminRegistrar matched:
- @ConditionalOnMissingBean (types: org.springframework.boot.admin.SpringApplicationAdminMXBeanRegistrar; SearchStrategy: all) did not find any beans (OnBeanCondition)
ValidationAutoConfiguration matched:
- @ConditionalOnClass found required class ''javax.validation.executable.ExecutableValidator''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
- @ConditionalOnResource found location classpath:META-INF/services/javax.validation.spi.ValidationProvider (OnResourceCondition)
ValidationAutoConfiguration#defaultValidator matched:
- @ConditionalOnMissingBean (types: javax.validation.Validator; SearchStrategy: all) did not find any beans (OnBeanCondition)
ValidationAutoConfiguration#methodValidationPostProcessor matched:
- @ConditionalOnMissingBean (types: org.springframework.validation.beanvalidation.MethodValidationPostProcessor; SearchStrategy: all) did not find any beans (OnBeanCondition)
WebMvcAutoConfiguration matched:
- @ConditionalOnClass found required classes ''javax.servlet.Servlet'', ''org.springframework.web.servlet.DispatcherServlet'', ''org.springframework.web.servlet.config.annotation.WebMvcConfigurer''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
- found ConfigurableWebEnvironment (OnWebApplicationCondition)
- @ConditionalOnMissingBean (types: org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; SearchStrategy: all) did not find any beans (OnBeanCondition)
WebMvcAutoConfiguration#hiddenHttpMethodFilter matched:
- @ConditionalOnMissingBean (types: org.springframework.web.filter.HiddenHttpMethodFilter; SearchStrategy: all) did not find any beans (OnBeanCondition)
WebMvcAutoConfiguration#httpPutFormContentFilter matched:
- @ConditionalOnProperty (spring.mvc.formcontent.putfilter.enabled) matched (OnPropertyCondition)
- @ConditionalOnMissingBean (types: org.springframework.web.filter.HttpPutFormContentFilter; SearchStrategy: all) did not find any beans (OnBeanCondition)
WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter#defaultViewResolver matched:
- @ConditionalOnMissingBean (types: org.springframework.web.servlet.view.InternalResourceViewResolver; SearchStrategy: all) did not find any beans (OnBeanCondition)
WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter#requestContextFilter matched:
- @ConditionalOnMissingBean (types: org.springframework.web.context.request.RequestContextListener,org.springframework.web.filter.RequestContextFilter; SearchStrategy: all) did not find any beans (OnBeanCondition)
WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter#viewResolver matched:
- @ConditionalOnBean (types: org.springframework.web.servlet.ViewResolver; SearchStrategy: all) found beans ''defaultViewResolver'', ''beanNameViewResolver'', ''mvcViewResolver''; @ConditionalOnMissingBean (names: viewResolver; types: org.springframework.web.servlet.view.ContentNegotiatingViewResolver; SearchStrategy: all) did not find any beans (OnBeanCondition)
WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter.FaviconConfiguration matched:
- @ConditionalOnProperty (spring.mvc.favicon.enabled) matched (OnPropertyCondition)
WebSocketServletAutoConfiguration matched:
- @ConditionalOnClass found required classes ''javax.servlet.Servlet'', ''javax.websocket.server.ServerContainer''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
- found ConfigurableWebEnvironment (OnWebApplicationCondition)
WebSocketServletAutoConfiguration.TomcatWebSocketConfiguration matched:
- @ConditionalOnClass found required classes ''org.apache.catalina.startup.Tomcat'', ''org.apache.tomcat.websocket.server.WsSci''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
WebSocketServletAutoConfiguration.TomcatWebSocketConfiguration#websocketContainerCustomizer matched:
- @ConditionalOnMissingBean (names: websocketServletWebServerCustomizer; SearchStrategy: all) did not find any beans (OnBeanCondition)
Negative matches:
-----------------
ActiveMQAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''javax.jms.ConnectionFactory'', ''org.apache.activemq.ActiveMQConnectionFactory'' (OnClassCondition)
AopAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''org.aspectj.lang.annotation.Aspect'', ''org.aspectj.lang.reflect.Advice'', ''org.aspectj.weaver.AnnotatedElement'' (OnClassCondition)
ArtemisAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''javax.jms.ConnectionFactory'', ''org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory'' (OnClassCondition)
BatchAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''org.springframework.batch.core.launch.JobLauncher'', ''org.springframework.jdbc.core.JdbcOperations'' (OnClassCondition)
CacheAutoConfiguration:
Did not match:
- @ConditionalOnBean (types: org.springframework.cache.interceptor.CacheAspectSupport; SearchStrategy: all) did not find any beans of type org.springframework.cache.interceptor.CacheAspectSupport (OnBeanCondition)
Matched:
- @ConditionalOnClass found required class ''org.springframework.cache.CacheManager''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
CacheAutoConfiguration.CacheManagerJpaDependencyConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean'' (OnClassCondition)
- Ancestor org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration did not match (ConditionEvaluationReport.AncestorsMatchedCondition)
CaffeineCacheConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''com.github.benmanes.caffeine.cache.Caffeine'', ''org.springframework.cache.caffeine.CaffeineCacheManager'' (OnClassCondition)
CassandraAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''com.datastax.driver.core.Cluster'' (OnClassCondition)
CassandraDataAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''com.datastax.driver.core.Cluster'', ''org.springframework.data.cassandra.core.CassandraAdminOperations'' (OnClassCondition)
CassandraReactiveDataAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''com.datastax.driver.core.Cluster'', ''org.springframework.data.cassandra.core.ReactiveCassandraTemplate'', ''reactor.core.publisher.Flux'' (OnClassCondition)
CassandraReactiveRepositoriesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''org.springframework.data.cassandra.ReactiveSession'', ''org.springframework.data.cassandra.repository.ReactiveCassandraRepository'' (OnClassCondition)
CassandraRepositoriesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''com.datastax.driver.core.Session'', ''org.springframework.data.cassandra.repository.CassandraRepository'' (OnClassCondition)
CloudAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.cloud.config.java.CloudScanConfiguration'' (OnClassCondition)
CouchbaseAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''com.couchbase.client.java.CouchbaseBucket'', ''com.couchbase.client.java.Cluster'' (OnClassCondition)
CouchbaseCacheConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''com.couchbase.client.java.Bucket'', ''com.couchbase.client.spring.cache.CouchbaseCacheManager'' (OnClassCondition)
CouchbaseDataAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''com.couchbase.client.java.Bucket'', ''org.springframework.data.couchbase.repository.CouchbaseRepository'' (OnClassCondition)
CouchbaseReactiveDataAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''com.couchbase.client.java.Bucket'', ''org.springframework.data.couchbase.repository.ReactiveCouchbaseRepository'', ''reactor.core.publisher.Flux'' (OnClassCondition)
CouchbaseReactiveRepositoriesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''com.couchbase.client.java.Bucket'', ''org.springframework.data.couchbase.repository.ReactiveCouchbaseRepository'', ''reactor.core.publisher.Flux'' (OnClassCondition)
CouchbaseRepositoriesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''com.couchbase.client.java.Bucket'', ''org.springframework.data.couchbase.repository.CouchbaseRepository'' (OnClassCondition)
DataSourceAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType'' (OnClassCondition)
DataSourceTransactionManagerAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''org.springframework.jdbc.core.JdbcTemplate'', ''org.springframework.transaction.PlatformTransactionManager'' (OnClassCondition)
DispatcherServletAutoConfiguration.DispatcherServletConfiguration#multipartResolver:
Did not match:
- @ConditionalOnBean (types: org.springframework.web.multipart.MultipartResolver; SearchStrategy: all) did not find any beans of type org.springframework.web.multipart.MultipartResolver (OnBeanCondition)
EhCacheCacheConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''net.sf.ehcache.Cache'', ''org.springframework.cache.ehcache.EhCacheCacheManager'' (OnClassCondition)
ElasticsearchAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''org.elasticsearch.client.Client'', ''org.springframework.data.elasticsearch.client.TransportClientFactoryBean'' (OnClassCondition)
ElasticsearchDataAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''org.elasticsearch.client.Client'', ''org.springframework.data.elasticsearch.core.ElasticsearchTemplate'' (OnClassCondition)
ElasticsearchRepositoriesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''org.elasticsearch.client.Client'', ''org.springframework.data.elasticsearch.repository.ElasticsearchRepository'' (OnClassCondition)
EmbeddedLdapAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''com.unboundid.ldap.listener.InMemoryDirectoryServer'' (OnClassCondition)
EmbeddedMongoAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''com.mongodb.MongoClient'', ''de.flapdoodle.embed.mongo.MongodStarter'' (OnClassCondition)
EmbeddedWebServerFactoryCustomizerAutoConfiguration.JettyWebServerFactoryCustomizerConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''org.eclipse.jetty.server.Server'', ''org.eclipse.jetty.util.Loader'', ''org.eclipse.jetty.webapp.WebAppContext'' (OnClassCondition)
EmbeddedWebServerFactoryCustomizerAutoConfiguration.UndertowWebServerFactoryCustomizerConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''io.undertow.Undertow'', ''org.xnio.SslClientAuthMode'' (OnClassCondition)
ErrorWebFluxAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.web.reactive.config.WebFluxConfigurer'' (OnClassCondition)
FlywayAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.flywaydb.core.Flyway'' (OnClassCondition)
FreeMarkerAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''freemarker.template.Configuration'', ''org.springframework.ui.freemarker.FreeMarkerConfigurationFactory'' (OnClassCondition)
GroovyTemplateAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''groovy.text.markup.MarkupTemplateEngine'' (OnClassCondition)
GsonAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''com.google.gson.Gson'' (OnClassCondition)
GsonHttpMessageConvertersConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''com.google.gson.Gson'' (OnClassCondition)
H2ConsoleAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.h2.server.web.WebServlet'' (OnClassCondition)
HazelcastAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''com.hazelcast.core.HazelcastInstance'' (OnClassCondition)
HazelcastCacheConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''com.hazelcast.core.HazelcastInstance'', ''com.hazelcast.spring.cache.HazelcastCacheManager'' (OnClassCondition)
HazelcastJpaDependencyAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''com.hazelcast.core.HazelcastInstance'', ''org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean'' (OnClassCondition)
HibernateJpaAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean'', ''javax.persistence.EntityManager'' (OnClassCondition)
HttpHandlerAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.web.reactive.DispatcherHandler'' (OnClassCondition)
HypermediaAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''org.springframework.hateoas.Resource'', ''org.springframework.plugin.core.Plugin'' (OnClassCondition)
InfinispanCacheConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.infinispan.spring.provider.SpringEmbeddedCacheManager'' (OnClassCondition)
InfluxDbAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.influxdb.InfluxDB'' (OnClassCondition)
IntegrationAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.integration.config.EnableIntegration'' (OnClassCondition)
JCacheCacheConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''javax.cache.Caching'', ''org.springframework.cache.jcache.JCacheCacheManager'' (OnClassCondition)
JacksonAutoConfiguration.JodaDateTimeJacksonConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''org.joda.time.DateTime'', ''com.fasterxml.jackson.datatype.joda.ser.DateTimeSerializer'', ''com.fasterxml.jackson.datatype.joda.cfg.JacksonJodaDateFormat'' (OnClassCondition)
JacksonHttpMessageConvertersConfiguration.MappingJackson2XmlHttpMessageConverterConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''com.fasterxml.jackson.dataformat.xml.XmlMapper'' (OnClassCondition)
JdbcTemplateAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.jdbc.core.JdbcTemplate'' (OnClassCondition)
JerseyAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.glassfish.jersey.server.spring.SpringComponentProvider'' (OnClassCondition)
JestAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''io.searchbox.client.JestClient'' (OnClassCondition)
JmsAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''javax.jms.Message'', ''org.springframework.jms.core.JmsTemplate'' (OnClassCondition)
JndiConnectionFactoryAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.jms.core.JmsTemplate'' (OnClassCondition)
JndiDataSourceAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType'' (OnClassCondition)
JooqAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.jooq.DSLContext'' (OnClassCondition)
JpaRepositoriesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.data.jpa.repository.JpaRepository'' (OnClassCondition)
JsonbAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''javax.json.bind.Jsonb'' (OnClassCondition)
JsonbHttpMessageConvertersConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''javax.json.bind.Jsonb'' (OnClassCondition)
JtaAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''javax.transaction.Transaction'' (OnClassCondition)
KafkaAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.kafka.core.KafkaTemplate'' (OnClassCondition)
LdapAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.ldap.core.ContextSource'' (OnClassCondition)
LdapDataAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.data.ldap.repository.LdapRepository'' (OnClassCondition)
LdapRepositoriesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.data.ldap.repository.LdapRepository'' (OnClassCondition)
LiquibaseAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''liquibase.integration.spring.SpringLiquibase'', ''liquibase.change.DatabaseChange'' (OnClassCondition)
MailSenderAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''javax.mail.internet.MimeMessage'', ''org.springframework.mail.MailSender'' (OnClassCondition)
MailSenderValidatorAutoConfiguration:
Did not match:
- @ConditionalOnProperty (spring.mail.test-connection) did not find property ''test-connection'' (OnPropertyCondition)
MessageSourceAutoConfiguration:
Did not match:
- ResourceBundle did not find bundle with basename messages (MessageSourceAutoConfiguration.ResourceBundleCondition)
MongoAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''com.mongodb.MongoClient'' (OnClassCondition)
MongoDataAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''com.mongodb.MongoClient'', ''org.springframework.data.mongodb.core.MongoTemplate'' (OnClassCondition)
MongoReactiveAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''com.mongodb.reactivestreams.client.MongoClient'' (OnClassCondition)
MongoReactiveDataAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''com.mongodb.reactivestreams.client.MongoClient'', ''org.springframework.data.mongodb.core.ReactiveMongoTemplate'' (OnClassCondition)
MongoReactiveRepositoriesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''com.mongodb.reactivestreams.client.MongoClient'', ''org.springframework.data.mongodb.repository.ReactiveMongoRepository'' (OnClassCondition)
MongoRepositoriesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''com.mongodb.MongoClient'', ''org.springframework.data.mongodb.repository.MongoRepository'' (OnClassCondition)
MustacheAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''com.samskivert.mustache.Mustache'' (OnClassCondition)
Neo4jDataAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''org.neo4j.ogm.session.SessionFactory'', ''org.springframework.data.neo4j.transaction.Neo4jTransactionManager'', ''org.springframework.transaction.PlatformTransactionManager'' (OnClassCondition)
Neo4jRepositoriesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''org.neo4j.ogm.session.Neo4jSession'', ''org.springframework.data.neo4j.repository.Neo4jRepository'' (OnClassCondition)
OAuth2ClientAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''org.springframework.security.config.annotation.web.configuration.EnableWebSecurity'', ''org.springframework.security.oauth2.client.registration.ClientRegistration'' (OnClassCondition)
PersistenceExceptionTranslationAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor'' (OnClassCondition)
ProjectInfoAutoConfiguration#buildProperties:
Did not match:
- @ConditionalOnResource did not find resource ''${spring.info.build.location:classpath:META-INF/build-info.properties}'' (OnResourceCondition)
ProjectInfoAutoConfiguration#gitProperties:
Did not match:
- GitResource did not find git info at classpath:git.properties (ProjectInfoAutoConfiguration.GitResourceAvailableCondition)
QuartzAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''org.quartz.Scheduler'', ''org.springframework.scheduling.quartz.SchedulerFactoryBean'', ''org.springframework.transaction.PlatformTransactionManager'' (OnClassCondition)
RabbitAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''org.springframework.amqp.rabbit.core.RabbitTemplate'', ''com.rabbitmq.client.Channel'' (OnClassCondition)
ReactiveUserDetailsServiceAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.security.authentication.ReactiveAuthenticationManager'' (OnClassCondition)
ReactiveWebServerFactoryAutoConfiguration:
Did not match:
- not a reactive web application (OnWebApplicationCondition)
Matched:
- @ConditionalOnClass found required class ''org.springframework.http.ReactiveHttpInputMessage''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
ReactorCoreAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''reactor.core.publisher.Mono'', ''reactor.core.publisher.Flux'' (OnClassCondition)
RedisAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.data.redis.core.RedisOperations'' (OnClassCondition)
RedisCacheConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.data.redis.connection.RedisConnectionFactory'' (OnClassCondition)
RedisReactiveAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''org.springframework.data.redis.connection.ReactiveRedisConnectionFactory'', ''org.springframework.data.redis.core.ReactiveRedisTemplate'', ''reactor.core.publisher.Flux'' (OnClassCondition)
RedisRepositoriesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.data.redis.repository.configuration.EnableRedisRepositories'' (OnClassCondition)
RepositoryRestMvcAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration'' (OnClassCondition)
SecurityAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.security.authentication.DefaultAuthenticationEventPublisher'' (OnClassCondition)
SecurityFilterAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer'', ''org.springframework.security.config.http.SessionCreationPolicy'' (OnClassCondition)
SendGridAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''com.sendgrid.SendGrid'' (OnClassCondition)
ServletWebServerFactoryConfiguration.EmbeddedJetty:
Did not match:
- @ConditionalOnClass did not find required classes ''org.eclipse.jetty.server.Server'', ''org.eclipse.jetty.util.Loader'', ''org.eclipse.jetty.webapp.WebAppContext'' (OnClassCondition)
ServletWebServerFactoryConfiguration.EmbeddedUndertow:
Did not match:
- @ConditionalOnClass did not find required classes ''io.undertow.Undertow'', ''org.xnio.SslClientAuthMode'' (OnClassCondition)
SessionAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.session.Session'' (OnClassCondition)
SolrAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''org.apache.solr.client.solrj.impl.HttpSolrClient'', ''org.apache.solr.client.solrj.impl.CloudSolrClient'' (OnClassCondition)
SolrRepositoriesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''org.apache.solr.client.solrj.SolrClient'', ''org.springframework.data.solr.repository.SolrRepository'' (OnClassCondition)
SpringDataWebAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.data.web.PageableHandlerMethodArgumentResolver'' (OnClassCondition)
ThymeleafAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.thymeleaf.templatemode.TemplateMode'' (OnClassCondition)
TransactionAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.transaction.PlatformTransactionManager'' (OnClassCondition)
UserDetailsServiceAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.security.authentication.AuthenticationManager'' (OnClassCondition)
WebClientAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.web.reactive.function.client.WebClient'' (OnClassCondition)
WebFluxAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.web.reactive.config.WebFluxConfigurer'' (OnClassCondition)
WebFluxSecurityConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity'', ''org.springframework.security.web.server.WebFilterChainProxy'' (OnClassCondition)
WebMvcAutoConfiguration.ResourceChainCustomizerConfiguration:
Did not match:
- @ConditionalOnEnabledResourceChain did not find class org.webjars.WebJarAssetLocator (OnEnabledResourceChainCondition)
WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter#beanNameViewResolver:
Did not match:
- @ConditionalOnMissingBean (types: org.springframework.web.servlet.view.BeanNameViewResolver; SearchStrategy: all) found beans of type ''org.springframework.web.servlet.view.BeanNameViewResolver'' beanNameViewResolver (OnBeanCondition)
WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter#localeResolver:
Did not match:
- @ConditionalOnProperty (spring.mvc.locale) did not find property ''locale'' (OnPropertyCondition)
WebServicesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.ws.transport.http.MessageDispatcherServlet'' (OnClassCondition)
WebSocketMessagingAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer'' (OnClassCondition)
WebSocketReactiveAutoConfiguration:
Did not match:
- not a reactive web application (OnWebApplicationCondition)
Matched:
- @ConditionalOnClass found required classes ''javax.servlet.Servlet'', ''javax.websocket.server.ServerContainer''; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
WebSocketServletAutoConfiguration.JettyWebSocketConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer'' (OnClassCondition)
WebSocketServletAutoConfiguration.UndertowWebSocketConfiguration:
Did not match:
- @ConditionalOnClass did not find required class ''io.undertow.websockets.jsr.Bootstrap'' (OnClassCondition)
XADataSourceAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes ''javax.transaction.TransactionManager'', ''org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType'' (OnClassCondition)
Exclusions:
-----------
None
Unconditional classes:
----------------------
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration
此处便是Spring Boot的自动配置报告。主要分为两部分:1、匹配上的(postivie matches),列出了应用中,所有的自动配置;2、没有匹配的(negative matches),没有满足的自动匹配。
查看关键的自动配置:
3.2.1、DispatcherServletAutoConfiguration自动配置
源码:


/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.web.servlet;
import java.util.Arrays;
import java.util.List;
import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletRegistration;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionMessage.Style;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.servlet.DispatcherServlet;
/**
* {@link EnableAutoConfiguration Auto-configuration} for the Spring
* {@link DispatcherServlet}. Should work for a standalone application where an embedded
* web server is already present and also for a deployable application using
* {@link SpringBootServletInitializer}.
*
* @author Phillip Webb
* @author Dave Syer
* @author Stephane Nicoll
* @author Brian Clozel
*/
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass(DispatcherServlet.class)
@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)
@EnableConfigurationProperties(ServerProperties.class)
public class DispatcherServletAutoConfiguration {
/*
* The bean name for a DispatcherServlet that will be mapped to the root URL "/"
*/
public static final String DEFAULT_DISPATCHER_SERVLET_BEAN_NAME = "dispatcherServlet";
/*
* The bean name for a ServletRegistrationBean for the DispatcherServlet "/"
*/
public static final String DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME = "dispatcherServletRegistration";
@Configuration
@Conditional(DefaultDispatcherServletCondition.class)
@ConditionalOnClass(ServletRegistration.class)
@EnableConfigurationProperties(WebMvcProperties.class)
protected static class DispatcherServletConfiguration {
private final WebMvcProperties webMvcProperties;
public DispatcherServletConfiguration(WebMvcProperties webMvcProperties) {
this.webMvcProperties = webMvcProperties;
}
@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServlet dispatcherServlet() {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
dispatcherServlet.setDispatchOptionsRequest(
this.webMvcProperties.isDispatchOptionsRequest());
dispatcherServlet.setDispatchTraceRequest(
this.webMvcProperties.isDispatchTraceRequest());
dispatcherServlet.setThrowExceptionIfNoHandlerFound(
this.webMvcProperties.isThrowExceptionIfNoHandlerFound());
return dispatcherServlet;
}
@Bean
@ConditionalOnBean(MultipartResolver.class)
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
public MultipartResolver multipartResolver(MultipartResolver resolver) {
// Detect if the user has created a MultipartResolver but named it incorrectly
return resolver;
}
}
@Configuration
@Conditional(DispatcherServletRegistrationCondition.class)
@ConditionalOnClass(ServletRegistration.class)
@EnableConfigurationProperties(WebMvcProperties.class)
@Import(DispatcherServletConfiguration.class)
protected static class DispatcherServletRegistrationConfiguration {
private final ServerProperties serverProperties;
private final WebMvcProperties webMvcProperties;
private final MultipartConfigElement multipartConfig;
public DispatcherServletRegistrationConfiguration(
ServerProperties serverProperties, WebMvcProperties webMvcProperties,
ObjectProvider<MultipartConfigElement> multipartConfigProvider) {
this.serverProperties = serverProperties;
this.webMvcProperties = webMvcProperties;
this.multipartConfig = multipartConfigProvider.getIfAvailable();
}
@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.serverProperties.getServlet().getPath());
registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
registration.setLoadOnStartup(
this.webMvcProperties.getServlet().getLoadOnStartup());
if (this.multipartConfig != null) {
registration.setMultipartConfig(this.multipartConfig);
}
return registration;
}
}
@Order(Ordered.LOWEST_PRECEDENCE - 10)
private static class DefaultDispatcherServletCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage
.forCondition("Default DispatcherServlet");
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
List<String> dispatchServletBeans = Arrays.asList(beanFactory
.getBeanNamesForType(DispatcherServlet.class, false, false));
if (dispatchServletBeans.contains(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)) {
return ConditionOutcome.noMatch(message.found("dispatcher servlet bean")
.items(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME));
}
if (beanFactory.containsBean(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)) {
return ConditionOutcome
.noMatch(message.found("non dispatcher servlet bean")
.items(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME));
}
if (dispatchServletBeans.isEmpty()) {
return ConditionOutcome
.match(message.didNotFind("dispatcher servlet beans").atAll());
}
return ConditionOutcome.match(message
.found("dispatcher servlet bean", "dispatcher servlet beans")
.items(Style.QUOTE, dispatchServletBeans)
.append("and none is named " + DEFAULT_DISPATCHER_SERVLET_BEAN_NAME));
}
}
@Order(Ordered.LOWEST_PRECEDENCE - 10)
private static class DispatcherServletRegistrationCondition
extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
ConditionOutcome outcome = checkDefaultDispatcherName(beanFactory);
if (!outcome.isMatch()) {
return outcome;
}
return checkServletRegistration(beanFactory);
}
private ConditionOutcome checkDefaultDispatcherName(
ConfigurableListableBeanFactory beanFactory) {
List<String> servlets = Arrays.asList(beanFactory
.getBeanNamesForType(DispatcherServlet.class, false, false));
boolean containsDispatcherBean = beanFactory
.containsBean(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
if (containsDispatcherBean
&& !servlets.contains(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)) {
return ConditionOutcome
.noMatch(startMessage().found("non dispatcher servlet")
.items(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME));
}
return ConditionOutcome.match();
}
private ConditionOutcome checkServletRegistration(
ConfigurableListableBeanFactory beanFactory) {
ConditionMessage.Builder message = startMessage();
List<String> registrations = Arrays.asList(beanFactory
.getBeanNamesForType(ServletRegistrationBean.class, false, false));
boolean containsDispatcherRegistrationBean = beanFactory
.containsBean(DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME);
if (registrations.isEmpty()) {
if (containsDispatcherRegistrationBean) {
return ConditionOutcome
.noMatch(message.found("non servlet registration bean").items(
DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME));
}
return ConditionOutcome
.match(message.didNotFind("servlet registration bean").atAll());
}
if (registrations
.contains(DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)) {
return ConditionOutcome.noMatch(message.found("servlet registration bean")
.items(DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME));
}
if (containsDispatcherRegistrationBean) {
return ConditionOutcome
.noMatch(message.found("non servlet registration bean").items(
DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME));
}
return ConditionOutcome.match(message.found("servlet registration beans")
.items(Style.QUOTE, registrations).append("and none is named "
+ DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME));
}
private ConditionMessage.Builder startMessage() {
return ConditionMessage.forCondition("DispatcherServlet Registration");
}
}
}
是一个典型的Spring boot配置类。
使用了@Configuration注解
通过@AutoConfigureOrder注解来声明优先等级,需要优先进行配置
可以看到具体的分发器DispatcherSerlvet以及multipart解析器的配置
3.3、视图解析器、静态资源以及区域配置
WebMvcAutoConfiguration自动配置
源码


/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.web.servlet;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Optional;
import javax.servlet.Servlet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProviders;
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
import org.springframework.boot.autoconfigure.validation.ValidatorAdapter;
import org.springframework.boot.autoconfigure.web.ConditionalOnEnabledResourceChain;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.ResourceProperties.Strategy;
import org.springframework.boot.autoconfigure.web.format.WebConversionService;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.filter.OrderedHiddenHttpMethodFilter;
import org.springframework.boot.web.servlet.filter.OrderedHttpPutFormContentFilter;
import org.springframework.boot.web.servlet.filter.OrderedRequestContextFilter;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.GenericConverter;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.format.Formatter;
import org.springframework.format.FormatterRegistry;
import org.springframework.format.support.FormattingConversionService;
import org.springframework.http.CacheControl;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.util.ClassUtils;
import org.springframework.validation.DefaultMessageCodesResolver;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.accept.ContentNegotiationStrategy;
import org.springframework.web.accept.PathExtensionContentNegotiationStrategy;
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextListener;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.filter.HttpPutFormContentFilter;
import org.springframework.web.filter.RequestContextFilter;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceChainRegistration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
import org.springframework.web.servlet.i18n.FixedLocaleResolver;
import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.servlet.resource.AppCacheManifestTransformer;
import org.springframework.web.servlet.resource.GzipResourceResolver;
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler;
import org.springframework.web.servlet.resource.ResourceResolver;
import org.springframework.web.servlet.resource.VersionResourceResolver;
import org.springframework.web.servlet.view.BeanNameViewResolver;
import org.springframework.web.servlet.view.ContentNegotiatingViewResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
/**
* {@link EnableAutoConfiguration Auto-configuration} for {@link EnableWebMvc Web MVC}.
*
* @author Phillip Webb
* @author Dave Syer
* @author Andy Wilkinson
* @author Sébastien Deleuze
* @author Eddú Meléndez
* @author Stephane Nicoll
* @author Kristine Jetzke
* @author Bruce Brouwer
*/
@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 = { "/" };
@Bean
@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
return new OrderedHiddenHttpMethodFilter();
}
@Bean
@ConditionalOnMissingBean(HttpPutFormContentFilter.class)
@ConditionalOnProperty(prefix = "spring.mvc.formcontent.putfilter", name = "enabled", matchIfMissing = true)
public OrderedHttpPutFormContentFilter httpPutFormContentFilter() {
return new OrderedHttpPutFormContentFilter();
}
// Defined as a nested config to ensure WebMvcConfigurer is not read when not
// on the classpath
@Configuration
@Import(EnableWebMvcConfiguration.class)
@EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })
@Order(0)
public static class WebMvcAutoConfigurationAdapter
implements WebMvcConfigurer, ResourceLoaderAware {
private static final Log logger = LogFactory.getLog(WebMvcConfigurer.class);
private final ResourceProperties resourceProperties;
private final WebMvcProperties mvcProperties;
private final ListableBeanFactory beanFactory;
private final ObjectProvider<HttpMessageConverters> messageConvertersProvider;
final ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer;
private ResourceLoader resourceLoader;
public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties,
WebMvcProperties mvcProperties, ListableBeanFactory beanFactory,
ObjectProvider<HttpMessageConverters> messageConvertersProvider,
ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider) {
this.resourceProperties = resourceProperties;
this.mvcProperties = mvcProperties;
this.beanFactory = beanFactory;
this.messageConvertersProvider = messageConvertersProvider;
this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider
.getIfAvailable();
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
this.messageConvertersProvider.ifAvailable((customConverters) -> converters
.addAll(customConverters.getConverters()));
}
@Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
Duration timeout = this.mvcProperties.getAsync().getRequestTimeout();
if (timeout != null) {
configurer.setDefaultTimeout(timeout.toMillis());
}
}
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseSuffixPatternMatch(
this.mvcProperties.getPathmatch().isUseSuffixPattern());
configurer.setUseRegisteredSuffixPatternMatch(
this.mvcProperties.getPathmatch().isUseRegisteredSuffixPattern());
}
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
WebMvcProperties.Contentnegotiation contentnegotiation = this.mvcProperties
.getContentnegotiation();
configurer.favorPathExtension(contentnegotiation.isFavorPathExtension());
configurer.favorParameter(contentnegotiation.isFavorParameter());
if (contentnegotiation.getParameterName() != null) {
configurer.parameterName(contentnegotiation.getParameterName());
}
Map<String, MediaType> mediaTypes = this.mvcProperties.getContentnegotiation()
.getMediaTypes();
mediaTypes.forEach(configurer::mediaType);
}
@Bean
@ConditionalOnMissingBean
public InternalResourceViewResolver defaultViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix(this.mvcProperties.getView().getPrefix());
resolver.setSuffix(this.mvcProperties.getView().getSuffix());
return resolver;
}
@Bean
@ConditionalOnBean(View.class)
@ConditionalOnMissingBean
public BeanNameViewResolver beanNameViewResolver() {
BeanNameViewResolver resolver = new BeanNameViewResolver();
resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 10);
return resolver;
}
@Bean
@ConditionalOnBean(ViewResolver.class)
@ConditionalOnMissingBean(name = "viewResolver", value = ContentNegotiatingViewResolver.class)
public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {
ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
resolver.setContentNegotiationManager(
beanFactory.getBean(ContentNegotiationManager.class));
// ContentNegotiatingViewResolver uses all the other view resolvers to locate
// a view so it should have a high precedence
resolver.setOrder(Ordered.HIGHEST_PRECEDENCE);
return resolver;
}
@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;
}
@Override
public MessageCodesResolver getMessageCodesResolver() {
if (this.mvcProperties.getMessageCodesResolverFormat() != null) {
DefaultMessageCodesResolver resolver = new DefaultMessageCodesResolver();
resolver.setMessageCodeFormatter(
this.mvcProperties.getMessageCodesResolverFormat());
return resolver;
}
return null;
}
@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);
}
}
private <T> Collection<T> getBeansOfType(Class<T> type) {
return this.beanFactory.getBeansOfType(type).values();
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache()
.getCachecontrol().toHttpCacheControl();
if (!registry.hasMappingForPattern("/webjars/**")) {
customizeResourceHandlerRegistration(registry
.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/")
.setCachePeriod(getSeconds(cachePeriod))
.setCacheControl(cacheControl));
}
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
customizeResourceHandlerRegistration(
registry.addResourceHandler(staticPathPattern)
.addResourceLocations(getResourceLocations(
this.resourceProperties.getStaticLocations()))
.setCachePeriod(getSeconds(cachePeriod))
.setCacheControl(cacheControl));
}
}
private Integer getSeconds(Duration cachePeriod) {
return (cachePeriod != null) ? (int) cachePeriod.getSeconds() : null;
}
@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(
ApplicationContext applicationContext) {
return new WelcomePageHandlerMapping(
new TemplateAvailabilityProviders(applicationContext),
applicationContext, getWelcomePage(),
this.mvcProperties.getStaticPathPattern());
}
static String[] getResourceLocations(String[] staticLocations) {
String[] locations = new String[staticLocations.length
+ SERVLET_LOCATIONS.length];
System.arraycopy(staticLocations, 0, locations, 0, staticLocations.length);
System.arraycopy(SERVLET_LOCATIONS, 0, locations, staticLocations.length,
SERVLET_LOCATIONS.length);
return locations;
}
private Optional<Resource> getWelcomePage() {
String[] locations = getResourceLocations(
this.resourceProperties.getStaticLocations());
return Arrays.stream(locations).map(this::getIndexHtml)
.filter(this::isReadable).findFirst();
}
private Resource getIndexHtml(String location) {
return this.resourceLoader.getResource(location + "index.html");
}
private boolean isReadable(Resource resource) {
try {
return resource.exists() && (resource.getURL() != null);
}
catch (Exception ex) {
return false;
}
}
private void customizeResourceHandlerRegistration(
ResourceHandlerRegistration registration) {
if (this.resourceHandlerRegistrationCustomizer != null) {
this.resourceHandlerRegistrationCustomizer.customize(registration);
}
}
@Bean
@ConditionalOnMissingBean({ RequestContextListener.class,
RequestContextFilter.class })
public static RequestContextFilter requestContextFilter() {
return new OrderedRequestContextFilter();
}
@Configuration
@ConditionalOnProperty(value = "spring.mvc.favicon.enabled", matchIfMissing = true)
public static class FaviconConfiguration implements ResourceLoaderAware {
private final ResourceProperties resourceProperties;
private ResourceLoader resourceLoader;
public FaviconConfiguration(ResourceProperties resourceProperties) {
this.resourceProperties = resourceProperties;
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
@Bean
public SimpleUrlHandlerMapping faviconHandlerMapping() {
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
mapping.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);
mapping.setUrlMap(Collections.singletonMap("**/favicon.ico",
faviconRequestHandler()));
return mapping;
}
@Bean
public ResourceHttpRequestHandler faviconRequestHandler() {
ResourceHttpRequestHandler requestHandler = new ResourceHttpRequestHandler();
requestHandler.setLocations(resolveFaviconLocations());
return requestHandler;
}
private List<Resource> resolveFaviconLocations() {
String[] staticLocations = getResourceLocations(
this.resourceProperties.getStaticLocations());
List<Resource> locations = new ArrayList<>(staticLocations.length + 1);
Arrays.stream(staticLocations).map(this.resourceLoader::getResource)
.forEach(locations::add);
locations.add(new ClassPathResource("/"));
return Collections.unmodifiableList(locations);
}
}
}
/**
* Configuration equivalent to {@code @EnableWebMvc}.
*/
@Configuration
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration {
private final WebMvcProperties mvcProperties;
private final ListableBeanFactory beanFactory;
private final WebMvcRegistrations mvcRegistrations;
public EnableWebMvcConfiguration(
ObjectProvider<WebMvcProperties> mvcPropertiesProvider,
ObjectProvider<WebMvcRegistrations> mvcRegistrationsProvider,
ListableBeanFactory beanFactory) {
this.mvcProperties = mvcPropertiesProvider.getIfAvailable();
this.mvcRegistrations = mvcRegistrationsProvider.getIfUnique();
this.beanFactory = beanFactory;
}
@Bean
@Override
public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter();
adapter.setIgnoreDefaultModelOnRedirect(this.mvcProperties == null
|| this.mvcProperties.isIgnoreDefaultModelOnRedirect());
return adapter;
}
@Override
protected RequestMappingHandlerAdapter createRequestMappingHandlerAdapter() {
if (this.mvcRegistrations != null
&& this.mvcRegistrations.getRequestMappingHandlerAdapter() != null) {
return this.mvcRegistrations.getRequestMappingHandlerAdapter();
}
return super.createRequestMappingHandlerAdapter();
}
@Bean
@Primary
@Override
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
// Must be @Primary for MvcUriComponentsBuilder to work
return super.requestMappingHandlerMapping();
}
@Bean
@Override
public FormattingConversionService mvcConversionService() {
WebConversionService conversionService = new WebConversionService(
this.mvcProperties.getDateFormat());
addFormatters(conversionService);
return conversionService;
}
@Bean
@Override
public Validator mvcValidator() {
if (!ClassUtils.isPresent("javax.validation.Validator",
getClass().getClassLoader())) {
return super.mvcValidator();
}
return ValidatorAdapter.get(getApplicationContext(), getValidator());
}
@Override
protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
if (this.mvcRegistrations != null
&& this.mvcRegistrations.getRequestMappingHandlerMapping() != null) {
return this.mvcRegistrations.getRequestMappingHandlerMapping();
}
return super.createRequestMappingHandlerMapping();
}
@Override
protected ConfigurableWebBindingInitializer getConfigurableWebBindingInitializer() {
try {
return this.beanFactory.getBean(ConfigurableWebBindingInitializer.class);
}
catch (NoSuchBeanDefinitionException ex) {
return super.getConfigurableWebBindingInitializer();
}
}
@Override
protected ExceptionHandlerExceptionResolver createExceptionHandlerExceptionResolver() {
if (this.mvcRegistrations != null && this.mvcRegistrations
.getExceptionHandlerExceptionResolver() != null) {
return this.mvcRegistrations.getExceptionHandlerExceptionResolver();
}
return super.createExceptionHandlerExceptionResolver();
}
@Override
protected void configureHandlerExceptionResolvers(
List<HandlerExceptionResolver> exceptionResolvers) {
super.configureHandlerExceptionResolvers(exceptionResolvers);
if (exceptionResolvers.isEmpty()) {
addDefaultHandlerExceptionResolvers(exceptionResolvers);
}
if (this.mvcProperties.isLogResolvedException()) {
for (HandlerExceptionResolver resolver : exceptionResolvers) {
if (resolver instanceof AbstractHandlerExceptionResolver) {
((AbstractHandlerExceptionResolver) resolver)
.setWarnLogCategory(resolver.getClass().getName());
}
}
}
}
@Bean
@Override
public ContentNegotiationManager mvcContentNegotiationManager() {
ContentNegotiationManager manager = super.mvcContentNegotiationManager();
List<ContentNegotiationStrategy> strategies = manager.getStrategies();
ListIterator<ContentNegotiationStrategy> iterator = strategies.listIterator();
while (iterator.hasNext()) {
ContentNegotiationStrategy strategy = iterator.next();
if (strategy instanceof PathExtensionContentNegotiationStrategy) {
iterator.set(new OptionalPathExtensionContentNegotiationStrategy(
strategy));
}
}
return manager;
}
}
@Configuration
@ConditionalOnEnabledResourceChain
static class ResourceChainCustomizerConfiguration {
@Bean
public ResourceChainResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer() {
return new ResourceChainResourceHandlerRegistrationCustomizer();
}
}
interface ResourceHandlerRegistrationCustomizer {
void customize(ResourceHandlerRegistration registration);
}
private static class ResourceChainResourceHandlerRegistrationCustomizer
implements ResourceHandlerRegistrationCustomizer {
@Autowired
private ResourceProperties resourceProperties = new ResourceProperties();
@Override
public void customize(ResourceHandlerRegistration registration) {
ResourceProperties.Chain properties = this.resourceProperties.getChain();
configureResourceChain(properties,
registration.resourceChain(properties.isCache()));
}
private void configureResourceChain(ResourceProperties.Chain properties,
ResourceChainRegistration chain) {
Strategy strategy = properties.getStrategy();
if (strategy.getFixed().isEnabled() || strategy.getContent().isEnabled()) {
chain.addResolver(getVersionResourceResolver(strategy));
}
if (properties.isGzipped()) {
chain.addResolver(new GzipResourceResolver());
}
if (properties.isHtmlApplicationCache()) {
chain.addTransformer(new AppCacheManifestTransformer());
}
}
private ResourceResolver getVersionResourceResolver(
ResourceProperties.Strategy properties) {
VersionResourceResolver resolver = new VersionResourceResolver();
if (properties.getFixed().isEnabled()) {
String version = properties.getFixed().getVersion();
String[] paths = properties.getFixed().getPaths();
resolver.addFixedVersionStrategy(version, paths);
}
if (properties.getContent().isEnabled()) {
String[] paths = properties.getContent().getPaths();
resolver.addContentVersionStrategy(paths);
}
return resolver;
}
}
/**
* Decorator to make {@link PathExtensionContentNegotiationStrategy} optional
* depending on a request attribute.
*/
static class OptionalPathExtensionContentNegotiationStrategy
implements ContentNegotiationStrategy {
private static final String SKIP_ATTRIBUTE = PathExtensionContentNegotiationStrategy.class
.getName() + ".SKIP";
private final ContentNegotiationStrategy delegate;
OptionalPathExtensionContentNegotiationStrategy(
ContentNegotiationStrategy delegate) {
this.delegate = delegate;
}
@Override
public List<MediaType> resolveMediaTypes(NativeWebRequest webRequest)
throws HttpMediaTypeNotAcceptableException {
Object skip = webRequest.getAttribute(SKIP_ATTRIBUTE,
RequestAttributes.SCOPE_REQUEST);
if (skip != null && Boolean.parseBoolean(skip.toString())) {
return MEDIA_TYPE_ALL_LIST;
}
return this.delegate.resolveMediaTypes(webRequest);
}
}
}
视图解析:查看WebMvcAutoConfigurationAdapter中WebMvcProperties属性,可以看到,
spring.mvc.view.prefix=
spring.mvc.view.suffix=
静态资源:以及查看ResourceProperties,可以看到静态资源配置路径,任何一个位置即可。或者使用:spring.resources.static-locations=重新配置
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
"classpath:/META-INF/resources/", "classpath:/resources/",
"classpath:/static/", "classpath:/public/" };
静态资源:webjar默认
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache()
.getCachecontrol().toHttpCacheControl();
if (!registry.hasMappingForPattern("/webjars/**")) {
customizeResourceHandlerRegistration(registry
.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/")
.setCachePeriod(getSeconds(cachePeriod))
.setCacheControl(cacheControl));
}
对带有“ewbjar”前缀资源访问将会在类路径中解析,可以使用maven中央仓库预先打包好JavaScript依赖。
WebJars是jar包格式的客户端JavaScript库。
地域管理
@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;
}
默认只会处理一个地域,可以自定义:spring.mvc.locale
3.4、错误与转码配置
查看ErrorMvcAutoConfiguration源码


/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.web.servlet.error;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.Servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.framework.autoproxy.AutoProxyUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider;
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProviders;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPath;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.expression.MapAccessor;
import org.springframework.core.Ordered;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.view.BeanNameViewResolver;
import org.springframework.web.util.HtmlUtils;
/**
* {@link EnableAutoConfiguration Auto-configuration} to render errors via an MVC error
* controller.
*
* @author Dave Syer
* @author Andy Wilkinson
* @author Stephane Nicoll
*/
@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class })
// Load before the main WebMvcAutoConfiguration so that the error View is available
@AutoConfigureBefore(WebMvcAutoConfiguration.class)
@EnableConfigurationProperties({ ServerProperties.class, ResourceProperties.class })
public class ErrorMvcAutoConfiguration {
private final ServerProperties serverProperties;
private final DispatcherServletPath dispatcherServletPath;
private final List<ErrorViewResolver> errorViewResolvers;
public ErrorMvcAutoConfiguration(ServerProperties serverProperties,
DispatcherServletPath dispatcherServletPath,
ObjectProvider<List<ErrorViewResolver>> errorViewResolversProvider) {
this.serverProperties = serverProperties;
this.dispatcherServletPath = dispatcherServletPath;
this.errorViewResolvers = errorViewResolversProvider.getIfAvailable();
}
@Bean
@ConditionalOnMissingBean(value = ErrorAttributes.class, search = SearchStrategy.CURRENT)
public DefaultErrorAttributes errorAttributes() {
return new DefaultErrorAttributes(
this.serverProperties.getError().isIncludeException());
}
@Bean
@ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT)
public BasicErrorController basicErrorController(ErrorAttributes errorAttributes) {
return new BasicErrorController(errorAttributes, this.serverProperties.getError(),
this.errorViewResolvers);
}
@Bean
public ErrorPageCustomizer errorPageCustomizer() {
return new ErrorPageCustomizer(this.serverProperties, this.dispatcherServletPath);
}
@Bean
public static PreserveErrorControllerTargetClassPostProcessor preserveErrorControllerTargetClassPostProcessor() {
return new PreserveErrorControllerTargetClassPostProcessor();
}
@Configuration
static class DefaultErrorViewResolverConfiguration {
private final ApplicationContext applicationContext;
private final ResourceProperties resourceProperties;
DefaultErrorViewResolverConfiguration(ApplicationContext applicationContext,
ResourceProperties resourceProperties) {
this.applicationContext = applicationContext;
this.resourceProperties = resourceProperties;
}
@Bean
@ConditionalOnBean(DispatcherServlet.class)
@ConditionalOnMissingBean
public DefaultErrorViewResolver conventionErrorViewResolver() {
return new DefaultErrorViewResolver(this.applicationContext,
this.resourceProperties);
}
}
@Configuration
@ConditionalOnProperty(prefix = "server.error.whitelabel", name = "enabled", matchIfMissing = true)
@Conditional(ErrorTemplateMissingCondition.class)
protected static class WhitelabelErrorViewConfiguration {
private final SpelView defaultErrorView = new SpelView(
"<html><body><h1>Whitelabel Error Page</h1>"
+ "<p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p>"
+ "<div id=''created''>${timestamp}</div>"
+ "<div>There was an unexpected error (type=${error}, status=${status}).</div>"
+ "<div>${message}</div></body></html>");
@Bean(name = "error")
@ConditionalOnMissingBean(name = "error")
public View defaultErrorView() {
return this.defaultErrorView;
}
// If the user adds @EnableWebMvc then the bean name view resolver from
// WebMvcAutoConfiguration disappears, so add it back in to avoid disappointment.
@Bean
@ConditionalOnMissingBean
public BeanNameViewResolver beanNameViewResolver() {
BeanNameViewResolver resolver = new BeanNameViewResolver();
resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 10);
return resolver;
}
}
/**
* {@link SpringBootCondition} that matches when no error template view is detected.
*/
private static class ErrorTemplateMissingCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage
.forCondition("ErrorTemplate Missing");
TemplateAvailabilityProviders providers = new TemplateAvailabilityProviders(
context.getClassLoader());
TemplateAvailabilityProvider provider = providers.getProvider("error",
context.getEnvironment(), context.getClassLoader(),
context.getResourceLoader());
if (provider != null) {
return ConditionOutcome
.noMatch(message.foundExactly("template from " + provider));
}
return ConditionOutcome
.match(message.didNotFind("error template view").atAll());
}
}
/**
* Simple {@link View} implementation that resolves variables as SpEL expressions.
*/
private static class SpelView implements View {
private static final Log logger = LogFactory.getLog(SpelView.class);
private final NonRecursivePropertyPlaceholderHelper helper;
private final String template;
private volatile Map<String, Expression> expressions;
SpelView(String template) {
this.helper = new NonRecursivePropertyPlaceholderHelper("${", "}");
this.template = template;
}
@Override
public String getContentType() {
return "text/html";
}
@Override
public void render(Map<String, ?> model, HttpServletRequest request,
HttpServletResponse response) throws Exception {
if (response.isCommitted()) {
String message = getMessage(model);
logger.error(message);
return;
}
if (response.getContentType() == null) {
response.setContentType(getContentType());
}
PlaceholderResolver resolver = new ExpressionResolver(getExpressions(),
model);
String result = this.helper.replacePlaceholders(this.template, resolver);
response.getWriter().append(result);
}
private String getMessage(Map<String, ?> model) {
Object path = model.get("path");
String message = "Cannot render error page for request [" + path + "]";
if (model.get("message") != null) {
message += " and exception [" + model.get("message") + "]";
}
message += " as the response has already been committed.";
message += " As a result, the response may have the wrong status code.";
return message;
}
private Map<String, Expression> getExpressions() {
if (this.expressions == null) {
synchronized (this) {
ExpressionCollector expressionCollector = new ExpressionCollector();
this.helper.replacePlaceholders(this.template, expressionCollector);
this.expressions = expressionCollector.getExpressions();
}
}
return this.expressions;
}
}
/**
* {@link PlaceholderResolver} to collect placeholder expressions.
*/
private static class ExpressionCollector implements PlaceholderResolver {
private final SpelExpressionParser parser = new SpelExpressionParser();
private final Map<String, Expression> expressions = new HashMap<>();
@Override
public String resolvePlaceholder(String name) {
this.expressions.put(name, this.parser.parseExpression(name));
return null;
}
public Map<String, Expression> getExpressions() {
return Collections.unmodifiableMap(this.expressions);
}
}
/**
* SpEL based {@link PlaceholderResolver}.
*/
private static class ExpressionResolver implements PlaceholderResolver {
private final Map<String, Expression> expressions;
private final EvaluationContext context;
ExpressionResolver(Map<String, Expression> expressions, Map<String, ?> map) {
this.expressions = expressions;
this.context = getContext(map);
}
private EvaluationContext getContext(Map<String, ?> map) {
return SimpleEvaluationContext.forPropertyAccessors(new MapAccessor())
.withRootObject(map).build();
}
@Override
public String resolvePlaceholder(String placeholderName) {
Expression expression = this.expressions.get(placeholderName);
Object expressionValue = (expression != null)
? expression.getValue(this.context) : null;
return escape(expressionValue);
}
private String escape(Object value) {
return HtmlUtils.htmlEscape((value != null) ? value.toString() : null);
}
}
/**
* {@link WebServerFactoryCustomizer} that configures the server''s error pages.
*/
private static class ErrorPageCustomizer implements ErrorPageRegistrar, Ordered {
private final ServerProperties properties;
private final DispatcherServletPath dispatcherServletPath;
protected ErrorPageCustomizer(ServerProperties properties,
DispatcherServletPath dispatcherServletPath) {
this.properties = properties;
this.dispatcherServletPath = dispatcherServletPath;
}
@Override
public void registerErrorPages(ErrorPageRegistry errorPageRegistry) {
ErrorPage errorPage = new ErrorPage(this.dispatcherServletPath
.getRelativePath(this.properties.getError().getPath()));
errorPageRegistry.addErrorPages(errorPage);
}
@Override
public int getOrder() {
return 0;
}
}
/**
* {@link BeanFactoryPostProcessor} to ensure that the target class of ErrorController
* MVC beans are preserved when using AOP.
*/
static class PreserveErrorControllerTargetClassPostProcessor
implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
String[] errorControllerBeans = beanFactory
.getBeanNamesForType(ErrorController.class, false, false);
for (String errorControllerBean : errorControllerBeans) {
try {
beanFactory.getBeanDefinition(errorControllerBean).setAttribute(
AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
}
catch (Throwable ex) {
// Ignore
}
}
}
}
}
定义了一个Bean,即DefaultErrorAttributes,他通过特定的属性暴露了有用的错误信息,这些属性包括状态、错误码和相关的栈跟踪信息
定义了一个BasicErrorController的bean,负责展示错误页。
允许我们将spring boot的whitelabel错误页设置为无效,server.error.whitelabel.enabled=false
还可以以借助模板引擎提供自己的错误页面。他的名字是error.html,ErrorTemplateMissingCondition条件会对此进行检查。
转码:HttpEncodingAutoConfiguration,他是通过Spring的CharacterEncodingFilter类实现,通过spring.http.encoding.charset=UTF-8;配置。如果禁用:spring.http.encoding.enabled=false
3.5、嵌入式Servlet容器配置
查看:EmbeddedWebServerFactoryCustomizerAutoConfiguration代码:


/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.web.embedded;
import io.undertow.Undertow;
import org.apache.catalina.startup.Tomcat;
import org.apache.coyote.UpgradeProtocol;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.webapp.WebAppContext;
import org.xnio.SslClientAuthMode;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
/**
* {@link EnableAutoConfiguration Auto-configuration} for embedded servlet and reactive
* web servers customizations.
*
* @author Phillip Webb
* @since 2.0.0
*/
@Configuration
@EnableConfigurationProperties(ServerProperties.class)
public class EmbeddedWebServerFactoryCustomizerAutoConfiguration {
@ConditionalOnClass({ Tomcat.class, UpgradeProtocol.class })
public static class TomcatWebServerFactoryCustomizerConfiguration {
@Bean
public TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer(
Environment environment, ServerProperties serverProperties) {
return new TomcatWebServerFactoryCustomizer(environment, serverProperties);
}
}
/**
* Nested configuration if Jetty is being used.
*/
@Configuration
@ConditionalOnClass({ Server.class, Loader.class, WebAppContext.class })
public static class JettyWebServerFactoryCustomizerConfiguration {
@Bean
public JettyWebServerFactoryCustomizer jettyWebServerFactoryCustomizer(
Environment environment, ServerProperties serverProperties) {
return new JettyWebServerFactoryCustomizer(environment, serverProperties);
}
}
/**
* Nested configuration if Undertow is being used.
*/
@Configuration
@ConditionalOnClass({ Undertow.class, SslClientAuthMode.class })
public static class UndertowWebServerFactoryCustomizerConfiguration {
@Bean
public UndertowWebServerFactoryCustomizer undertowWebServerFactoryCustomizer(
Environment environment, ServerProperties serverProperties) {
return new UndertowWebServerFactoryCustomizer(environment, serverProperties);
}
}
}
可以看待spring-boot默认支持tomcat,tc-server,Jetty,Undertow web容器。
3.5.1、http端口
使用:server.port=8080配置,-1禁用http,0随机端口启动应用,便于测试
3.5.2、ssl配置
server.port=8443
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password=secret
server.ssl.key-password=another-secret
3.5.3、其他配置
在JacksonAutoConfiguration中,声明使用Jackson进行json序列化
在HttpMessageConvertersAutoConfiguration中,声明了默认的HttpMessageConverter;
在JmxAutoConfiguration中,声明了JMX功能。
禁用spring.jmx.enabled=false
四、gradle构建多模块项目
1、可以使用工具或者命令创建
mkdir springboot-mm
cd springboot-mm
gradle init
目录结构:
修改gradleParent的相关配置
settings.gradle
rootProject.name = ''gradle-mvc4''
include ''demo01-thymeleaf''
build.gradle
allprojects {
ext {
springBootVersion = ''2.0.7.RELEASE''
}
apply plugin: ''java''
apply plugin: ''idea''
// JVM 版本号要求
sourceCompatibility = 1.8
targetCompatibility = 1.8
group = ''com.github.bjlhx15.gradle''
version = ''0.0.1-SNAPSHOT''
// java编译的时候缺省状态下会因为中文字符而失败
[compileJava,compileTestJava,javadoc]*.options*.encoding = ''UTF-8''
repositories {
mavenCentral()
}
dependencies {
implementation ''org.springframework.boot:spring-boot-starter-web''
compile group: ''org.springframework.boot'', name: ''spring-boot-starter-thymeleaf'', version: ''2.0.7.RELEASE''
testImplementation ''org.springframework.boot:spring-boot-starter-test''
}
}
子项目build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: ''org.springframework.boot''
apply plugin: ''io.spring.dependency-management''
archivesBaseName = ''demo01-thymeleaf''
代码参看:https://github.com/bjlhx15/gradle-mvc4
16. SpringBoot自动配置流程分析
背景分析
我们在搭建项目的时候,需要用到很多很多的冗余的配置文件,当我们的ide如果是IntelliJ IDEA还好,因为有强大的代码提示,但是如果ide是eclipse或者myeclipse,很可能会被这些配置文件搞得很惨,当然,大牛除外,当然,也可能只是我自己的问题哈。那么此时,Spring公司出了一款专门用于集成项目的框架SpringBoot,而这款框架对我来说哈,牛逼之处就在于各种自动配置,帮我们解决了前端控制器、视图解析器等一系列的配置文件,不需要自己再去做配置。
此时,我们只需要写一个Java类,在类上写一个注解,就可以全部都实现。
思路分析
首先我们在主配置文件上面会加一个注解
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
那么此时我们跟进到@SpringBootApplication
这个注解上方有一个@EnableAutoConfiguration
的注解
这个注解,手动狗头翻译过来的意思应该是:“使能够自动配置”,好吧,那我们又继续往里面走
此时进入到了“使能够自动配置”的注解里面,那么我们可以发现,它的上方,导入了一个class文件,又来手动狗头翻译:“自动配置导入选择器”,看起来有点儿像那么回事了哈,然后我们继续跟进进去,,此时,我们全靠猜,可能进行不通了,像我这种菜鸟,近500行的源码,看起来还是比较吃力的,于是,好吧,我们此时在这个类里面的搜索
spring.factories
,然后会找到一个getCandidateConfigurations
方法,
那么这个时候我们看这个方法的注释大致意思可以发现,它会返回一个自动配置的类名,其实我们会发现这个方法里面会通过Spring工厂加载器和加载工厂名去根据bean的类加载器和Spring工厂类加载器去获取一个配置的集合,然后再去断言获取到的配置不为空就执行这些配置,如果为空,就抛出一个没找到的信息,请注意这里的没找到,我们再细看,它会从spring.factories
里面去找,那么现在我们就又有线索了,于是可以按两下Shift,然后找这个文件
此时会发现,根本什么都没有,请不要气急败坏,先把你的右上角Include non-project items
选中,就会出现和我如下图片一样多的选择,此时,不要乱点,切记,只选正确的,我已经框起来的了,要注意路径
然后我们进去之后,就会发现,这就是一个spring自己的配置文件,并且,有一个大大的自动配置字样
这里,其实就是spring将所有的自动配置文件都加载到这里,我们以视图解析器为例来看一下,此时,我们会发现根本就找不到InternalResourceViewResolver
,注意注意,不要慌张,既然springboot要整合,那肯定要重写这个类嘛,就像我们写拦截器什么的,都会根据自己的需求来写具体的代码,springboot也是一样,我们可以搜ThymeleafTemplateAvailabilityProvider
,为什么要搜这个呢?因为springboot用的模板技术是Thymeleaf
,SSM里面用的是jsp技术,这个是不一样的地方,所以springboot的视图解析器命名也是根据Thymeleaf
来的,此时,我们进入这个类里面可以看到
默认的前后缀,然后再进入ThymeleafProperties
类可以看到具体的前后缀了
结语
到这里,基本也就结束了,像SSM需要我们手动配置的前端控制器、之类的,都在这里面,内容不一样,但是原理都是一样的。谨以此文献给我自己,以及需要的人,哈哈哈哈
ps:写得不好,少喷将就看
spring boot http接口单元测试运行流程分析
先粘贴一下test方法截图
测试类启动过程:
HandlerMappingIntrospector的initHandlerMappings()具体逻辑如下:
private static List<HandlerMapping> initHandlerMappings(ApplicationContext applicationContext) {
Map<String, HandlerMapping> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
applicationContext, HandlerMapping.class, true, false);
if (!beans.isEmpty()) {
List<HandlerMapping> mappings = new ArrayList<>(beans.values());
AnnotationAwareOrderComparator.sort(mappings);
return Collections.unmodifiableList(mappings);
}
return Collections.unmodifiableList(initFallback(applicationContext));
}
可以看到beans的数量为8,此时HandlerMappingIntrospector.handlerMappings属性值已经被赋值了。
private void filterAndRecordMetrics(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
Object handler;
try {
handler = getHandler(request);//1
}
catch (Exception ex) {
logger.debug("Unable to time request", ex);
filterChain.doFilter(request, response);
return;
}
//
filterAndRecordMetrics(request, response, filterChain, handler);
}
第1处获取HandlerMethod;第2处,继续执行doFilter()方法,最终在MockFilterChain.doFilter()执行到DispatcherServlet.doDispatch(request, response);
其中mappedHandler = getHandler(processedRequest);获取HandlerExecutionChain。
Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
在上面codwe块中获取合适的HandlerAdapter。
中根据mappedHandler得到HandlerMethod
中依据HandlerMethod利用反射技术去调用目标类,获得返回值。
spring boot 自动配置与启动流程分析
spring boot 自动配置与启动流程分析
http://blog.csdn.net/doctor_who2004/article/details/79208966
今天的关于SpringBoot 2.0 系列002 --运行流程分析和springboot的运行流程的分享已经结束,谢谢您的关注,如果想了解更多关于001-快速搭建Spring web应用【springboot 2.0.4】-gradle、springboot的启动过程分析、gradle多模块构建、16. SpringBoot自动配置流程分析、spring boot http接口单元测试运行流程分析、spring boot 自动配置与启动流程分析的相关知识,请在本站进行查询。
本文标签: