Tomcat 在/static/*上下文中提供静态资源,同时保持servlet处理/*上下文

Tomcat 在/static/*上下文中提供静态资源,同时保持servlet处理/*上下文,tomcat,servlets,servlet-container,Tomcat,Servlets,Servlet Container,我的问题很简单。我想让我的静态资源服务于/static/*上下文,但我的特定servlet服务于/*上下文。因为/static/*是/*的子集,所以它不起作用。 My web.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.

我的问题很简单。我想让我的静态资源服务于
/static/*
上下文,但我的特定servlet服务于
/*
上下文。因为
/static/*
/*
的子集,所以它不起作用。 My web.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>  

模板guice-jersey-tomcat
30
index.jsp
guiceFilter
com.google.inject.servlet.GuiceFilter
guiceFilter
/*
违约
/静态/*
de.danbim.templateguicejerseytomcat.GuiceServletConfig

这个问题有一个非常清晰的解决方案:

不幸的是,在查看DefaultServlet源代码后,我发现DefaultServlet只获取请求URL的pathInfo部分,所以如果您的请求是/static/styles.css,容器会将其转换为/styles.css。DefaultServlet省略了Servlet部分。如果要访问此类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>

违约
违约
pl.kuligowski.example.DefaultFilter
违约
/静态/*
*.ico
只有静态内容调用与DefaultFilter匹配,DefaultFilter只会断开筛选器链并将请求转发给DefaultServlet


对我来说,这在Tomcat8.5中起作用(我甚至没有web.xml):

更具体的url模式似乎自动获得优先权。要扩展catalina默认servlet,请将
org.apache.tomcat>tomcat catalina
maven依赖项和提供的
范围添加到项目中

您(和我一样)可能会立即遇到这样一个问题:仅对应用程序上下文的请求在解析html中的相对路径(例如样式表和Java脚本)时遇到问题

我通过主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;
    }

    //...
  }

仅仅扩展DefaultServlet就可以让我不用为问题寻找解决方案。
  @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;
    }

    //...
  }