当前位置: 首页 > 知识库问答 >
问题:

servlet过滤器在Spring中是如何工作的?

唐经国
2023-03-14

我试图将CORS过滤器添加到SpringWeb应用程序中,但该过滤器未被执行。我在这里遵循了相关步骤:https://spring.io/guides/gs/rest-service-cors/无济于事。我没有用Spring靴。我正在3.0 servlet规范容器中使用Spring的WebApplicationInitializer引导我的应用程序。

我的应用程序中的其他一切都在工作:配置类、控制器、hibernate实体等。

更新1:

通过将过滤器添加到servlet容器,下面的答案对我很有用:

container.addFilter("CorsFilter", CorsFilter.class)
          .addMappingForUrlPatterns(null, false, "/*");

然而,我很好奇为什么SpringBoot不需要这个?他们必须自动搜索过滤器并将其添加到上下文中。有没有一种简单的方法可以做到这一点?似乎很不幸,我必须创建一个过滤器,然后将其添加到另一个类的某个列表中。如果它们像在Spring Boot中那样自动注册,那就太好了。

相关代码片段:

WebApplicationInitializer:

public class AppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) throws ServletException {
        // Create the 'root' Spring application context
        AnnotationConfigWebApplicationContext rootContext =
                new AnnotationConfigWebApplicationContext();
        rootContext.register(AppConfig.class);

        // Manage the lifecycle of the root application context
        container.addListener(new ContextLoaderListener(rootContext));

        // Create the dispatcher servlet's Spring application context
        AnnotationConfigWebApplicationContext dispatcherContext =
                new AnnotationConfigWebApplicationContext();
        dispatcherContext.register(WebAppConfig.class);

        // Register and map the dispatcher servlet
        ServletRegistration.Dynamic dispatcher =
                container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }

}

AppConfig:

@Configuration
@ComponentScan
public class AppConfig {
}

WebAppConfig:

@Configuration
@EnableWebMvc
@EnableSpringDataWebSupport
@ComponentScan(basePackageClasses = AppConfig.class)
public class WebAppConfig extends WebMvcConfigurerAdapter {
}

科斯菲尔特:

@Component
public class CorsFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        HttpServletResponse httpResponse = (HttpServletResponse) response;
        httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
        httpResponse.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
        httpResponse.setHeader("Access-Control-Max-Age", "3600");
        httpResponse.setHeader("Access-Control-Allow-Headers", "x-requested-with, Content-Type");

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String origin = httpRequest.getHeader("Origin");
        if (StringUtils.hasText(origin)) {

            boolean isMyDomain =
                Pattern.compile("^https://(.*?\\.)?mydomain.com(:\\d+)?$")
                        .matcher(origin)
                        .find();
            if (isMyDomain) {
                httpResponse.setHeader("Access-Control-Allow-Origin", origin);
            } else {
                httpResponse.setHeader("Access-Control-Allow-Origin", "mydomain");
            }

        }
        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        LoggerFactory.getLogger(getClass()).info("CorsFilter initiated");
    }

    @Override
    public void destroy() {
        LoggerFactory.getLogger(getClass()).info("CorsFilter destroyed");
    }
}

共有2个答案

杨彦君
2023-03-14

您只需在应用初始值设定项中注册过滤器即可。

public class AppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) throws ServletException {
        // Create the 'root' Spring application context
        AnnotationConfigWebApplicationContext rootContext =
                new AnnotationConfigWebApplicationContext();
        rootContext.register(AppConfig.class);

        // Manage the lifecycle of the root application context
        container.addListener(new ContextLoaderListener(rootContext));

        // Create the dispatcher servlet's Spring application context
        AnnotationConfigWebApplicationContext dispatcherContext =
                new AnnotationConfigWebApplicationContext();
        dispatcherContext.register(WebAppConfig.class);

        // Register and map the dispatcher servlet
        ServletRegistration.Dynamic dispatcher =
                container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");

        //Added filter dynamically
        javax.servlet.FilterRegistration.Dynamic corsFilter = container.addFilter("corsfilter", CORSFilter.class);
        corsFilter.addMappingForUrlPatterns(null, true, "/*");
    }

}

您可以参考这个github存储库。

慕容安易
2023-03-14

你可以这样补充:

container.addFilter("CorsFilter", CorsFilter.class)
          .addMappingForUrlPatterns(null, false, "/*");
 类似资料:
  • 问题内容: 我定义了一个,并且具有带有Spring注释的Java类。 我想将Bean 放入我的,因此尝试了以下操作: 但是它总是返回。我怎样才能得到一个Spring bean? 问题答案: 尝试: 你的bean在应用程序上下文中的名称/标识在哪里。甚至更好: 还可以看看GenericFilterBean及其子类。

  • 我试图理解过滤器链接。正如这个问题所定义的 所有过滤器都被链接(按照它们在web.xml中定义的顺序)。chain.doFilter()正在进行到链中的下一个元素。链的最后一个元素是目标资源/servlet。 我很想知道容器中的场景背后,容器是如何处理过滤器链接的。有人能解释一下过滤器链接是如何在容器内处理的吗?

  • 问题内容: 我正在尝试找到一种方法,可将请求从过滤器重定向到登录页面,但我不知道如何从servlet重定向。我搜索了,但发现的是方法。我在过滤器的响应对象上找不到此方法。是什么原因 我该如何解决? 问题答案: 在Filter中,响应是而不是。因此将强制转换为。 如果使用上下文路径: 也不要忘记在最后打电话。

  • 问题内容: 现在可以将Spring中的 s配置为仅使用来在某些URL上调用。 Servlet过滤器可以实现相同的功能(日志记录,安全性等)。那么应该使用哪一个呢? 我认为使用Interceptor,可以使用对象与模型一起使用,因此它具有更多的优势。谁能提出过滤器或拦截器比其他方法更具优势的方案? 问题答案: 该接口的JavaDoc本身有两个段落讨论这个问题: HandlerInterceptor基

  • 在过去的三天里,我一直在与错误“跨源请求被阻止:相同的源策略不允许读取http://localhost:8080/demomongo/templateapp/login上的远程资源。”(原因:缺少CORS头'Access-Control-Allow-Origin')。

  • 我将在一个已经存在的网站中介绍Spring Web Security。现在出现了一个问题: 我希望我的自定义筛选器在Spring Security筛选器链之前在Tomcat筛选器链中执行。我不想让他们成为这个Spring安全过滤器链的一部分。 我所找到的只是Spring Boot中的一个解决方案(请参见“Spring-How to insert a filter before SpringSecu