how to autowire bean in the servlet filters in spring application?
Asked Answered
M

2

6

I have a spring-boot application.

I have no ApplicationContext.xml or web.xml files in my project. I prefer to avoid them and have everything configured in Java code.

I have read the following the posts about bean injection in servlet filters.

  1. How can I get a Spring bean in a servlet filter?

  2. http://www.deadcoderising.com/2015-05-04-dependency-injection-into-filters-using-delegatingfilterproxy/

  3. spring injection in servlet filter

After reading them, I started to use DelegatingFilterProxy.

My question is how to autowire the bean into filter and avoid using xml files especially for DelegatingFilterProxy configuration.

The code snipped is available from the second post hosted in github.

public class AuditHandler {

    public void auditRequest(String appName, ServletRequest request) {
        System.out.println(appName + ": Received request from " + request.getRemoteAddr() );
    }
}

public class AuditFilter implements Filter {

    private final AuditHandler auditHandler;
    private String appName;

    public AuditFilter(AuditHandler auditHandler) {
        this.auditHandler = auditHandler;
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        auditHandler.auditRequest(appName, request);
        chain.doFilter(request, response);
    }

    public void init(FilterConfig filterConfig) throws ServletException {
        appName = filterConfig.getInitParameter("appName");
    }

    public void destroy() {}
}

ApplicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd">


    <bean id="auditHandler" class="com.deadcoderising.AuditHandler">
    </bean>

    <bean id="auditFilter" class="com.deadcoderising.AuditFilter">
        <constructor-arg ref="auditHandler"/>
    </bean>
</beans>

web.xml

<web-app version="3.0"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         metadata-complete="true">

    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:applicationContext*.xml</param-value>
    </context-param>


    <filter>
        <filter-name>auditFilter</filter-name>
        <filter-class>
            org.springframework.web.filter.DelegatingFilterProxy
        </filter-class>
        <init-param>
            <param-name>targetFilterLifecycle</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>appName</param-name>
            <param-value>di-example</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>auditFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>
Mainis answered 20/8, 2015 at 19:59 Comment(0)
F
8

You should add a FilterRegistrationBean to your main Application class (class annotated with @SpringBootApplication) and let Spring provide instance of the AuditHandler:

@Bean
@Autowired
public FilterRegistrationBean auditFilterRegistration(AuditHandler handler) {
    FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
    filterRegistrationBean.setFilter(new AuditFilter(handler));
    filterRegistrationBean.setOrder(3); // ordering in the filter chain
    return filterRegistrationBean;
}

If this doesn't work (e.g. your AuditHandler implementation is not annotated properly or it's not on the default package scanning path) you can instruct Spring to provide it (also in your @SpringBootApplication annotated class):

@Bean
public AuditHandler auditHandler() {
    return new AuditHandlerImplementation();
}
Fronde answered 20/8, 2015 at 21:6 Comment(6)
if I have a number of filters to be applied, how is the order specified?Mainis
FilterRegistrationBean#setOrder(int), I have updated the answer.Fronde
Thanks, I will test this nowMainis
how can I do the same in non-spring boot application. There is no FilterRegistrationBean available in spring MVCMainis
The filter can also be registered in the same way in a configuration class (class annotated with @Configuration)Haleakala
@Fronde how register multiple filters on different URLs? If set() sets one.Hurried
F
0

Add the following code into the init method of your filter class.

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);

So the init method will look like:

    public void init(FilterConfig filterConfig) throws ServletException {
        appName = filterConfig.getInitParameter("appName");
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
    }

Now, you can use @Autowired or @Inject or @Resource anotation to inject the dependency (bean) into the filter class.

Fowl answered 28/8, 2023 at 15:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.