一个 webapp 的两个单独的 Spring 上下文

Posted

技术标签:

【中文标题】一个 webapp 的两个单独的 Spring 上下文【英文标题】:Two separate Spring contexts for one webapp 【发布时间】:2012-06-26 10:28:20 【问题描述】:

我想使用两个不同的 Spring web 上下文,每个都有自己的 contextConfig、spring servlet 和 filter,应该映射到不同的 url。我有一个

    标准 Grails 项目,映射到“/” 还有一个现有的 Spring webapp,我想映射到 /extra/

我知道我可以将两者部署到一个 Tomcat 中,但我正在寻找一种制作一个应用程序的方法(一个 war 等),因为它可以简化我们的部署和开发过程。

这个应用程序不需要共享 bean 或任何东西,应该是完全独立的。两者都有 DispatcherServlet 和 DispatcherFilter(并且都使用 Spring Security,但配置不同)

如何为此类 webapp 配置 web.xml

我已尝试添加新过滤器:

<filter>
    <filter-name>extraSpringSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
        <param-name>contextAttribute</param-name>
        <param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.extraSpring</param-value>
    </init-param>
    <init-param>
        <param-name>targetBeanName</param-name>
        <param-value>extraSecurityFilterBean</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>extraSpringSecurityFilterChain</filter-name>
    <url-pattern>/extra/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

和 spring 调度程序 servlet:

<servlet>
    <servlet-name>extraSpring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    <init-param>
        <param-name>springConfigLocation</param-name>
        <param-value>classpath:extra-spring-web.xml</param-value>
    </init-param>
</servlet>

地点:

类路径中的两个上下文 xml(在 exra 库 jar 中): 额外的spring-web.xml extra-spring-security.xml(!!!应该如何配置?) 额外的spring-security.xml 是相当标准的 Spring Security 配置 已配置beanextraSecurityFilterBean 对来自 -web 上下文的 bean 有依赖(但不是必须的)

它现在处于半工作状态:

我从日志中看到,extraSpring servlet 成功地从 extra-spring-web.xml 加载了 bean 但在访问 url /extra/ 后,我得到了 NoSuchBeanDefinitionException:没有定义名为“extraSecurityFilterBean”的 bean。

那么,问题来了,我如何为DelegatingFilterProxy 定义上下文?我什至尝试将此文件添加到主上下文(contextConfigLocation 参数)中,这不是我想要的,但它没有用。

我查看了 DelegatingFilterProxy 源,但我不清楚它是如何加载上下文的。

【问题讨论】:

我认为您不必编辑 grails web.xml。你可以用tomcat和apache得到你想要玩的东西。在 tomcat '/app1' 和 '/app2' 中部署两个独立的应用程序。在 apache 中,所有请求都映射到 '/**' => '/app1/**' 除了那些额外的 '/extra/**' => '/app2/**' 是的,我知道,谢谢。但我确信应该有一种方法可以只使用一个 web.xml / 将两者放入一个 WAR 你如何加载extra-spring-security.xml?你没有在 web.xml sn-p 中命名它,它是 extra-spring-web.xml 中的 &lt;import&gt; 吗? @IanRoberts 是的,这是问题所在,我不知道如何加载 extra-spring-security.xml。它应该由SpringSecurityFilterChain 使用,但我不明白如何为其配置上下文路径 我的意思是,我尝试了不同的选项,但没有找到任何工作 【参考方案1】:

根据我对这个问题的评论,如果安全过滤器链是在 extra-spring-security.xml 中定义的,那么除了 extra-spring-web.xml 之外,您还需要确保该文件由额外的 DispatcherServlet 加载,或者通过 &lt;import&gt;ing -来自 -web 的安全文件或将其配置为:

<servlet>
    <servlet-name>extraSpring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
          classpath:extra-spring-web.xml
          classpath:extra-spring-security.xml
        </param-value>
    </init-param>
</servlet>

您还需要确保 Grails 应用程序中的安全过滤器不适用于 /extra URI,具体操作方式取决于您是否使用注释、数据库 RequestMap条目等。

【讨论】:

伊恩,谢谢!你是对的,它正在工作,不知道为什么我不尝试这种方式。我仍然在尝试处理 /extra url 的 grails 过滤器上遇到问题,但这是另一个问题 @IanRoberts 我遇到了类似的问题 (***.com/q/23017839/827480)。您能否提供其他信息/参考以防止 Grails 中的安全过滤器应用于/extra URL?这可能是我缺少的链接。【参考方案2】:

如果模块完全分开:最简单的方法是将它们打包为两个不同的 webapp。数十个不同的基于 spring 的应用程序可以在一个应用程序服务器中运行——即使在一台普通的开发人员机器上——也不会出现问题。

【讨论】:

我知道,谢谢。但我正在寻找一种方法如何将它们合并为一个。考虑一下,因为我必须部署到一些 PaaS 托管中,而且我只能部署为一个应用程序【参考方案3】:

几个问题

您的 Spring Security 配置是什么样的? 我很困惑为什么错误状态“未定义名为 'apiservSecurityFilterChain' 的 bean”,但您发布的 web.xml 仅引用了 extraSpringSecurityFilterChain(bean 名称应该匹配,或者一些重要的配置被遗漏了)。李>

可能的答案

我猜问题是过滤器名称需要匹配 Spring Security 的 bean 名称(如果没有看到您正在使用的 Spring Security 配置就无法确定)。 Spring Security 命名空间使用的默认值是 springSecurityFilterChain,因此请在 web.xml 中尝试以下操作(注意 extraSpringSecurityFilterChain 更改为 springSecurityFilterChain):

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
        <param-name>contextAttribute</param-name>
        <param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.extraSpring</param-value>
    </init-param>
    <init-param>
        <param-name>targetBeanName</param-name>
        <param-value>extraSecurityFilterBean</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/extra/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

【讨论】:

谢谢!是的,它是“没有名为 'extraSecurityFilterBean' 的 bean”,我被错误地提到它,对不起。这是一个默认的 springSecurityFilterChanin bean,命名为 extraSecurityFilterBean(以区分来自 grails 的标准过滤器链)。 我不能使用名为“springSecurityFilterChain”的过滤器,因为它已经被另一个spring安全过滤器链(来自grails)使用了

以上是关于一个 webapp 的两个单独的 Spring 上下文的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security:如何将两个应用程序与单独的 Spring Security 配置集成?

由于缺少 WebApp 库,在 Spring-boot-starter 项目中构建失败

通过单独运行批处理微服务在 Spring Cloud Data Flow 上部署 Spring Batch 应用程序

如何在 AWS Elastic Beanstalk 应用程序负载均衡器上运行的 Spring webapp 上获取请求者 IP

如何使用 REST-ful URL 创建 Spring 3 + Tiles 2 webapp?

Spring Security OAuth2:如何为两类用户提供两个单独的登录链接?