SpringBoot原生组件注入实现两种方式介绍

 更新时间:2022年10月20日 16:15:53   作者:刘婉晴  
SpringBoot是Spring全家桶的成员之一,基于约定优于配置的思想(即有约定默认值,在不配置的情况下会使用默认值,在配置文件下配置的话会使用配置的值)。SpringBoot是一种整合Spring技术栈的方式(或者说是框架),同时也是简化Spring的一种快速开发的脚手架

原生组件注入SpringBoot,即注册 Servlet 、Filter、Listener 进入 SpringBoot

一、使用 Servlet API

使用 Servlet API 可以实现原生组件注入,通过在自定义 Servlet 前加入 @WebServlet 注释,并且在 SpringBoot 启动类前加入 @ServletComponentScan 注释,可实现注册 Servlet

代码示例:

1、实现自定义 MyServlet

自定义 Servlet 类:

@WebServlet(urlPatterns = "/my") // 加入 @WebServlet 注释
public class MyServlet extends HttpServlet { // 注意要继承 HttpServlet 类
    @Override // 重写 DoGet 方法
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().println("haha");
    }
}

项目启动类:

@ServletComponentScan(basePackages = "com.wanqing.admin") //扫描那个包中有servlet
@SpringBootApplication
public class DemoAdminApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoAdminApplication.class, args);
    }
}

2、实现自定义 MyFilter

@Slf4j
@WebFilter(urlPatterns = {"/css/*", "/images/*"}) // 拦截静态资源
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
        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() {
        Filter.super.destroy();
        log.info("MyFilter销毁");
    }
}

3、实现自定义 MyServletContextListener

@WebListener
@Slf4j
public class MyServletContextListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        log.info("MyServletContextListener 监听到项目初始化完成");
    }
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        log.info("MyServletContextListener 监听到项目销毁");
    }
}

二、使用 RegistrationBean 的方式注入原生组件

通过编写 MyRegistConfig 配置类,返回 RegistrationBean 的方式实现组件的注入,与上一种方式的区别在于,这种方式不需要给 自定义 Servlet 类写 @WebServlet 注释。

注意点:要记得使用 @Bean 注释将 ServletRegistrationBean 注册到容器中。

代码示例:

自定义 MyRegistConfig 配置类,注册 myServlet 组件,返回 ServletRegistrationBean 对象 (对象参数为自定义的 myServlet 对象实例)

myFilter 及myListener 的实现方式同理

@Configuration
public class MyRegistConfig {
    @Bean
    public ServletRegistrationBean myServlet(){
        MyServlet myServlet = new MyServlet();
        return new ServletRegistrationBean(myServlet, "/my","/my02");
    }
    @Bean
    public FilterRegistrationBean myFilter(){
        MyFilter filter = new MyFilter();
        //return new FilterRegistrationBean(filter, myServlet()); // 拦截myServlet()的路径
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(filter);
        filterRegistrationBean.addUrlPatterns("/my","/css/*");
        return filterRegistrationBean;
    }
    @Bean
    public ServletListenerRegistrationBean myListener(){
        MyServletContextListener myServletContextListener = new MyServletContextListener();
        return new ServletListenerRegistrationBean(myServletContextListener);

    }
}

拓展:为什么拦截器不拦截 我们自定义的 MyServlet 请求?

分析 DispatcherServlet 如何注册进入容器中,从 DispatcherServletAutoConfiguration 类开始

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

		@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME) // 注册 DispatcherServlet  组件
		public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) {
			DispatcherServlet dispatcherServlet = new DispatcherServlet();
			dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());
			dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest());
			dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound());
			dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents());
			dispatcherServlet.setEnableLoggingRequestDetails(webMvcProperties.isLogRequestDetails());
			return dispatcherServlet;
		}

通过 ServletRegistrationBean < DispatcherServlet > 机制(DispatcherServletRegistrationBean.class)将 DispatcherServlet 原生的 Servlet 组件配置进来

		@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()); // 拿到默认映射路径为 / 路径
			registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
			registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());
			multipartConfig.ifAvailable(registration::setMultipartConfig);
			return registration;
		}

拿到默认映射路径 /

WebMvcProperties.class 中配置

使用 Tomcat 做原生 Servlet 开发,如果多个 Servlet 都能处理到同一层路径,是精确优先原则,例如:

A:/my/

B: /my/1

发送 /my/1 请求 B处理,而发送 /my/2 请求 A 处理

结论 : 来到 /my 不经过 / —— 精确匹配 /my 直接经 Tomcat 写出响应,不经过 SpringMVC 的一系列流程,因此不被拦截器拦截,如下图所示:

到此这篇关于SpringBoot原生组件注入实现两种方式介绍的文章就介绍到这了,更多相关SpringBoot原生组件注入内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 浅谈Mybatis之参数传递的几种姿势

    浅谈Mybatis之参数传递的几种姿势

    在mybatis的日常开发中,mapper接口中定义的参数如何与xml中的参数进行映射呢?本文就详细的介绍一下,感兴趣的可以了解一下
    2021-09-09
  • Java中instanceof关键字的用法总结

    Java中instanceof关键字的用法总结

    instanceof是Java的一个二元操作符,和==,>,<是同一类东东。由于它是由字母组成的,所以也是Java的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回boolean类型的数据
    2013-10-10
  • MyBatis中如何查询某个时间段内的数据

    MyBatis中如何查询某个时间段内的数据

    这篇文章主要介绍了MyBatis中如何查询某个时间段内的数据,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • 详解MyBatis resultType与resultMap中的几种返回类型

    详解MyBatis resultType与resultMap中的几种返回类型

    本文主要介绍了MyBatis resultType与resultMap中的几种返回类型,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • spring*.xml配置文件明文加密的实现

    spring*.xml配置文件明文加密的实现

    这篇文章主要介绍了spring*.xml配置文件明文加密的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • Java中JDBC的使用教程详解

    Java中JDBC的使用教程详解

    Java语言操作数据库 JDBC本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。本文讲解了JDBC的使用方法,需要的可以参考一下
    2022-06-06
  • springboot配置Jackson返回统一默认值的实现示例

    springboot配置Jackson返回统一默认值的实现示例

    在项目开发中,我们返回的数据或者对象没有的时候一般直接返回的null,那么如何返回统一默认值,感兴趣的可以了解一下
    2021-07-07
  • 关于SpringBoot的spring.factories文件详细说明

    关于SpringBoot的spring.factories文件详细说明

    spring.factories 文件是 Spring Boot 自动配置机制的核心部分之一,它位于每个 Spring Boot 自动配置模块的 META-INF 目录下,经常看到 spring.factories 文件,却没有对它进行深入的了解和分析,今天我们就一起揭开面纱看看它的内在,需要的朋友可以参考下
    2024-12-12
  • Springmvc应用Mongodb分页实现

    Springmvc应用Mongodb分页实现

    这篇文章主要为大家详细介绍了Springmvc应用Mongodb分页实现,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11
  • 解决mybatis分页插件PageHelper导致自定义拦截器失效

    解决mybatis分页插件PageHelper导致自定义拦截器失效

    这篇文章主要为大家介绍了解决mybatis分页插件PageHelper导致自定义拦截器失效方案示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08

最新评论