我可以在<filter-mapping>里面的<url-pattern>中排除一些具体的url吗?

我想要一些具体的filter应用于除了一个具体(除/specialpath之外的/* )所有的URL。

有没有可能做到这一点?


示例代码:

 <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> 

标准的Servlet API不支持这个function。 您可能希望为Tuckey的一个 (这与Apache HTTPD的mod_rewrite非常相似)使用rewrite-URLfilter,或者在Filter listen /*doFilter()方法中添加一个检查。

 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. } 

您可以根据需要指定要忽略的path作为filter的init-param ,以便您可以在web.xml控制它。 你可以在filter中获取它,如下所示:

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

如果filter是第三方API的一部分,因此无法对其进行修改,则将其映射到更具体的url-pattern ,例如/otherfilterpath/*并在/*上创build一个新的filter,并转发到匹配第三方派对filter。

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

为了避免这个filter会在无限循环中调用自己,你需要让它只在REQUEST上监听(dispatch),而在FORWARD只监听第三方filter。

也可以看看:

  • 如何防止静态资源被映射到/ *的前端控制器servlet处理
  • 如何处理Spring MVC中的静态内容?

我使用了Eric Daugherty所描述的方法:我创build了一个特殊的servlet,总是用403代码来回答,并将其映射放在通用的代码之前。

映射片段:

  <servlet> <servlet-name>generalServlet</servlet-name> <servlet-class>project.servlet.GeneralServlet</servlet-class> </servlet> <servlet> <servlet-name>specialServlet</servlet-name> <servlet-class>project.servlet.SpecialServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>specialServlet</servlet-name> <url-pattern>/resources/restricted/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>generalServlet</servlet-name> <url-pattern>/resources/*</url-pattern> </servlet-mapping> 

和servlet类:

 public class SpecialServlet extends HttpServlet { public SpecialServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.sendError(HttpServletResponse.SC_FORBIDDEN); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.sendError(HttpServletResponse.SC_FORBIDDEN); } } 

当你想阻止一个特定的filter和所有下面的filter时,这种方法是有效的。 它应该工作,如果你如。 想要在servlet容器中将一些内容作为静态资源提供,而不是让你的应用程序逻辑(通过像GuiceFilter这样的filter):

将文件夹与您的静态资源文件映射到默认的servlet。 创build一个servletfilter,并把它放在你的web.xml中的GuiceFilter 之前 。 在您创build的filter中,您可以在将一些请求转发给GuiceFilter和其他人之间直接分配给调度员。 示例如下…

web.xml中

 <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/static/*</url-pattern> </servlet-mapping> <filter> <filter-name>StaticResourceFilter</filter-name> <filter-class>com.project.filter.StaticResourceFilter</filter-class> </filter> <filter-mapping> <filter-name>StaticResourceFilter</filter-name> <url-pattern>/static/*</url-pattern> </filter-mapping> <filter> <filter-name>guiceFilter</filter-name> <filter-class>com.google.inject.servlet.GuiceFilter</filter-class> </filter> <filter-mapping> <filter-name>guiceFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> 

StaticResourceFilter.class

 public class StaticResourceFilter implements Filter { private final static Logger LOGGER = LoggerFactory.getLogger(StaticResourceFilter.class); private static final String RESOURCE_PATH = "/static/"; @Override public void init(final FilterConfig filterConfig) throws ServletException { LOGGER.info("StaticResourceFilter initialized"); } @Override public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { String path = ((HttpServletRequest) request).getServletPath(); if (path.toLowerCase().startsWith(RESOURCE_PATH)) { request.getRequestDispatcher(path).forward(request, response); } else { chain.doFilter(request, response); } } @Override public void destroy() { LOGGER.info("StaticResourceFilter destroyed"); } } 

不幸的是,如果你只是想在filter链中跳过一个单独的步骤,而保持下面的步骤,这是行不通的。

我不认为你可以,唯一的其他configuration替代scheme是枚举你想过滤的path,所以而不是/*你可以添加一些/this/*/that/*等,但是赢得了'当你有很多这样的path时,这将导致足够的解决scheme。

你可以做的是向filter添加一个参数,提供一个expression式(就像正则expression式),用来跳过匹配path的过滤function。 servlet容器仍然会为你的filter调用这些URL,但是你可以更好地控制configuration。

编辑

现在你提到你没有控制filter,你可以做的是从filter中调用super方法inheritance,除非你想跳过的urlpath存在,并按照@BalusC提出的filter链,或者build立一个filter,在相同的情况下实例化你的filter和委托。 在这两种情况下,filter参数都会包含您添加的expression式参数以及您从中inheritance或委派给的filter的参数。

构build委托filter(包装器)的优点是可以将包装filter的filter类添加为参数,并在其他情况下重用它。

我也不得不在Java代码中基于URL模式(/ {servicename} / api / stats /)进行过滤。

 if (path.startsWith("/{servicename}/api/statistics/")) { validatingAuthToken(((HttpServletRequest) request).getHeader("auth_token")); filterChain.doFilter(request, response); } 

但是奇怪的是,这个servlet不支持除(/ *)以外的url模式,这对于servlet API来说应该是一个很常见的情况!

我遇到了同样的问题,但是我发现下面显示了一个链接。

web.xml中

  <!-- set this param value for the filter--> <init-param> <param-name>freePages</param-name> <param-value> MainFrame.jsp; </param-value> </init-param> 

filter.java

 strFreePages = config.getInitParameter("freePages"); //get the exclue pattern from config file isFreePage(strRequestPage) //decide the exclude path 

这样你就不必骚扰具体的Filter类。