SpringBoot10——Web05原生组件注入,嵌入式servlet容器与定制化原理

Web原生组件注入(使用web的Servlet、Filter、Listener)

如何在springboot里面使用web原生的组件,一般有两种方式

1.使用Servlet API(要通过标注注解)

Servlet 

基本上就是原生使用的格式

@WebServlet
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("6666666666");
    }
}

之前我们请求的路径需要在xml里面配置,现在请求路径在注解里配置就可以了

@WebServlet(urlPatterns = "/my")

但是如果想让他生效,我们还需要在主配置类上添加注解

注解的内容可以自定义项目扫描servlet的路径

@ServletComponentScan(basePackages = "com.LALALA.admin")
@SpringBootApplication
public class SpringBoot06Web04InterceptorFileUploadExceptionHandlingApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBoot06Web04InterceptorFileUploadExceptionHandlingApplication.class, args);
    }

}

如果里面不写内容,默认是扫描主配置类所在包与其子包

 但是现在没有让我们之前配置的拦截器拦截就可以访问,这是为什么?

Filter

@Slf4j
@WebFilter
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("MyFilter初始化完成");
    }


    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        log.info("MyFilter在工作");
        //放行拦截器链路
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {
        log.info("MyFilter销毁完成");
    }
}

而且在这个@WebFilter里面可以填写多个拦截路径,例如现在想拦截css文件

@WebFilter(urlPatterns = {"/css/*","/images/*"})

 

 

 

 Listener

@Slf4j
@WebListener
public class MyListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        log.info("项目初始化完成");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        log.info("项目销毁完成");
    }
}

 

 2.使用RegistrationBean

如果我们现在不能动用原生servlet里(也即是我们刚刚写的那三个),而且把这些标注为普通类的时候,就可以使用这个东西完成对原生servlet的使用

 现在我们这几个servlet肯定不能使用了

使用RegistrationBean方法

//这是一个配置类
@Configuration
public class MyRegistConfig {

    //把这个东西加入容器当中
    @Bean
    public ServletRegistrationBean myServlet(){
        //自己new一个servlet
        MyServlet myServlet = new MyServlet();
        //把我们的servlet和我们需要映射的路径传入并且返回
        return new ServletRegistrationBean(myServlet,"/my");
    }
}
@Bean
    public FilterRegistrationBean myFilter(){

        MyFilter myFilter = new MyFilter();
        //这种写法是传入myFilter和上面的myServlet()里面写的啥路径,这玩意就拦截啥路径
        //return new FilterRegistrationBean(myFilter,myServlet());
        //自己new一个拦截器
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(myFilter);
        //把拦截器的拦截路径注入
        filterRegistrationBean.setUrlPatterns(Arrays.asList("/my","/css/*"));
        //返回对象
        return filterRegistrationBean;
    }

    @Bean
    public ServletListenerRegistrationBean myListener(){
        MyListener myListener = new MyListener();
        return new ServletListenerRegistrationBean(myListener);
    }

细节,我们需要把这几个组件设置为单实例的

 为什么我们自己注入的组件没有经过spring拦截器的拦截?

现在我们servlet的情况

 看一下dispatchServlet的自动配置类

给容器中放了一个名字为dispatchservlet的组件

容器中自动配置了 DispatcherServlet 属性绑定到 WebMvcProperties;对应的配置文件配置项是 spring.mvc。

 

 下面还有组件

这个组件的本质还是通过 ServletRegistrationBean<DispatcherServlet> 把 DispatcherServlet 配置进来。

所以这个dispatchServlet就是我们容器中使用的中央处理器组件,但是这个玩意的默认访问路径什么的都在哪呢?——其实都在配置文件里面

 

 我们也可以在配置文件上面修改默认访问路径

 

 

 

 Tomcat-Servlet;多个Servlet都能处理到同一层路径,精确优选原则

现在我们的情况就是这样,我们之前访问的也是/my路径,属于精确优先,所以不会走我们spring的拦截器了

