• 周一. 6月 24th, 2024

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

springboot配置嵌入式的servlet容器的原理(一)

[db:作者]

1月 4, 2022
大咖揭秘Java人都栽在了哪?点击免费领取《大厂面试清单》,攻克面试难关~>>>

本笔记源码地址:https://github.com/pshdhx/springbootcurd

使用IDEA打开pom文件,单击右键,如图所示:

我么可以发现,springboot给我们内置了tomcat9.xx

如此,我们就不需要再把springboot项目打包放到tomcat中发布了。因为它内置了嵌入式的tomcat;

如何修改springboot的servlet容器设置

在springboot2.0之前,我们通过编写一个EmbeddedServletContainerCustomizer:嵌入式的Servlet容器的定制器;来修改Servlet容器的配置

@Bean //一定要将这个定制器加入到容器中
public EmbeddedServletContainerCustomizer embeddedServletContainerCustomizer(){
return new EmbeddedServletContainerCustomizer() {
//定制嵌入式的Servlet容器相关的规则
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
container.setPort(8083);
}
};
}

但是2.0之后这个类被取消了,使用了

WebServerFactoryCustomizer这个类来代替;
package com.pshdhx.config;
import org.springframework.boot.web.server.ConfigurableWebServerFactory;
import org.springframework.boot.web.server.WebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* @Authtor pshdhx
* @Date 2020/11/3020:46
* @Version 1.0
*/
@Configuration
public class MyServletConfiguration extends WebMvcConfigurerAdapter {
@Bean
public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer(){
return new WebServerFactoryCustomizer<ConfigurableWebServerFactory>() {
@Override
public void customize(ConfigurableWebServerFactory factory) {
factory.setPort(8083);
}
};
}
}

重启之后,tomcat生效;

1、springboot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(@Bean,@Component),如果有,就用用户自己配置的,如果没有,才自动配置。有些组件可以有多个,如(ViewResolver)可以将用户配置的和自动配置的结合起来。

2、在springboot中会有很多的xxConfigurer帮助我们进行扩展配置

3、在springboot中会有很多的xxxCustomizer帮助我们进行定制配置。==>

custmize:定制
customizer:定制器

2)、注册Servlet三大组件【Servlet、Filter、Listener】

 

由于SpringBoot默认是以jar包的方式启动嵌入式的Servlet容器来启动SpringBoot的web应用,没有web.xml文件。

注册三大组件用以下方式

ServletRegistrationBean:servlet注册器

FilterRegistrationBean :过滤器注册器

ServletListenerRegistrationBean :监听器注册器

servlet配置

package com.pshdhx.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @Authtor pshdhx
* @Date 2020/11/3021:16
* @Version 1.0
* 自定义servlet
*/
public class MyServlet extends HttpServlet {
//处理get请求
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
//处理post请求
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("Hello MyServlet");
}
}

Filter配置

package com.pshdhx.filter;
import javax.servlet.*;
import java.io.IOException;
/**
* @Authtor pshdhx
* @Date 2020/11/3021:37
* @Version 1.0
*/
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("filter 初始化");
}
@Override
public void destroy() {
System.out.println("filter 销毁");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filter 进行中");
}
}

Listener配置

package com.pshdhx.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
* @Authtor pshdhx
* @Date 2020/11/3021:45
* @Version 1.0
*/
public class MyListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("web应用启动");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("当前web应用销毁");
}
}

servlet注册器

package com.pshdhx.config;
import com.pshdhx.filter.MyFilter;
import com.pshdhx.listener.MyListener;
import com.pshdhx.servlet.MyServlet;
import org.springframework.boot.web.server.ConfigurableWebServerFactory;
import org.springframework.boot.web.server.WebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import java.util.Arrays;
/**
* @Authtor pshdhx
* @Date 2020/11/3020:46
* @Version 1.0
*/
@Configuration
public class MyServletConfiguration extends WebMvcConfigurerAdapter {
//对嵌入式的tomcat容器进行设置,加入到容器中
@Bean
public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer(){
return new WebServerFactoryCustomizer<ConfigurableWebServerFactory>() {
@Override
public void customize(ConfigurableWebServerFactory factory) {
factory.setPort(8083);
}
};
}
//把Servlet注册到容器中
@Bean
public ServletRegistrationBean myServlet(){
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new MyServlet(),"/myServlet");
//设置启动顺序
registrationBean.setLoadOnStartup(1);
return registrationBean;
}
//把Filter注册到容器中
@Bean
public FilterRegistrationBean myFilter(){
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new MyFilter());
registrationBean.setUrlPatterns(Arrays.asList("/hello","/myServlet"));
return registrationBean;
}
//注册Listener监听组件到容器
@Bean
public ServletListenerRegistrationBean myListener(){
ServletListenerRegistrationBean<MyListener> registrationBean = new ServletListenerRegistrationBean<>(new MyListener());
return registrationBean;
}
}

