其他分享
首页 > 其他分享> > springMvc笔记-Filter

springMvc笔记-Filter

作者:互联网

本笔记基于springBoot 2.3.3版本

一般我们平常如果要使用Filter,会用到如下代码。

@Configuration
@ConditionalOnClass(CoreFilter.class)
public class CoreFilterAutoConfiguration {

    @Bean
    public FilterRegistrationBean coreFilterAutoConfig() {
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.setFilter(new CoreFilter());
        return bean;
    }
}

图中我们可以看到,在CoreFilterAutoConfiguration配置类里我们定义一个@Bean注解,将码好的CoreFilter过滤器装入FilterRegistrationBean,最后注入到spring容器中去。

源码分析:

ServletContextInitializer

这个接口是spring提供的专门给Servlet,Filter,Lister组件使用的。我们看一下其集成UML图:


图中我们可以看到,上图分别是Filter,Servlet,Listener组件的spring类UML图。我们重点看第一张Filter图。通过上文我们知道,Filter是在StandardContext初始化阶段进行加载装入的。代码如下:

for (Map.Entry<ServletContainerInitializer, Set<Class<?>>> entry :
                initializers.entrySet()) {
                try {
                    1.entry.getKey().onStartup(entry.getValue(),
                            getServletContext());
                } catch (ServletException e) {
                    log.error(sm.getString("standardContext.sciFail"), e);
                    ok = false;
                    break;
                }
            }

            // Configure and call application event listeners
            if (ok) {
                2. if (!listenerStart()) {
                    log.error(sm.getString("standardContext.listenerFail"));
                    ok = false;
                }
            }

            // Check constraints for uncovered HTTP methods
            // Needs to be after SCIs and listeners as they may programmatically
            // change constraints
            if (ok) {
                checkConstraintsForUncoveredMethods(findConstraints());
            }

            try {
                // Start manager
                Manager manager = getManager();
                if (manager instanceof Lifecycle) {
                    ((Lifecycle) manager).start();
                }
            } catch(Exception e) {
                log.error(sm.getString("standardContext.managerFail"), e);
                ok = false;
            }

            // Configure and call application filters
            if (ok) {
                3. if (!filterStart()) {
                    log.error(sm.getString("standardContext.filterFail"));
                    ok = false;
                }
            }

过滤器是在1处被加载的,具体如下代码:

	private void selfInitialize(ServletContext servletContext) throws ServletException {
		prepareWebApplicationContext(servletContext);
		registerApplicationScope(servletContext);
		WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(), servletContext);
		for (ServletContextInitializer beans : getServletContextInitializerBeans()) {
			beans.onStartup(servletContext);
		}
	}

selfInitialize会将从spring容器(或者叫spring应用上下文)里将ServletContextInitializer类型的Bean拿出来进行遍历执行其onStartUp方法。具体到FilterRegistrationBean方法执行顺序就是:
RegistrationBean.onStartUp ->  DynamicRegistrationBean.register -> AbstractFilterRegistrationBean.addRegistration -> ApplicationContextFacade.addFilter -> ApplicationContext.addFilter -> StandardContext.addFilterDef -> filterDefs.put

 

RegistrationBean.onStartUp -> DynamicRegistrationBean.register -> AbstractFilterRegistrationBean.configure -> ApplicationFilterRegistration.addMappingForServletNames-> StandardContext.addFilterMap-> filterMaps.add

至此过滤器就已经添加到StandardContext的filterDefs属性当中去了,并同时将fiter相关信息也添加进filterMaps里

    private Map<String, FilterDef> filterDefs = new HashMap<>();

    private final ContextFilterMaps filterMaps = new ContextFilterMaps();

1方法之后开始执行3方法filterStart,这个方法将我们刚才添加入filterDefs里的filterDef转换成ApplicationFilterConfig 并放入fiterConfigs里,代码如下:

    public boolean filterStart() {

        if (getLogger().isDebugEnabled()) {
            getLogger().debug("Starting filters");
        }
        // Instantiate and record a FilterConfig for each defined filter
        boolean ok = true;
        synchronized (filterConfigs) {
            filterConfigs.clear();
            for (Entry<String,FilterDef> entry : filterDefs.entrySet()) {
                String name = entry.getKey();
                if (getLogger().isDebugEnabled()) {
                    getLogger().debug(" Starting filter '" + name + "'");
                }
                try {
                    ApplicationFilterConfig filterConfig =
                            new ApplicationFilterConfig(this, entry.getValue());
                    filterConfigs.put(name, filterConfig);
                } catch (Throwable t) {
                    t = ExceptionUtils.unwrapInvocationTargetException(t);
                    ExceptionUtils.handleThrowable(t);
                    getLogger().error(sm.getString(
                            "standardContext.filterStart", name), t);
                    ok = false;
                }
            }
        }

        return ok;
    }

当用户请求来时,调用链是TomcatWebServer.start -> Connector.start -> Connector.startInternal -> Http11NioProtocol.start -> NioEndpoint.start 这个方法里会创建服务器线程池,poller以及 acceptor线程。代码如下。

    @Override
    public void startInternal() throws Exception {

        if (!running) {
            running = true;
            paused = false;

            if (socketProperties.getProcessorCache() != 0) {
                processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
                        socketProperties.getProcessorCache());
            }
            if (socketProperties.getEventCache() != 0) {
                eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
                        socketProperties.getEventCache());
            }
            if (socketProperties.getBufferPool() != 0) {
                nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
                        socketProperties.getBufferPool());
            }

            // Create worker collection
            if (getExecutor() == null) {
                createExecutor();
            }

            initializeConnectionLatch();

            // Start poller thread
            poller = new Poller();
            Thread pollerThread = new Thread(poller, getName() + "-ClientPoller");
            pollerThread.setPriority(threadPriority);
            pollerThread.setDaemon(true);
            pollerThread.start();

            startAcceptorThread();
        }
    }

Accepter:用于接收socket连接,并将socket连接封装后,添加到Poller中去
Poller: 用于监听Socket事件,当Socket有读写事件时,将Socket封装下添加到Worker中线程任务队列中去
Worker(线程池里面的):拿到Poller传过来的socket连接后,对socket请求的预处理,包括分析报文并创建Request对象.再交给后续处理。流程图如下

 方法流程是:Acceptor run方法-> poller.run -> poller. processKey-> AbstractEndpoint.processSocket -> 请求放入到线程池 -> SocketProcessor.doRun -> AbstractProtocol.process -> AbstractProcessorLight.process -> Http11Processor.service ->

CoyoteAdapter.service -> standEngineValve.invoke -> StandardContextValve.invoke -> StandardWrapperValve.invoke -> ApplicationFilterFactory.createFilterChain(该方法会将filterMaps,filterConfigs里的所有filter取出来和servlet组成调用链) ->

ApplicationFilterChain.doFilter -> ApplicationFilterChain.internalDoFilter(先执行所有filter,然后执行servlet的service方法,即DispathServlet) -> servlet.service 方法 -> 返回用户。

标签:socketProperties,ok,springMvc,笔记,Filter,start,new,SynchronizedStack,poller
来源: https://blog.csdn.net/Jarvan_Song/article/details/116595322