切换Web服务器与定制化服务器原理

嵌入式服务器执行流程原理

我们现在不用自己配置tomcar是因为底层已经帮助我们做好了自动配置,但是它是如何做的,已经想使用其他方式的嵌入式服务器如何做?

根据官方文档我们发现,如果现在是web场景,就会把我们的IOC容器变成另外一种形式

 

 但是这个容器的本质其实还是一个普通的IOC

 

SpringBoot应用启动发现当前是Web应用。web场景包-导入tomcat


web应用会创建一个web版的ioc容器 ServletWebServerApplicationContext

ServletWebServerApplicationContext  启动的时候寻找 ServletWebServerFactory(Servlet 的web服务器工厂---> 生产Servlet 的web服务器) 

那平时都会生产哪些?

SpringBoot底层默认有很多的WebServer工厂TomcatServletWebServerFactory, JettyServletWebServerFactory, or UndertowServletWebServerFactory

底层直接会有一个自动配置类。ServletWebServerFactoryAutoConfiguration
○ServletWebServerFactoryAutoConfiguration导入了ServletWebServerFactoryConfiguration(配置类)

 那这个配置类都干了什么?

ServletWebServerFactoryConfiguration 配置类 根据动态判断系统中到底导入了那个Web服务器的包。(默认是web-starter导入tomcat包),容器中就有 TomcatServletWebServerFactory

 

 

 TomcatServletWebServerFactory 创建出Tomcat服务器并启动;TomcatWebServer 的构造器拥有初始化方法initialize---this.tomcat.start();

 

 

 

 

 
内嵌服务器,就是手动把启动服务器的代码调用(tomcat核心jar包存在)
 

如何切换嵌入式服务器

使用pom文件就行

1.在我们的web场景排除tomcat服务器

2.添加我们想使用的服务器依赖

 定制化嵌入式服务器

1.修改配置文件 server.xxx

因为我们的服务器自动配置类里的取值都是在server下的配置文件抽取的

 在服务器工厂的定制化器中也是在server下的配置文件抽取的

 配置文件内容

 2.自己写一个web服务器的生产工厂放进去

直接自定义 ConfigurableServletWebServerFactory

3.修改上文所说的容器工厂定制化器

 

 实现 WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>
○把配置文件的值和ServletWebServerFactory 进行绑定

定制化springMVC的原理

springMVC完成自动配置的原理流程
 

场景starter - xxxxAutoConfiguration - 导入xxx组件 - 绑定xxxProperties -- 绑定配置文件项

定制化的常用操作

1.编写自定义的配置类 xxxConfiguration;+ @Bean替换、增加容器中默认组件;视图解析器

2.修改配置文件

3.修改上文所说的容器工厂定制化器:xxxxxCustomizer;

4.Web应用 编写一个配置类实现 WebMvcConfigurer 的接口即可定制化web功能(可以重写接口里面的方法);+ @Bean给容器中再扩展一些组件

5.@EnableWebMvc + WebMvcConfigurer —— @Bean 可以全面接管SpringMVC,所有规则全部自己重新配置; 实现定制和扩展功能

○原理
○1、WebMvcAutoConfiguration 默认的SpringMVC的自动配置功能类。静态资源、欢迎页.....
○2、一旦使用 @EnableWebMvc 、。会 @Import(DelegatingWebMvcConfiguration.class)
○3、DelegatingWebMvcConfiguration 的 作用,只保证SpringMVC最基本的使用
        ■把所有系统中的 WebMvcConfigurer 拿过来。所有功能的定制都是这些 WebMvcConfigurer         合起来一起生效
        ■自动配置了一些非常底层的组件。RequestMappingHandlerMapping、这些组件依赖的                组 件都是从容器中获取
        ■public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport
○4、WebMvcAutoConfiguration 里面的配置要能生效 必须 @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
○5、@EnableWebMvc 导致了 WebMvcAutoConfiguration 没有生效(因为这个组件是被DelegatingWebMvcConfiguration继承的组件)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值