Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring MVC - Exclude assets from all interceptors

I'm trying to figure out a way to avoid having to exclude static content from all interceptors instead of having to specify an exclude-mapping tag for each interceptor that should ignore these. Part of my context.xml is as follows:

<mvc:resources mapping="/assets/**" location="/assets/"/>

<mvc:interceptors>

    <bean class="com.myapp.security.interceptor.SecurityInterceptor" />

    <mvc:interceptor>
        <mvc:mapping path="/**" />
        <mvc:exclude-mapping path="/assets/**" />
        <bean class="com.myapp.interceptor.MessageInterceptor" />
    </mvc:interceptor>

</mvc:interceptors>

As you can see, I've specified /assets/ from being excluded from the MessageInterceptor. However, I also want SecurityInterceptor to exclude resources as well. Following DRY, it seems unreasonable to have to specify an exclude-mapping for every interceptor (since there should never really be a reason to intercept resources).

I've searched around and could not find any solutions. Any help is appreciated!

Thanks

like image 923
Mike Avatar asked Aug 23 '13 14:08

Mike


1 Answers

I'm struggling to think of any method to achieve what you want in configuration. Perhaps someone else can offer a solution.

A quick code solution which would achieve what you want would be something like:

public abstract class ResourceExcludingHandlerInterceptor implements HandlerInterceptor
{

     @Override
     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception
     {
          if (!isResourceHandler(handler))
          {
             doAfterCompletion(request, response, handler, ex);
          }
     }

     public abstract void doAfterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception;

     public abstract void doPostHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception;

     public abstract boolean doPreHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

     /**
     * <p>
         * Determine if the request is about to be handled by a mapping configured
     * by <mvc:resources>
     * </p>
     * 
     * @param handler
     *            - the handler to inspect
     * @return - true if this is a <mvc:resources> mapped request, false
     *         otherwise
     */
     private boolean isResourceHandler(Object handler)
     {
         return handler instanceof ResourceHttpRequestHandler;
     }

     @Override
     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception
     {
         if (!isResourceHandler(handler))
         {
             doPostHandle(request, response, handler, modelAndView);
         }
     }

     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
     {
         return isResourceHandler(handler) ? true : doPreHandle(request, response, handler);
     }
 }

You could then have your HandlerInterceptor implementations extend this abstract class. As <mvc:resources> is basically a short-hand way of registering ResourceHttpRequestHandler instances, this would ensure that your HandlerInterceptor implementations simply ignore any requests mapped to be handled by one.

like image 164
Rob Blake Avatar answered Nov 09 '22 14:11

Rob Blake