Make simple servlet filter work with @ControllerAdvice
As specified by the java servlet specification Filter
s execute always before a Servlet
is invoked. Now a @ControllerAdvice
is only useful for controller which are executed inside the DispatcherServlet
. So using a Filter
and expecting a @ControllerAdvice
or in this case the @ExceptionHandler
, to be invoked isn't going to happen.
You need to either put the same logic in the filter (for writing a JSON response) or instead of a filter use a HandlerInterceptor
which does this check. The easiest way is to extend the HandlerInterceptorAdapter
and just override and implement the preHandle
method and put the logic from the filter into that method.
public class ClientKeyInterceptor extends HandlerInterceptorAdapter {
@Value('${CLIENT_KEY}')
String clientKey
@Override
public boolean preHandle(ServletRequest req, ServletResponse res, Object handler) {
String reqClientKey = req.getHeader('Client-Key')
if (!clientKey.equals(reqClientKey)) {
throw new AccessForbiddenException('Invalid API key')
}
return true;
}
}
You can't use @ControllerAdvice
, because it gets called in case of an exception in some controller, but your ClientKeyFilter
is not a @Controller
.
You should replace the @Controller
annotation with the @Component
and just set response body and status like this:
@Component
public class ClientKeyFilter implements Filter {
@Value('${CLIENT_KEY}')
String clientKey
public void init(FilterConfig filterConfig) {
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String reqClientKey = request.getHeader("Client-Key");
if (!clientKey.equals(reqClientKey)) {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Invalid API key");
return;
}
chain.doFilter(req, res);
}
public void destroy() {
}
}