使用Jetty服务器和undertow服务器进行启动

<!-- 引入web模块 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<!--引入其他的Servlet容器-->
<dependency>
<artifactId>spring-boot-starter-jetty</artifactId>
<groupId>org.springframework.boot</groupId>
</dependency>
<!-- 引入web模块 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<!--引入其他的Servlet容器-->
<dependency>
<artifactId>spring-boot-starter-undertow</artifactId>
<groupId>org.springframework.boot</groupId>
</dependency>

启动之后,即为Jeety和undertow服务器;

原理:

嵌入式Servlet容器自动配置原理

这是最新版的源码

@Configuration(proxyBeanMethods = false)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration {

导入的BeanPostProcessorsRegistrar.class是后置处理器,就是在组件初始化之后,再给组件进行配置。

后置处理器:bean初始化前后(创建完对象,还没赋值赋值)执行初始化工作

如果引入了tomcat,那么就是tomcat进行工厂类定制操作:

@Bean
@ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat")
public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCustomizer(
ServerProperties serverProperties) {
return new TomcatServletWebServerFactoryCustomizer(serverProperties);
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })
@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
static class EmbeddedTomcat {
@Bean
TomcatServletWebServerFactory tomcatServletWebServerFactory(
ObjectProvider<TomcatConnectorCustomizer> connectorCustomizers,
ObjectProvider<TomcatContextCustomizer> contextCustomizers,
ObjectProvider<TomcatProtocolHandlerCustomizer<?>> protocolHandlerCustomizers) {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.getTomcatConnectorCustomizers()
.addAll(connectorCustomizers.orderedStream().collect(Collectors.toList()));
factory.getTomcatContextCustomizers()
.addAll(contextCustomizers.orderedStream().collect(Collectors.toList()));
factory.getTomcatProtocolHandlerCustomizers()
.addAll(protocolHandlerCustomizers.orderedStream().collect(Collectors.toList()));
return factory;
}
}

