【问题标题】:Spring 3.2 - AbstractAnnotationConfigDispatcherServletInitializer onStartup - adding a servlet filter returns nullSpring 3.2 - AbstractAnnotationConfigDispatcherServletInitializer onStartup - 添加 servlet 过滤器返回 null
【发布时间】:2014-05-20 09:04:00
【问题描述】:

我有一个纯 JavaConfig Java webapp,它使用从 AbstractAnnotationConfigDispatcherServletInitializer 扩展的类。它非常适合配置我的调度程序 servlet,但我的调度程序 servlet 仅映射到具有 url 模式“/rest/*”的请求。对于所有其他请求(即 css、html、js 等),没有 spring 映射,一切都通过默认的 servlet。对于这些请求,我想实现一个 GZip 过滤器。我在许多项目中使用了多年前在网上找到的自定义 gzip 过滤器。

通过 JavaConfig 实现,我了解到受保护的 Filter[] getServletFilters() 方法适用于调度程序 serlvet...这是不正确的吗?

我现在要做的是将 gzip 过滤器应用于任何不发送到调度程序 servlet 的请求。我像这样覆盖 onStartup 方法:

@Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        super.onStartup(servletContext);      
        FilterRegistration.Dynamic encodingFilter = servletContext.addFilter("encodingFilter", new CharacterEncodingFilter());
        encodingFilter.setInitParameter("encoding", "UTF-8");
        encodingFilter.setInitParameter("forceEncoding", "true");
        encodingFilter.addMappingForUrlPatterns(null, true, "/*");

        FilterRegistration.Dynamic gzipFilter = servletContext.addFilter("gzipFilter", new GzipFilter());
        gzipFilter.addMappingForUrlPatterns(null, true, "/*");   
    }

编码过滤器工作正常,但是当我添加映射时 GzipFilter 上出现 NullPointerException ...... servletContext.addFilter 返回 null。我想我的自定义类和新的 JavaConfig 实现可能有些奇怪,所以我在网上发现人们正在使用 ehacache-web 包中包含的 gzip 过滤器,所以我将其添加为依赖项并尝试使用该过滤器代替.同样... CharacterEncodingFilter 工作正常,addFilter 方法正确返回 FilterRegistration.Dynamic 对象,但是 gzip 过滤器仍然返回 null。

任何想法是什么原因造成的?

编辑:

这是我的整个配置文件:

public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        super.onStartup(servletContext);

        FilterRegistration.Dynamic encodingFilter = servletContext.addFilter("encodingFilter", new CharacterEncodingFilter());
        encodingFilter.setInitParameter("encoding", "UTF-8");
        encodingFilter.setInitParameter("forceEncoding", "true");
        encodingFilter.addMappingForUrlPatterns(null, true, "/*");

        FilterRegistration.Dynamic gzipFilter = servletContext.addFilter("gzipFilter", new GzipFilter());
        gzipFilter.addMappingForUrlPatterns(null, true, "/*");


    }

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SecurityConfig.class, Log4jConfig.class, PersistenceConfig.class, ServiceConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{
            "/rest/*",
            "/index.html",
            "/login.html",
            "/admin.html",
            "/index/*",
            "/login/*",
            "/admin/*"
        };
    }

    @Override
    protected Filter[] getServletFilters() {
        OpenEntityManagerInViewFilter openEntityManagerInViewFilter = new OpenEntityManagerInViewFilter();
        openEntityManagerInViewFilter.setBeanName("openEntityManagerInViewFilter");
        openEntityManagerInViewFilter.setPersistenceUnitName("HSQL");

        return new javax.servlet.Filter[]{openEntityManagerInViewFilter};
    }

}

无论我是否将 GzipFilter 添加到 getServletFilters() 或使用 URL 映射“/*”从 servletContext.addFilter() 创建 FilterRegistration.Dynamic,只有通过调度程序 servlet 处理的请求才会被压缩。

编辑 2:

这是一个未被压缩的 URL:

http://localhost:8084/swtc/js/ServiceWidget/templates/ServiceWidget.html

Response Headers
Accept-Ranges   bytes
Content-Length  399
Content-Type    text/html
Date    Mon, 07 Apr 2014 18:47:08 GMT
Etag    W/"399-1377195848751"
Last-Modified   Thu, 22 Aug 2013 18:24:08 GMT
Server  Apache-Coyote/1.1

这是一个正在压缩的 URL:

http://localhost:8084/swtc/rest/mapServices/getEnabledServices

Response Headers
Content-Encoding    gzip
Content-Length  76
Content-Type    application/json;charset=UTF-8
Date    Tue, 08 Apr 2014 18:34:11 GMT
Server  Apache-Coyote/1.1

是否可以将调度程序 serlvet 映射更改为 /* 并将我的 js、css、img 等文件夹定义为资源?我觉得这是在回避这个问题......很高兴知道为什么我可以像以前在 web.xml 中那样指定一个与 Spring 无关的过滤器。

【问题讨论】:

  • 请发布您的完整堆栈跟踪和其余配置。
  • 这只是一个 NullPointerException。在生成 NPE 之前,servletContext.addFilter 方法返回 null,此时它应该返回 FilterRegistration.Dynamic。当 gzipFilter 为空时,NPE 是由于尝试在 gzipfilter 上调用 addMappingforUrlPatterns 而产生的。

标签: java spring spring-mvc servlet-filters spring-java-config


【解决方案1】:

你没有给我们我想要的那么多,但这就是 ServletContext#addFilter(String, Filter) 的 javadoc 所说的

返回:一个FilterRegistration 对象,可用于进一步 配置给定的过滤器,null 如果这个 ServletContext 已经 包含给定过滤器的完整FilterRegistration filterName 或者如果已经注册了相同的过滤器实例 在同一个容器中使用这个或另一个 ServletContext

您似乎已经注册了 Filter 或其他同名的用户。

【讨论】:

  • 检查上下文对象显示有一个 gzip 过滤器,我在 getServletFilters 方法中注册它...所以我猜我的假设是受保护的 Filter[] getServletFilters() 方法仅适用于过滤器对于调度程序 servlet... 或者传递给 onStartup(ServletContext servletContext) 方法的 servlet 上下文是调度程序 servlet 上下文。不管怎样,我现在有一个很好的办法来解决这个问题。感谢您的回答!
  • @Bal Servlet 容器为其每个 Web 应用程序仅提供一个 ServletContext 对象。不要被容器提供的ServletContextDispatcherServlet加载的ApplicationContext所迷惑,即。 Spring 称之为 servlet 上下文。
  • 感谢您的信息!我在重写的 getServletFilters() 方法中添加了一个新的 gzip 过滤器实例,但是我认为它只映射到调度程序 servlet 请求,因为我无法指定 URL 模式,在我的情况下,它只是模式 /rest/ 的 url *。我将其删除并使用“/*”模式将其直接添加到 ServletContext 对象中,但仍然只有来自调度程序 servlet 的请求被压缩。对我的 /js 或 /css 文件夹的任何请求都不会被压缩。有什么想法吗?
  • @Bal 你能发布相关配置作为编辑吗? /* 将匹配所有请求,包括由调度程序 servlet 处理的请求。我不知道为什么他们不匹配你的其他人。此外,请举例说明您看到的匹配的网址和不匹配的网址。
  • 非常感谢您的帮助。我已经发布了我的 Web 配置和示例 URL,以及它们相应的响应标头。如果您想看其他内容,请告诉我。
猜你喜欢
  • 1970-01-01
  • 2017-02-21
  • 2013-04-09
  • 1970-01-01
  • 2018-09-08
  • 2014-10-02
  • 2015-11-19
  • 2014-11-26
  • 2019-01-29
相关资源
最近更新 更多