SpringBoot : How to integrate a Filter in Spring Boot Application

What is a Filter : 

A Filter is an object that performs filtering tasks on either the request to a resource (a servlet or static content), or on the response from a resource, or both. Filters perform filtering in the doFilter method. Every Filter has access to a FilterConfig object from which it can obtain its initialization parameters, a reference to the ServletContext which it can use, for example, to load resources needed for filtering tasks. In this article we will see how to integrate a Filter with a spring boot application. Following are the methods in a Filter:

Method Summary Method Description
 void

destroy() Called by the web container to indicate to a filter that it is being taken out of service.

 void

doFilter(ServletRequest request, ServletResponse response, FilterChain chain)     

The doFilter method of the Filter is called by the container each time a request/response pair is passed through the chain due to a client request for a resource at the end of the chain.

 void

init(FilterConfig filterConfig) 

Called by the web container to indicate to a filter that it is being placed into service.

In our Filter WebFilter we will intercept the request in doFilter method and add a header parameter named remote_addr in the Request. And we will try to retreive the same header parameter in our controller class to ensure that our Filter implementation is working. Following is our filter implementation.

package com.tuturself.spring.boot.filter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class WebFilter implements Filter {

	private static final Logger logger = LoggerFactory.getLogger(WebFilter.class);
	
	private static final boolean CONDITION = true;
	
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		logger.debug("Initiating WebFilter >> ");
	}
	
	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		if (CONDITION == true) {
			HttpServletRequest req = (HttpServletRequest) request;
			HeaderMapRequestWrapper requestWrapper = new 
					HeaderMapRequestWrapper(req);
			String remote_addr = request.getRemoteAddr();
			requestWrapper.addHeader("remote_addr", remote_addr);
            // Goes to default servlet
			chain.doFilter(requestWrapper, response); 
		} else {
			((HttpServletResponse) response)
				.setStatus(HttpServletResponse.SC_BAD_REQUEST);
		}
	}
	
	@Override
	public void destroy() {
		logger.debug("Destroying WebFilter >> ");
	}
}

The filter is registered by @Component annotation. The @Order(Ordered.HIGHEST_PRECEDENCE)  is used for Advice execution precedence. The highest precedence advice runs first. The lower the number, the higher the precedence. For example, given two pieces of 'before' advice, the one with highest precedence will run first. If you have multiple filters then we can use numeric numbers to specify the order like 

@Component
@Order(2)
public class WebFilter implements Filter {
   
}

@Component
@Order(1)
public class AnotherWebFilter implements Filter {
   
}

Now we need to create our own HttpServletRequestWrapper for adding a new header parameter in request. Following is the HeaderMapRequestWrapper.

package com.tuturself.spring.boot.filter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.*;


public class HeaderMapRequestWrapper extends HttpServletRequestWrapper {
    /**
     * construct a wrapper for this request
     *
     * @param request
     */
    public HeaderMapRequestWrapper(HttpServletRequest request) {
        super(request);
    }

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

    /**
     * add a header with given name and value
     *
     * @param name
     * @param value
     */
    public void addHeader(String name, String value) {
        headerMap.put(name, value);
    }

    @Override
    public String getHeader(String name) {
        String headerValue = super.getHeader(name);
        if (headerMap.containsKey(name)) {
            headerValue = headerMap.get(name);
        }
        return headerValue;
    }

    /**
     * get the Header names
     */
    @Override
    public Enumeration<String> getHeaderNames() {
        List<String> names = Collections.list(super.getHeaderNames());
        for (String name : headerMap.keySet()) {
            names.add(name);
        }
        return Collections.enumeration(names);
    }

    @Override
    public Enumeration<String> getHeaders(String name) {
        List<String> values = Collections.list(super.getHeaders(name));
        if (headerMap.containsKey(name)) {
            values.add(headerMap.get(name));
        }
        return Collections.enumeration(values);
    }
}

Now create our Controller class where we will check that the header is added correctly in the Request.

package com.tuturself.spring.boot.filter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test")
public class WebApi {

    private static final Logger logger = LoggerFactory.getLogger(WebApi.class);

    @RequestMapping(method = RequestMethod.GET)
    public ResponseEntity<Object> doSomething(@RequestHeader(name = "remote_addr") 
    	String remoteAddress) {
        logger.debug("The Remote address added by WebFiler is :: {}", remoteAddress);
        ResponseEntity<Object> response = null;
        try {
            response = new ResponseEntity<Object>("SUCCESS", HttpStatus.OK);
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
            return new ResponseEntity<Object>(ex.getMessage(), 
            		HttpStatus.INTERNAL_SERVER_ERROR);
        }
        return response;
    }
}

Here in the doSomething() method we retrieve the header parameter that we added in the Filter by:

@RequestHeader(name = "remote_addr") String remoteAddress

Download the whole project from GitHub : Download link

Servlet 12 Spring Boot 12

FOLLOW US ON LinkedIn



Explore Tutu'rself