Nestle Caau
Nestle Caau

Reputation: 91

why spring boot filter call twice?

my spring boot version is 1.5.4,here is my config code

@SpringBootApplication
@Configuration
@RestController
@ServletComponentScan
public class Application {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class, args);
    }

    @RequestMapping("/")
    public String home() {
        System.out.println("test");
        return "Hello World!";
    }

}

here is my servlet filter code

@WebFilter(urlPatterns = "/*")
public class LogFilter implements Filter {


@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    System.out.println("LogFilter");
    chain.doFilter(request, response);
}

//init and destroy

When i visit http://localhost:8080/ console is out print

LogFilter
test
LogFilter <----the second time

why call filter twice?Spring boot Why do this? Is there a relevant document or source reference?where I want him to call once, how can i do it?

update: thx all the problem has been solved

Upvotes: 9

Views: 17222

Answers (6)

ylmzzsy
ylmzzsy

Reputation: 21

Spring Security doesn’t guarantee the filter won’t be called more than once, so we have to take care of this ourselves. The easiest way is to implement the filter using the OncePerRequestFilter class

Here is an example;

public class AuthenticationLoggingFilter extends OncePerRequestFilter {
    private final Logger logger = Logger.getLogger(AuthenticationLoggingFilter.class.getName());

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain)
            throws ServletException, IOException {
        String requestId = request.getHeader("Request-Id");
        logger.info("Successfully authenticated request with id " + requestId);
        filterChain.doFilter(request, response);
    }
}

Upvotes: 1

Johan
Johan

Reputation: 435

Extending answer from @wrathtoliar

If your filter is invoking Spring bean. Make an autowired variable instead of manual java instantiation.

@Autowired
private YourFilter yourFilter;

http.addFilterBefore(yourFilter, BasicAuthenticationFilter.class)

Upvotes: 0

wrathtoliar
wrathtoliar

Reputation: 321

Please check if the class where in you had defined your filter was a bean or a regular class. In case it is a bean/component then you do not have to specifically register the filter in your security configuration for eg by using

http.addFilterBefore(new YourFilter(), BasicAuthenticationFilter.class). 

By registering a bean additionally as mentioned, the same filter will get executed twice.

Upvotes: 21

Yongzhao Zhang
Yongzhao Zhang

Reputation: 131

If you try to log the request url from doFilter method, you'll see why. Here is I create new SpringBoot project and test with doFilter method.

    @Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) servletRequest;
    logger.info(request.getRequestURL().toString());
    filterChain.doFilter(servletRequest,servletResponse);
}

Well, the two urls are

http://localhost:8080/index
http://localhost:8080/favicon.ico

Upvotes: 13

Adrian
Adrian

Reputation: 3134

Answer to the question is in documentation:

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.

Source

Upvotes: 2

Adriaan Koster
Adriaan Koster

Reputation: 16209

I can think of two common reasons for this behavior:

  1. the spring application context is loaded twice by your application
  2. A redirect is causing a second request on the endpoint

Upvotes: 2

Related Questions