【Spring Boot】Web原生组件注入

一、闲话

今天本来准备偷懒一下,但是打开CSDN之前跟自己说,如果今天又涨粉丝了,那么就学习一下
学多学少都要学,打开一看,哈哈哈,多了三十多个粉丝,只能带着开心来继续学习咯

二、注入Web原生组件

1、使用Servlet API

关于servlet,可以看下博主之前写的博客【SpringMVC】MVC架构与Servlet

注意,如果要是下面的注解生效,还需要使用@ServletComponentScan注解

@ServletComponentScan(basePackages = “com.decade.servlet”) :指定原生Servlet组件都放在哪里,我们一般将他放在主启动类上
在这里插入图片描述

  • 注入Servlet:使用@WebServlet
package com.decade.servlet;

import lombok.extern.slf4j.Slf4j;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Slf4j
@WebServlet(urlPatterns = {"/myServlet"}) // 配置指定url,请求转发到此servlet
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().print("test OK!");
    }
}

效果:直接响应,我们要思考一下/my请求为什么没有经过Spring的拦截器?
在这里插入图片描述

  • 注入Filter:使用@WebFilter
package com.decade.servlet;

import lombok.extern.slf4j.Slf4j;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@Slf4j
@WebFilter(urlPatterns = {"/css/*", "/images/*"}) // 配置过滤器过滤的请求
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("filter初始化完成!");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        log.info("过滤器生效!");
        // 完成过滤逻辑之后,放行
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {
        log.info("filter销毁完成!");
    }
}
  • 注入Listener:使用@WebListener
package com.decade.servlet;

import lombok.extern.slf4j.Slf4j;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@Slf4j
@WebListener
public class MyListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        log.info("MyListener监听到项目初始化完成!");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        log.info("MyListener监听到项目销毁!");
    }
}

启动项目进行验证
在这里插入图片描述

2、使用RegistrationBean

创建一个配置类,使用@Bean注解将servlet、filter和listener注册到容器中去

我们结合一个实例来验证一下
首先我们将上面创建的三个类上面的@WebServlet、@WebFilter和@WebListener删除

然后自己新建一个配置类

package com.decade.servlet;

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 java.util.Arrays;

// 保证依赖的组件是单实例的
@Configuration(proxyBeanMethods = true)
public class MyServletConfig {

    @Bean
    public ServletRegistrationBean myServlet() {
        final MyServlet myServlet = new MyServlet();
        // 设置对应此servlet的请求路径
        return new ServletRegistrationBean(myServlet, "/myServlet", "/myServlet2");
    }

    @Bean
    public FilterRegistrationBean myFilter() {
        final MyFilter myFilter = new MyFilter();
        // 设置要过滤的请求,即对应这个请求的servlet
        //return new FilterRegistrationBean(myFilter, myServlet());

		// 方式二:使用setUrlPatterns配置要拦截的请求
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(myFilter);
        filterRegistrationBean.setUrlPatterns(Arrays.asList("/css/*", "/myServlet", "/myServlet2"));
        return filterRegistrationBean;
    }

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

验证同样生效
在这里插入图片描述

3、思考

/my请求为什么没有经过Spring的拦截器?

那么我们就要考虑一下DispatcherServlet类是怎么注册到容器中的
我们需要分析下和DispatcherServlet有关的自动配置类DispatcherServletAutoConfiguration

  • 它下面有一个配置类DispatcherServletConfiguration,向容器中注册了DispatcherServlet,并将属性绑定到 WebMvcProperties,点进去可以看到对应的配置文件配置项是spring.mvc
    在这里插入图片描述

  • 然后这里还有一个配置类DispatcherServletRegistrationConfiguration,它里面有一个方法dispatcherServletRegistration(),这里就和我们上面第二节的作用是一样的,使用RegistrationBean把DispatcherServlet这个类当作Servlet组件注册到容器中
    在这里插入图片描述

了解了上述原理之外,我们还需要了解一个原则,
精确优选原则:如果一个请求能被两个Servlet处理,那么我们先选匹配精确度高的那个

这就解释了为什么,我们自定义的Servlet对应的请求没有被我们系统中配置的拦截器拦截,因为他直接走了tomcat,没有走Spring默认配置的DispatcherServlet类下的doDispatch()方法,我们拦截器的前置和后置等操作都在这个方法中进行

如有错误,欢迎指正!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值