【spring】
---------------------------------------------------------------> 【spring boot】【tomcat】【filter】 <---------------------------------------------------
-------------------------------->梳理一下总的流程<--------------------------------------
1.故事开始
【SecurityFilterAutoConfiguration】类的【securityFilterChainRegistration】方法向spring上下文中注册一个【DelegatingFilterProxyRegistrationBean】对象,该【bean】的名称是【springSecurityFilterChain】,【targetBeanName】的属性值为【springSecurityFilterChain】。
2.围绕【StandardContext】中的【FilterMap[]】属性是何时被填充的展开
分析1->【tomcat】上下文【StandardContext】中的【TomcatStarter】是何时被加入的
1.1 【TomcatServletWebServerFactory】的【configureContext】方法,会创建一个【TomcatStarter】对象,并将一个【ServletContextInitializer[] initializers】加入到它的【initializers】列表。
1.2 调用【StandardContext】的【addServletContainerInitializer】方法,将该【TomcatStarter】加入。
分析2->关键在于【spring boot】中最初的这些【ServletContextInitializer】是如何获取到的
2.1 【spring】的【web】上下文会创建一个【WebServer】,通过一个【ServletWebServerFactory】获取【WebServer】,获取之前会调用【getSelfInitializer】方法
2.2 【spring】上下文中,该方法的返回值是一个【lumbda】表达式,只有这一个【ServletContextInitializer】。
3.3 在【WebServer】工厂中,通过【mergeInitializers】方法,又增加了一些额外的【ServletContextInitializer】。
3.3.1 第一个是给【ServletContext】设置参数的【ServletContextInitializer】,拿到【WebServerFactory】中的【initParameters】,设置到【ServletContext】中,以【lumbda】表达式的方式呈现。
3.3.2 第二个是创建了一个【SessionConfiguringInitializer】,添加到【List<ServletContextInitializer>】列表中。
3.3.3 第三个是把步骤2中的【ServletContextInitializer】添加到列表中。
3.3.4 第四个是把【WebServerFactory】中的【List<ServletContextInitializer>】添加到列表中。
3.3.5 转换为数组的形式返回。
3.4 通过创建【TomcatStarter】,将上面列表中的【ServletContextInitializer】传给【TomcatStarter】。
分析3->【TomcatStarter】内部的【ServletContextInitializer[] initializers】,何时执行,又分别做了哪些事情
3.1 【tomcat】上下文【StandardContext】的【startInternal】方法,会在某个阶段拿到它所持有的【Map<ServletContainerInitializer, Set<Class<?>>> initializers】属性,挨个调用他们的【onStartup】方法。
3.2 【spring boot】中该【StandardContext】的该属性,目前只有一个【ServletContainerInitializer】,是【TomcatStarter】,所以该调用会调用到【TomcatStarter】的【onStartup】方法上。
3.3 【TomcatStarter】内部持有【ServletContextInitializer[] initializers】列表,挨个调用这些个的【onStartup】方法。
3.4 其实最关键的是最后一个,它的作用就是先创建了一个【ServletContextInitializerBeans】,然后调用它的【onStartup】方法。
5.【ServletContextInitializerBeans】的创建逻辑也很关键.................
分析4->【ServletContextInitializerBeans】的创建逻辑
4.1 【BeanFactory】中获取类型为【ServletContextInitializer】的【bean】,键【key】为【name】,【value】为【bean】放入到【map】中。
4.2 获取到的两个【bean】分别是
【name】为【securityFilterChainRegistration】的【DelegatingFilterProxyRegistrationBean】,它的【targetBeanName】为【springSecurityFilterChain】。
【name】为【dispatcherServletRegistration】的【DispatcherServletRegistrationBean】
4.3 将这两个【bean】对象加入到一个【MultiValueMap<Class<?>, ServletContextInitializer> initializers】中
【Filter -> DelegatingFilterProxyRegistrationBean】
【Servlet -> DispatcherServletRegistrationBean】
4.4 调用【addAdaptableBeans】,从【BeanFactory】中获取类型为【Filter】的,他们分别是
【requestContextFilter】 -> 【OrderedRequestContextFilter】
【hiddenHttpMethodFilter】 -> 【OrderedHiddenHttpMethodFilter】
【formContentFilter】 -> 【OrderedFormContentFilter】
【springSecurityFilterChain】 -> (上一步已经被加载过了)
【characterEncodingFilter】 -> 【OrderedCharacterEncodingFilter】
4.5 将上面这几个加入封装成为【FilterRegistrationBean】,然后在加入到【MultiValueMap<Class<?>, ServletContextInitializer> initializers】中。
4.6 适配【EventListener】->目前上下文中没有,先略过。
4.7 上面的步骤已经创建好了【ServletContextInitializerBeans】,由于它实现了集合抽象类,所以将挨个调用上面封装好的【RegistrationBean】的【onStartup】方法。
分析5->这些大哥们的【onStartup】方法
5.1 【filter characterEncodingFilter】
是将其往【ServletContext】中注册。先获取到【Filter】,然后调用【ServletContext】的【addFilter】方法,将该【Filter】加入到【ServletContext】中。
加入完成以后会返回一个【ApplicationFilterRegistration】,然后调用【configure】方法对它进行处理,其实就是将【Filter】和【url】的映射关系加入到【ServletContext】中。
5.2 其它的也类似,就是将相应的【Filter】和【Servlet】加入到【ServletContext】中去。
------------------------------------------->请求到达【tomcat】【Filter】的处理流程<---------------------------------------------
分析1->【ApplicationFilterChain】被创建的细节
1.1 当请求到达【tomcat】时,【StandardWrapperValve】的【invoke】方法调用【ApplicationFilterFactory】的【createFilterChain】方法创建过滤器链。
1.2 直接【new】了一个【ApplicationFilterChain】,然后从【tomcat】上下文【Context】中拿出【FilterMap[]】,将和该请求的【path】匹配的【Filter】封装成为【ApplicationFilterConfig】,添加到【ApplicationFilterChain】的【ApplicationFilterConfig[] filters】属性中。
1.3 使用创建好的【ApplicationFilterChain】,调用其【doFilter】方法。
1.4 拿到刚才塞入到【ApplicationFilterChain】的【ApplicationFilterConfig[] filters】属性中的各个【Filter】,执行对请求的过滤处理。(【spring security】的过滤器也在其中)。
分析2->【Spring Security】过滤器的执行细节
2.1 【Tomcat】的过滤器链执行到【Spring Security】的过滤器时,通过【ApplicationFilterConfig】的【getFilter】方法,会拿到一个【DelegatingFilterProxy】对象,而该对象是由【DelegatingFilterProxyRegistrationBean】的【getFilter】方法创建的。
2.2 【DelegatingFilterProxy】会从【spring】的上下文中拿到一个名为【springSecurityFilterChain】,类型为【Filter】的过滤器,将其设置为它的【delegate】属性。
2.3 该【delegate】的类型为【FilterChainProxy】,从【List<SecurityFilterChain> filterChains】属性中选取一个合适的【SecurityFilterChain】,获取该【SecurityFilterChain】所持有的【Filter】列表。
2.4 根据上述步骤获取到的【Filter】列表,创建一个【VirtualFilterChain】对象,调用其【doFilter】方法。
2.5 上述调用过程会执行【spring security】过滤器的一系列逻辑。