六、配置嵌入式servlet
SpringBoot默认使用tomcat作为嵌入式的servlet容器;
发现在Spring Boot2.0以上配置嵌入式Servlet容器时EmbeddedServletContainerCustomizer类被WebServerFactoryCustomizer替代
/**
* 配置嵌入式的servlet容器
* @return
*/
@Bean
public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer(){
return new WebServerFactoryCustomizer<ConfigurableWebServerFactory>() {
//定制嵌入式的servlet容器相关的规则
@Override
public void customize(ConfigurableWebServerFactory factory) {
factory.setPort(8083);
}
};
}
6.1需要考虑的问题?
6.2如何定制和修改servlet容器的相关配置;
(一)、修改和server有关的配置(ServerProperties)
server.port=8081
server.context-path=/crud
server.tomcat.uri-encoding=utf-8
//通用的servlet容器设置
server.xxx
//Tomcat的设置
server.tomcat.xxx
(二)、编写一个EmbeddedServletContainerCustomizer;嵌入式的servlet容器的定制器;
6.3注册Servlet三大组件【Servlet、Filter、Listener】
由于Springboot默认是以jar包的方式启动嵌入式的servlet容器来启动Springboot的web应用,没有web.xml文件;
注册三大组件用以下方式:
ServletRegistrationBean
@Bean
public ServletRegistrationBean myServlet(){
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new MyServlet(),"/myServlet");
return registrationBean;
}
FilterRegistrationBean
@Bean
public FilterRegistrationBean myFilter(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new MyFilter());
bean.setUrlPatterns(Arrays.asList("/hello","/myServlet"));
return bean;
}
ServletListenerRegistrationBean
@Bean
public ServletListenerRegistrationBean myListener(){
ServletListenerRegistrationBean<MyListener> bean = new ServletListenerRegistrationBean<>(new MyListener());
return bean;
}
springboot帮助我们自动SpringMVC的时候,自动的注册SpringMVC前端控制器,DispatcherServlet;
@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
@ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet,
WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) {
DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet,
webMvcProperties.getServlet().getPath());
//默认拦截。/所有请求:包含静态资源 但是不拦截jsp请求; /*会拦截jsp
//可以通过server.servletPath来修改SpringMVC前端控制器默认拦截的请求路径
registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());
multipartConfig.ifAvailable(registration::setMultipartConfig);
return registration;
}
6.4使用其他Servlet容器
Tomcat(默认使用)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
//引入web模块默认就是使用嵌入式的tomcat作为servlet容器
</dependency>
Jetty(长连接)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--导入配置文件处理器,配置文件进行绑定就会有提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!--引入其他的servlet-->
<dependency>
<artifactId>spring-boot-starter-jetty</artifactId>
<groupId>org.springframework.boot</groupId>
</dependency>
Undertow
<!--引入其他的servlet-->
<dependency>
<artifactId>spring-boot-starter-undertow</artifactId>
<groupId>org.springframework.boot</groupId>
</dependency>
6.5嵌入式servlet容器自动配置原理:
尚硅谷48节
步骤:
1)、SpringBoot根据导入的依赖情况,给容器中添加相应的嵌入式容器工厂EmbeddedServletContainerFactory[TomcatEmbeddedServletContainerFactory]
2)、容器中某个组件要创建对象就会惊动后置处理器;EmbeddedServletContainerCustomizerBeanPostProcessor;只要嵌入式的Servlet容器工厂,后置处理器就工作;
3)、后置处理器,从容器中获取所有的EmbeddedServletContainerCustomizer调用定制器的定制方法
6.6嵌入式Servlet容器启动原理
什么时候创建嵌入式的Servlet容器工厂?什么时候获取嵌入式的Servlet容器并启动Tomcat?
1)、springboot启动运行run方法;
2)、refreshContext(context);SpringBoot刷新IOC容器【创建IOC容器对象,并初始化容器,创建容器中的每一个组件】如果是web应用创建AnnotationConfigEmbeddedWebApplicationContext,否则AnnotationConfigApplicationContext
3)、refresh(context);刷新刚创建好的IOC容器;
4)、onRefresh();web的IOC容器重写了onRefresh方法;
5)、webioc容器会创建嵌入式的servlet容器;createEmbeddedServletContainer();
6)、获取嵌入式的servlet容器工厂:
EmbeddedServletContainerFactory containerFactory = getEmbeddedServletcontainerFactory();
从IOC容器中获取EmbeddedServletContainerFactory组件;
TomcatEmbeddedServletContainerFactory创建对象,后置处理器一个是这个对象,就获取所有的定制器来先制定Servlet容器的相关配置;
7)、使用容器工厂获取嵌入式的Servlet容器:this.embeddedServletContainer = containerFactory.getEmbeddedServletContainer(getSelfInitializer());
8)、嵌入式的Servlet容器创建对象并启动Servlet容器
先启动servlet 容器,再将ioc容器中没有创建出来的对象获取出来;
IOC容器启动创建嵌入式的servlet容器
七、使用外置的Servlet容器
嵌入式servlet容器:jar
优点:简单、便捷
缺点:默认不支持jsp、优化定制比较复杂(使用定制器【ServerProperties、自定义EmbeddedServletContainerCustomizer】,自己编写嵌入式Servlet容器的创建工厂【EmbeddedServletContainerFactory】);
外置的Servlet就应用而生了
7.1创建一个新的项目,打成war包
7.1.1目录结构
7.1.3将嵌入式的Tomcat指定为provided;
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
7.1.4必须编写一个SpringBootServletInitializer的子类,并调用configure方法
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
//传入SpringBoot应用的主程序
return application.sources(SpringBoot04WebJspApplication.class);
}
}
7.2原理
jar包:执行SpringBoot主类的main方法,启动ioc容器,创建嵌入式的servlet容器;
war包:启动服务器,服务器启动Springboot应用【SpringBootServletInitializer】,启动ioc容器;
7.2.1servlet3.0(Spring注解版)
8.2.4 Shared libraries/runtimes pluggability;
规则:
1)、服务器启动(web应用启动)会创建当前web应用里面的每一个jar包里面ServletContainerInitializer实例;
2)、ServletContainerInitializer的实例放在jar包的META-INF/servies文件夹下,有一个名为javax.servlet.ServletContainerinitializer的文件,内容就是ServletContainerInitializer的实体类的全类名
3)、还可以使用@HandlesTypes,在应用启动的时候加载我们感兴趣的类;
流程:
1)、启动tomcat