In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-27 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/02 Report--
This article introduces the use of filter Filter in SpringBoot web, the content is very detailed, interested friends can refer to, hope to be helpful to you.
Here is another way to use Filter directly as the Bean of Spring, and in this way, the priority of Filter can be specified directly through the @ Order annotation. Finally, from the point of view of source code, we will analyze why one of the @ Order annotations works and the other does not.
I. Filter
The project execution environment of this blog post is still SpringBoot2+, project source code. You can get at the end of the article.
1. Use posture
In the previous blog post, we introduced two kinds of posture. Here is a brief introduction.
WebFilter comments
Add the annotation @ WebFilter; to the Filter class and then in the project, display the declaration @ ServletComponentScan and turn on the component scan for Servlet
@ WebFilterpublic class SelfFilter implements Filter {} @ ServletComponentScanpublic class SelfAutoConf {}
FilterRegistrationBean
Another way is to directly create a registered Bean of Filter, which internally holds an instance of Filter; in SpringBoot, what is initialized is the wrapper Bean of Filter.
@ Beanpublic FilterRegistrationBean orderFilter () {FilterRegistrationBean filter = new FilterRegistrationBean (); filter.setName ("orderFilter"); filter.setFilter (new SelfFilter ()); filter.setOrder (- 1); return filter;}
This article will introduce another way to use Filter directly as a normal Bean object, that is, we can directly add the annotation @ Component to the Filter class, and then Spring will register the Bean that implements the Filter interface as a filter
And in this posture, the priority of Filter can be specified through the @ Order annotation.
Design a case and define two Filter (ReqFilter and OrderFilter). When the priority is not specified, the OrderFilter priority will be higher according to the name. If we actively set it, we want the ReqFilter priority to be higher.
@ Order (1) @ Componentpublic class ReqFilter implements Filter {@ Override public void init (FilterConfig filterConfig) throws ServletException {} @ Override public void doFilter (ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println ("req filter"); chain.doFilter (request, response) } @ Override public void destroy () {} @ Order (10) @ Componentpublic class OrderFilter implements Filter {@ Override public void init (FilterConfig filterConfig) throws ServletException {} @ Override public void doFilter (ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println ("order filter!"); chain.doFilter (request, response);} @ Override public void destroy () {}} 2. Priority test
The above two Filter are written directly as Bean. Let's write a simple rest service to test it.
@ RestControllerpublic class IndexRest {@ GetMapping (path = {"/", "index"}) public String hello (String name) {return "hello" + name;}} @ SpringBootApplicationpublic class Application {public static void main (String [] args) {SpringApplication.run (Application.class);}}
The output result after the request is as follows, and ReqFilter gives priority to the execution.
ii. Source code analysis
When we use Filter directly as Spring Bean, there is no problem with the @ Order annotation to specify the priority of Filter, but the @ WebFilter annotation demonstrated in the previous blog post will not take effect
What is the difference between the two ways?
What is the use of @ Order annotations and how to use them
1. Bean mode
First of all, let's analyze the use of Filter as Spring bean, and our goal is on the registration logic of Filter.
The first step is to target: org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#selfInitialize
The following logic includes the initialization of ServeltContext, and our Filter can be thought of as a Bean belonging to Servlet
Private void selfInitialize (ServletContext servletContext) throws ServletException {prepareWebApplicationContext (servletContext); ConfigurableListableBeanFactory beanFactory = getBeanFactory (); ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes (beanFactory); WebApplicationContextUtils.registerWebApplicationScopes (beanFactory, getServletContext ()); existingScopes.restore (); WebApplicationContextUtils.registerEnvironmentBeans (beanFactory, getServletContext ()) For (ServletContextInitializer beans: getServletContextInitializerBeans ()) {beans.onStartup (servletContext);}}
Notice the for loop in the above code. When getServletContextInitializerBeans () is executed, the Filter has already been registered, so we need to go deeper.
Focus on org.springframework.boot.web.servlet.ServletContextInitializerBeans#ServletContextInitializerBeans
Public ServletContextInitializerBeans (ListableBeanFactory beanFactory) {this.initializers = new LinkedMultiValueMap (); addServletContextInitializerBeans (beanFactory); addAdaptableBeans (beanFactory) List sortedInitializers = this.initializers.values () .stream () .flatMap ((value)-> value.stream () .sorted (AnnotationAwareOrderComparator.INSTANCE)) .flat (Collectors.toList ()); this.sortedList = Collections.unmodifiableList (sortedInitializers);}
There are two prominent lines of code above, which have been fished out separately below, so we need to focus on them.
AddServletContextInitializerBeans (beanFactory); addAdaptableBeans (beanFactory)
Come in through the breakpoint and find that the first method is just to register the dispatcherServletRegistration; and then focus on the second one.
SuppressWarnings ("unchecked") private void addAdaptableBeans (ListableBeanFactory beanFactory) {MultipartConfigElement multipartConfig = getMultipartConfig (beanFactory); addAsRegistrationBean (beanFactory, Servlet.class, new ServletRegistrationBeanAdapter (multipartConfig)); addAsRegistrationBean (beanFactory, Filter.class, new FilterRegistrationBeanAdapter ()) For (Class listenerType: ServletListenerRegistrationBean. GetSupportTypes ()) {addAsRegistrationBean (beanFactory, EventListener.class, (Class) listenerType, new ServletListenerRegistrationBeanAdapter ());}}
As you can see from the method name called above, our Filter registration is in addAsRegistrationBean (beanFactory, Filter.class, new FilterRegistrationBeanAdapter ()).
The screenshot above is more core. When creating a FilterRegistrationBean, the final priority is specified according to the order of the Filter.
Then go back to the construction method, sort according to order, and finally determine the priority of Filter.
2. WebFilter mode
Next, let's take a look at why WebFilter doesn't work. When testing according to my project source code, please modify the custom Filter, open the @ WebFilter annotation on the class, delete the @ Component annotation, and open the ServletComponentScan on the Application class.
The path of debug here is not much different from that above, so we should focus on the following construction methods of ServletContextInitializerBeans
When we go into addServletContextInitializerBeans (beanFactory); when we enter debug in this line, we will find that our custom Filter is initialized here, while the previous usage is initialized in the addAdapterBeans () method, as shown in the following figure
Our custom Bean is returned in the call to getOrderedBeansOfType (beanFactory, ServletContextInitializer.class), which means that our custom Filter is considered to be the type of ServletContextInitializer.
Then let's change our goal and see what ReqFilter looks like when he registers.
Key code: org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition
(because there are a lot of bean, we can add conditional breakpoints.)
Through breakpoint debugging, you can know that our custom Filter is registered through WebFilterHandler class scanning. Those who are interested in this piece of pipe can take a closer look at org.springframework.boot.web.servlet.ServletComponentRegisteringPostProcessor#scanPackage.
The above only declares the registration information of Bean, but there is no specific instantiation yet. Let's go back to the previous process and take a look at the example process of Filter.
Private List getOrderedBeansOfType (ListableBeanFactory beanFactory, Class type, Set excludes) {Comparator comparator = (o1, O2)-> AnnotationAwareOrderComparator.INSTANCE.compare (o1.getValue (), o2.getValue ()); String [] names = beanFactory.getBeanNamesForType (type, true, false) Map map = new LinkedHashMap (); for (String name: names) {if (! excludes.contains (name) & &! ScopedProxyUtils.isScopedTarget (name)) {T bean = beanFactory.getBean (name, type) If (! excludes.contains (bean)) {map.put (name, bean);}} List beans = new ArrayList (); beans.addAll (map.entrySet ()) Beans.sort (comparator); return beans;}
Notice that our Filter instance is at T bean = beanFactory.getBean (name, type)
The Filter instance obtained in this way does not update the order property of FilterRegistrationBean with the value of the Order annotation on the ReqFilter class, so this annotation will not take effect
Finally, let's take a look at the fact that through WebFilter, there is no Bean of type ReqFilter.class in the container class, which is different from the previous approach.
iii. Summary
This paper mainly introduces another posture for using Filter, which registers Filter as an ordinary Spring Bean object. In this scenario, you can directly use the @ Order annotation to specify the priority of Filter.
However, in this way, many of the basic properties of our Filter are not easy to set. One solution is to refer to some of the writing methods of Fitler provided by SpringBoot and implement the relevant logic inside Filter.
On the use of filter Filter in SpringBoot web to share here, I hope that the above content can be of some help to you, can learn more knowledge. If you think the article is good, you can share it for more people to see.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.