总得来说:SpringBoot启动时,根据主程序入口的类类型来创建相应的容器,然后刷新容器refresh()(创建各种bean对象),此时也是创建嵌入式容器的。相关容器的子类实现类中,onRefresh方法实现了(方法中调用this.createWebServer()来创建并返回ServletWebServerFactory,再根据工厂来获取嵌入式容器)
ServletWebServerFactory factory = this.getWebServerFactory(); //内部其实就是从IOC容器中获取这个组件IOC容器启动的时候会创建嵌入式容器
深入看看创建容器(createApplicationContext),简化
protected ConfigurableApplicationContext createApplicationContext() { Class<?> contextClass = this.applicationContextClass; switch (this.webApplicationType) { case SERVLET: contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext"); break; case REACTIVE: contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext"); break; default: contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext"); } } return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass); }15. 使用外置的Servlet容器
嵌入式简单便捷、优化定制比较复杂,使用定制器或properties等来改变
外置的Serlvlet容器:外面安装Tomcat服务器--应用打包war包打包
必须创建war包
将嵌入式Tomcat指定为provided
必须编写一个ServletInitializer,并调用configure方法
启动服务器
外置Servlet容器的启动原理,
jar包:执行Spring主类的main方法,启动IOC容器,过程中创建Servlet容器
war包:启动服务器,服务器启动Springboot应用(ServletInitializer),接着上面的流程
servlet3.0中有个规范:
规则:
服务器启动会创建当前web应用里面每一个jar包里面的ServlerConttaininerInitializer实例
ServlerConttaininerInitializer的实现放在jar包的META-INF/services文件夹下,有个文件内容是指向ServlerConttaininerInitializer的实现类的全限定类名
使用注解@handlesTypes,在应用启动的时候加载我们感兴趣的类
流程
1)启动Tomcat
2)按照规则就会去创建jar下的实例,规则1
3)ServlerConttaininerInitializer将注解标注的类创建实例
4)每一个SpringBootServletInitializer就是多出来的ServletInitializer类的父类被创建,然后调用configure方法,其参数是主程序类,内部使用builder创建Spring应用最后run启动了
16. SpringBoot与数据访问
导入依赖
整合基本JDBC,在主配置文件中加入即可,默认使用class com.zaxxer.hikari.HikariDataSource数据源
spring.datasource.username=root spring.datasource.password= spring.datasource.url=jdbc:mysql://localhost:3306/test spring.datasource.driver-class-name=com.mysql.jdbc.Driver自动配置包下jdbc.DataSourceConfiguration中,默认支持:dbcp2、hikari、tomcat。还可以看到一个属性:spring.datasource.type
17. 整合druid数据源
引入依赖
<!-- https://mvnrepository.com/artifact/com.alibaba/druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.21</version> </dependency> <!-- 德鲁伊依赖log4j我有什么办法 --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>配置数据源具体数值
spring: datasource: username: root password: url: jdbc:mysql://127.0.0.1:3306/spring?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useAffectedRows=true driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource maxActive: 20 initialSize: 1 maxWait: 60000 minIdle: 1 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 30000 testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true maxOpenPreparedStatements: 20 filters: stat,wall,log4j因为自己加的druid是第三方数据源,所以要自己配置上去
@Configuration public class DruidConfig { @Bean @ConfigurationProperties(prefix = "spring.datasource") public DataSource druid() { return new DruidDataSource(); } // 配置监控 // 1.配置管理后台的Servlet // 2.配置一个监控的filter @Bean public ServletRegistrationBean statViewServlet(){ ServletRegistrationBean bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*"); Map<String,String> map = new HashMap<>(); map.put("loginUsername", "root"); map.put("loginPassword", "root"); map.put("allwo",""); bean.setInitParameters(map); return bean; } @Bean public FilterRegistrationBean WebStatFilter(){ FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<>(new WebStatFilter()); Map<String,String> map = new HashMap<>(); map.put("exclusions","*.js,*.css,/druid/*"); bean.setUrlPatterns(Arrays.asList("/*")); bean.setInitParameters(map); return bean; } }18. 整合Mybatis