如果引入了jetty,那么就对其进行初始化操作org\springframework\boot\autoconfigure\web\servlet\ServletWebServerFactoryConfiguration.java

 /**
* Nested configuration if Jetty is being used.
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Servlet.class, Server.class, Loader.class, WebAppContext.class })
@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
static class EmbeddedJetty {
@Bean
JettyServletWebServerFactory JettyServletWebServerFactory(
ObjectProvider<JettyServerCustomizer> serverCustomizers) {
JettyServletWebServerFactory factory = new JettyServletWebServerFactory();
factory.getServerCustomizers().addAll(serverCustomizers.orderedStream().collect(Collectors.toList()));
return factory;
}
}

如果引入了undertow,那么就对其进行初始化操作

/**
* Nested configuration if Undertow is being used.
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Servlet.class, Undertow.class, SslClientAuthMode.class })
@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
static class EmbeddedUndertow {
@Bean
UndertowServletWebServerFactory undertowServletWebServerFactory(
ObjectProvider<UndertowDeploymentInfoCustomizer> deploymentInfoCustomizers,
ObjectProvider<UndertowBuilderCustomizer> builderCustomizers) {
UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();
factory.getDeploymentInfoCustomizers()
.addAll(deploymentInfoCustomizers.orderedStream().collect(Collectors.toList()));
factory.getBuilderCustomizers().addAll(builderCustomizers.orderedStream().collect(Collectors.toList()));
return factory;
}
}

定制器帮我们修改了Servlet容器的配置?

怎么修改的原理?

–这个没找到到

//初始化之前
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
//如果当前初始化的是一个ConfigurableEmbeddedServletContainer类型的组件
if (bean instanceof ConfigurableEmbeddedServletContainer) {
//
postProcessBeforeInitialization((ConfigurableEmbeddedServletContainer) bean);
}
return bean;
}
private void postProcessBeforeInitialization(
ConfigurableEmbeddedServletContainer bean) {
//获取所有的定制器,调用每一个定制器的customize方法来给Servlet容器进行属性赋值;
for (EmbeddedServletContainerCustomizer customizer : getCustomizers()) {
customizer.customize(bean);
}
}
private Collection<EmbeddedServletContainerCustomizer> getCustomizers() {
if (this.customizers == null) {
// Look up does not include the parent context
this.customizers = new ArrayList<EmbeddedServletContainerCustomizer>(
this.beanFactory
//从容器中获取所有这葛类型的组件:EmbeddedServletContainerCustomizer
//定制Servlet容器,给容器中可以添加一个EmbeddedServletContainerCustomizer类型的组件
.getBeansOfType(EmbeddedServletContainerCustomizer.class,
false, false)
.values());
Collections.sort(this.customizers, AnnotationAwareOrderComparator.INSTANCE);
this.customizers = Collections.unmodifiableList(this.customizers);
}
return this.customizers;
}

org\springframework\boot\autoconfigure\web\ServerProperties.java也是定制器

 

步骤:

1)、SpringBoot根据导入的依赖情况,给容器中添加相应的EmbeddedServletContainerFactory【TomcatEmbeddedServletContainerFactory】

2)、容器中某个组件要创建对象就会惊动后置处理器;EmbeddedServletContainerCustomizerBeanPostProcessor;

只要是嵌入式的Servlet容器工厂,后置处理器就工作;

3)、后置处理器,从容器中获取所有的EmbeddedServletContainerCustomizer,调用定制器的定制方法

难点:

因为是看视频资料是以前的,很多类都过时了,或者找不到了,需要找到最新的类去读源码,费时费力。

像是

WebServerFactoryCustomizer这个类即是2.0之后出的,之前的EmbeddedServletContainerCustomizer这个类就不用了,诸如此类的。
《springboot配置嵌入式的servlet容器的原理(一)》有162个想法
  1. Не имеющий аналогов в соотношении цена/качество/функционал на сегодняшний день источник бесперебойного питания АБП 12-500 специально разработан для качественного и бесперебойного электропитания автоматики газовых котлов .

    стабилизаторы напряжения http://stabrov.ru.

  2. Hey everyone! I’ve just stumbled upon an incredible website that’s all about crypto markets. If you’re keen on exploring different cryptocurrency exchanges, this might be the ideal place for you!

    The site (https://cryptoairdrops.ru/) offers comprehensive insights of various cryptocurrency platforms, including fees, security measures, available cryptocurrencies, and user experience. Whether you’re a beginner just starting out or an experienced trader, there’s something for everyone.

    What I found particularly useful was their side-by-side comparisons, which made it super easy to evaluate different exchanges and find the one that best fits my needs. They also cover the latest trends in the crypto world, which keeps you informed on all the critical changes.

    If you’re looking into diversifying your portfolio, I highly recommend checking this site out. It’s packed with valuable information that can help you make informed decisions in the dynamic world of cryptocurrency.

    Let’s make the most of this resource and share our experiences! Would love to hear your thoughts and experiences with different exchanges as well.

  3. Приветствую. кузовные запчасти – большой ассортимент кузовных запчастей и подбор автозапчастей для кузова машины. Переходите в интернет-магазин для заказа новых и оригинальных запчастей для авто. Гарантия и доставка по Минску и областям.

  4. В современном мире, где аттестат – это начало успешной карьеры в любом направлении, многие стараются найти максимально быстрый путь получения качественного образования. Факт наличия официального документа трудно переоценить. Ведь диплом открывает двери перед любым человеком, который желает вступить в профессиональное сообщество или учиться в высшем учебном заведении.
    В данном контексте мы предлагаем очень быстро получить этот важный документ. Вы сможете заказать аттестат, и это является отличным решением для всех, кто не смог завершить обучение, утратил документ или желает исправить плохие оценки. Аттестат изготавливается аккуратно, с особым вниманием к мельчайшим деталям. В результате вы сможете получить полностью оригинальный документ.
    Плюсы подобного подхода состоят не только в том, что вы сможете оперативно получить аттестат. Процесс организован комфортно и легко, с профессиональной поддержкой. Начав от выбора подходящего образца документа до консультаций по заполнению персональных данных и доставки в любое место страны — все находится под абсолютным контролем наших специалистов.
    Для тех, кто ищет быстрый и простой способ получения необходимого документа, наша компания готова предложить выгодное решение. Приобрести аттестат – значит избежать длительного обучения и сразу перейти к достижению своих целей, будь то поступление в университет или старт карьеры.

    http://prema-attestats.ru/

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注