Reputation: 91
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
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
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
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
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
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.
Upvotes: 2
Reputation: 16209
I can think of two common reasons for this behavior:
Upvotes: 2