问题
我想要一些具体的过滤器应用于除一个混凝土之外的所有网址(即for282476135except/specialpath
)。
有可能这样做吗?
示例代码:
<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 热门回答(134 赞)
标准Servlet API不支持此功能。你可能希望对此使用重写URL过滤器,如Tuckey's one(与Apache HTTPD的mod_rewrite
非常相似),或者在监听/*
的过滤器的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.
}
你可以根据需要指定要忽略的路径作为过滤器的init-param
,以便你可以在web.xml
中控制它。你可以在过滤器中获取它,如下所示:
private String pathToBeIgnored;
public void init(FilterConfig config) {
pathToBeIgnored = config.getInitParameter("pathToBeIgnored");
}
如果过滤器是第三方API的一部分,因此你无法对其进行修改,则将其映射到更具体的url-pattern
,例如:/otherfilterpath/*
,并在/*
上创建一个新过滤器,该过滤器将转发到与第三方过滤器匹配的路径。
String path = ((HttpServletRequest) request).getRequestURI();
if (path.startsWith("/specialpath/")) {
chain.doFilter(request, response); // Just continue chain.
} else {
request.getRequestDispatcher("/otherfilterpath" + path).forward(request, response);
}
为避免此过滤器在无限循环中调用自身,你需要让它在REQUEST
上进行侦听(调度),并且仅在第二方过滤器上调用FORWARD
。
也可以看看:
- 如何防止映射在/ *上的前端控制器servlet处理静态资源
- 如何在Spring MVC中处理静态内容?
#2 热门回答(12 赞)
我使用了一种方法described by Eric Daugherty:我创建了一个特殊的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);
}
}
#3 热门回答(5 赞)
当你想要阻止某个过滤器和所有以下过滤器时,此方法有效。如果你这样做应该会很好。想要将一些内容作为servlet容器中的静态资源提供,而不是让你的应用程序逻辑(通过像GuiceFilter这样的过滤器):
将包含静态资源文件的文件夹映射到默认servlet。创建一个servlet过滤器并将其放在web.xml中的GuiceFilter之前。在你创建的过滤器中,你可以将一些请求转发到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");
}
}
不幸的是,如果你只想跳过过滤器链中的一个步骤,同时保留随后的步骤,这将不起作用。