views:

56

answers:

2

I want some concrete filter to be applied for all urls except for one concrete (i.e. for /* except for /specialpath).

Is there a possibility to do that?


sample code:

<filter>
    <filter-name>SomeFilter</filter-name>
    <filter-class>org.somproject.AFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>SomeFilter</filter-name>
    <url-pattern>/*</url-pattern>   <!-- the question is: how to modify this line?  -->
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>
+1  A: 

The standard Servlet API doesn't support this facility. You may want either to use a rewrite-URL filter for this like Tuckey's one (which is much similar Apache HTTPD's mod_rewrite), or to add a check in the doFilter() method of the Filter listening on /*.

String path = ((HttpServletRequest) request).getRequestURI();
if (path.startsWith("/specialpath")) {
    chain.doFilter(request, response); // Just continue chain.
} else {
    // Do your business stuff here for all paths other than /specialpath.
}

You can if necessary specify the paths-to-be-ignored as an init-param of the filter so that you can control it in the web.xml anyway. You can get it in the filter as follows:

private String pathToBeIgnored;

public void init(FilterConfig config) {
    pathToBeIgnored = config.getInitParameter("pathToBeIgnored");
}

Update the filter seems to be 3rd party API (you should have mentioned that in your question). In that case, map it on a more specific url-pattern, e.g. /otherfilterpath/* and let your filter which is listening on /* forward to that.

String path = ((HttpServletRequest) request).getRequestURI();
if (path.startsWith("/specialpath")) {
    chain.doFilter(request, response); // Just continue chain.
} else {
    request.getRequestDispatcher("/otherfilterpath" + path).forward(request, response);
}

Update 2: oh, I almost forget to add, to avoid that this filter will call itself in an infinite loop you need to let it listen (dispatch) on REQUEST only and the 3rd party filter on FORWARD only.

BalusC
My problem is that the filter is not mine, it's from component library.
Roman
A: 

I don't think you can, the only other configuration alternative is to enumerate the paths that you want to be filtered, so instead of /* you could add some for /this/* and /that/* etc, but that won't lead to a sufficient solution when you have alot of those paths.

What you can do is add a parameter to the filter providing an expression (like a regular expression) which is used to skip the filter functionality for the paths matched. The servlet container will still call your filter for those url's but you will have better control over the configuration.

Edit

Now that you mention you have no control over the filter, what you could do is either inherit from that filter calling super methods in its methods except when the url path you want to skip is present and follow the filter chain like @BalusC proposed, or build a filter which instantiates your filter and delegates under the same circumstances. In both cases the filter parameters would include both the expression parameter you add and those of the filter you inherit from or delegate to.

The advantage of building a delegating filter (a wrapper) is that you can add the filter class of the wrapped filter as parameter and reuse it in other situations like this one.

rsp