【Spring Boot】Web原生组件注入

生活中,最使人疲惫的往往不是道路的遥远,而是心中的郁闷;最使人痛苦的往往不是生活的不幸,而是希望的破灭;最使人颓废的往往不是前途的坎坷,而是自信的丧失;最使人绝望的往往不是挫折的打击,而是心灵的死亡。所以我们要有自己的梦想,让梦想的星光指引着我们走出落漠,走出惆怅,带着我们走进自己的理想。

导读:本篇文章讲解 【Spring Boot】Web原生组件注入,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

一、闲话

今天本来准备偷懒一下,但是打开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()方法,我们拦截器的前置和后置等操作都在这个方法中进行

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/136744.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!