我的问题很简单。我希望我的静态资源/static/*
上下文中提供服务,但我的特定 servlet /*
上下文中提供服务。由于/static/*
是/*
的子集,因此不起作用。我的网站.xml看起来像这样:
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>template-guice-jersey-tomcat</display-name>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- set up Google Guice Servlet integration -->
<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>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/static/*</url-pattern>
</servlet-mapping>
<listener>
<listener-class>de.danbim.templateguicejerseytomcat.GuiceServletConfig</listener-class>
</listener>
</web-app>
这是这个问题的非常干净的解决方案: http://www.kuligowski.pl/java/rest-style-urls-and-url-mapping-for-static-content-apache-tomcat,5:
不幸的是,在查看了 DefaultServlet 源代码后,我发现 DefaultServlet 只占用请求 URL 的 pathInfo 部分,所以如果你的请求是/static/styles.css,容器会将其转换为/styles.css。Servlet 部分被 DefaultServlet 省略。如果你想访问这样的css文件,你应该使用/static/static/styles.css请求url。
我们问题的简单解决方案是编写 DefaultFilter 类并将其放在 web.xml 文件的开头。此过滤器会将所有静态内容调用转发到 DefaultServlet。
定义一个过滤器,它将请求调度到默认 servlet:
public class DefaultFilter implements Filter {
private RequestDispatcher defaultRequestDispatcher;
@Override
public void destroy() {}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
defaultRequestDispatcher.forward(request, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.defaultRequestDispatcher =
filterConfig.getServletContext().getNamedDispatcher("default");
}
}
将过滤器(在其他过滤器之前)添加到 web.xml:
<filter>
<filter-name>default</filter-name>
<servlet-name>default</servlet-name>
<filter-class>pl.kuligowski.example.DefaultFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>default</filter-name>
<url-pattern>/static/*</url-pattern>
<url-pattern>*.ico</url-pattern>
</filter-mapping>
只有静态内容调用与 DefaultFilter 匹配,它只是中断过滤器链并将请求转发到 DefaultServlet。
,这在Tomcat 8.5中有效(我什至没有网络了.xml了):
@WebServlet(urlPatterns = "/*")
public class MainServlet {}
@WebServlet(urlPatterns = { "/static/*", "/gwt/*" })
public class StaticServlet extends org.apache.catalina.servlets.DefaultServlet {}
更具体的 url 模式似乎会自动获得优先级。要扩展 catalina 默认 servlet,请将具有范围provided
org.apache.tomcat > tomcat-catalina
maven 依赖项添加到项目中。
您可能会(像我一样)立即遇到这样的问题:仅对应用程序上下文的请求在解析 html 中的相对路径(例如样式表和 javascript)时遇到问题。
我通过主servlet中的重定向解决了这个问题:
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if(request.getPathInfo() == null) {
// redirect http://localhost:8080/test -> http://localhost:8080/test/ (add trailing slash)
// because only then are the relative paths to the gwt scripts correctly resolved
getResponse().sendRedirect(getRequest().getContextPath() + "/");
return;
}
//...
}