8. Servlet Architecture Overview

8.1 Servlet Architecture Overview

Spring Security’s servlet support relies on the servlet Filter API. This means that it can work with any application that runs in a servlet container. It does not require that you use Spring in any other part of your application.

8.1.1 Understanding the Servlet Filter API

Spring Security’s servlet container support (whether you run in Apache Tomcat or other servlet container) is built on top of the Filter API. This is done because the Filter API is a standard that allows injecting logic into an application in any servlet container.

Since Spring Security is built on top of javax.servlet.Filter objects. It will greatly benefit you if you understand the concept of interceptors and how Filter objects work.

The following example shows a simple Filter implementation:

Example 8.1. SimpleFilter Example

public class SimpleFilter implements Filter {

    public void init(FilterConfig filterConfig)
            throws ServletException {
            // optional initialization
    }

    // invoked every request the Filter is mapped for
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("Before"); 1
        chain.doFilter(request, response); 2
        System.out.println("After"); 3
    }

    public void destroy() {
        // optional cleanup
    }
}

1

Happens before the application is invoked.

2

Invokes the rest of the application. This could be additional Filter objects, a Servlet, or both.

3

Happens after the application is invoked


[Important]Important

If chain.doFilter is never invoked, neither is the rest of the application.

A servlet Filter lets us apply logic around the rest of the application. This means that we can perform logic before, conditionally invoke the rest of the application, and perform logic afterwards in any servlet container.

8.1.2 Registering a Servlet Filter

In order for a servlet Filter to be invoked, it must be registered with the servlet container.

The following example shows how to do so in XML:

Example 8.2. web.xml

1
<filter>
    <filter-name>simpleFilter</filter-name>
    <filter-class>sample.SimpleFilter</filter-class>
</filter>

2
<filter-mapping>
    <filter-name>simpleFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

1

Define the Filter to be mapped

2

Provide one or more mappings for the Filter. In this case, simpleFilter is mapped by using the /* pattern, which signifies that it should be mapped for every request.


In Java configuration, you can use a ServletContextListener. The following example shows how to do so:

Example 8.3. RegisterServletContextListener.java

@WebListener
public class FilterStartupListener
        implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        ServletContext ctx = sce.getServletContext();

        1
        FilterRegistration fltrReg = ctx.addFilter("simpleFilter", SimpleFilter.class);

        2
        EnumSet<DispatcherType> dispatchers =
            EnumSet.of(DispatcherType.REQUEST);
        3
        boolean isMatchAfter = true;
        4
        fltrReg.addMappingsForUrlPatterns(dispatchers, isMatchAfter, "/*");
    }
}

1

Define the Filter to be mapped.

2

In Java configuration, we must explicitly provide the Section 8.1.3, “Dispatch Types”.

3

In Java configuration, we must explicitly indicate whether the Filter should be before or after already registered Filter objects.

4

Provide one more mapping for the Filter. In this case, simpleFilter is mapped by using the /* pattern, which signifies that it should be mapped for every request.


8.1.3 Dispatch Types

8.1.4 Filter Ordering

8.1.5 Using DelegatingFilterProxy

At the heart of integrating Spring with a servlet Filter is the DelegatingFilterProxy. The DelegatingFilterProxy is registered directly with the servlet container, and it delegates all work to a Spring Bean that implements Filter.