【问题标题】:Expose jar resources over web通过网络公开 jar 资源
【发布时间】:2011-02-04 23:06:30
【问题描述】:

我有一个网络服务(使用 Spring-WS)。

我有一个包含多个架构(schema1.xsd、schema2.xsd 和 schema3.xsd)的 jar,我将它们包含在我的 Web 服务中。

有没有办法在我的 web 服务 wep 应用程序中通过 servlet 从 jar 中公开模式?

我的 Spring MessageDispatcherServlet 映射到 /ws/

我希望将我的架构暴露给 /schemas/schema1.xsd /schemas/schema2.xsd 等等。

我知道如何使用 servlet 来实现,但它过于冗长,必须有更好的方法。

我的想法是有一个 servlet 过滤器和所有点击 /schemas/ 检查它是否在我的允许资源列表中并显示它。

这必须是与服务器无关的解决方案。 (例如http://tuckey.org/urlrewrite/ 将不起作用)。

谢谢。

【问题讨论】:

  • 小心 - 您在 WEB-INF/ 中的资源受到保护是有原因的。如果您构建了一个真正通用的解决方案(这会很巧妙),您可能会无意中提供对 WEB-INF/ 中任何资源的访问权限。不一定是坏事,但您会考虑到这一点,并考虑是否以及如何限制对您打算服务的资源的访问。
  • Spring-WS 很好地支持根据您的模式自动生成 WSDL 文件,并能够为 wsdl 提供服务。这本质上将包括 xsd 文件中的定义。你在用这个吗?
  • Wsdl11Definition 将使用 xsd 就好了。问题不在于 wsdl,而在于 xsd 的可用性。每说如果我想使用 SoapUI 给它 wsdl 它将无法加载,因为它会尝试加载所有 xsd 并且它们不会在那里
  • 查看我的第二个答案以了解此问题的替代解决方案。

标签: java spring resources jar


【解决方案1】:

我在过去发现这样做的唯一方法是拥有一个 Spring 控制器(或 servlet,无论你的毒药是什么),它打开 JAR 中资源的流(例如,使用 Class.getResourceAsStream) ,然后将其“传输”到 HTTP 响应(使用 Apache Commons IO 的 IOUtils.copy())。

这不是很好,但它是一个完全通用的解决方案(只需使用资源的类路径对其进行参数化)。

这是我的来源:

@Controller
public class ResourceController {

    private Resource resource;

    @Required
    public void setResource(Resource resource) {
        this.resource = resource;
    }

    @RequestMapping
    public void handleRequest(HttpServletResponse httpResponse) throws IOException {
        InputStream resourceStream = resource.getInputStream();
        try {
            IOUtils.copy(resourceStream, httpResponse.getOutputStream());
        } finally {
            resourceStream.close();
        }
    }

}

【讨论】:

  • 我对 servlet 做了同样的事情。出于安全目的,我需要定义我将允许的 xsd 列表。我通过初始化参数来做到这一点。在我看来,这个解决方案仍然是一个黑客。我认为必须有一种更简单的方法,即 Spring 方法,但我想由于它可能导致的安全问题,实际上没有人实施任何解决方案。
  • 感觉像是 hack,是的,但是 JAR 文件的内容(以及 /WEB-INF 下的内容)不不应该通过客户端访问,所以你必须加倍努力。
  • 显然在Servlet 3.0中有更简单的解决方案,见stackoverflow.com/questions/4732965/…
【解决方案2】:

只需将您的 XSD 打包到名为 schemas.war 的战争中,放入默认 web.xml,然后将战争部署在您使用的任何 Web 容器中。这是解决问题的最简单、无需代码的方法。

【讨论】:

    【解决方案3】:

    又是我!看过你原来问题的 cmets,我想我会提供一个替代解决方案。

    如果我理解您的问题,您似乎有一个 WSDL(由 Spring-WS 生成),其中包含对各种架构的引用。当客户端尝试遵循这些架构引用时,它会失败,因为没有这样的资源。

    Spring-WS 提供了一个很好的解决方法,在 section on WSDL exposure 中有描述:

    如果你想使用多个模式, 通过包含或导入,您 可能想使用 CommonsXsdSchemaCollection,并参考 从那 DefaultWsdl11Definition,像这样:

    <bean id="schemaCollection" class="org.springframework.xml.xsd.commons.CommonsXsdSchemaCollection">
        <property name="xsds">
            <list>
                <value>classpath:/path/to/schema1.xsd</value>
                <value>classpath:/path/to/schema2.xsd</value>
            </list>
        </property>
        <property name="inline" value="true"/>
    </bean>
    

    启用内联属性时, 它遵循所有 XSD 导入和 包括并将它们内联在 WSDL。这大大简化了 架构的部署,这仍然 可以编辑它们 分开。

    因此,您得到的是一个生成的 WSDL,其中所有引用的模式都内联,因此 没有 客户端可以遵循的引用。它非常流畅,意味着您不必单独公开您的架构文件。

    【讨论】:

    • 哇!这就是我需要的。谢谢一百万,我应该阅读更多:)
    【解决方案4】:

    抱歉,这不完全是“答案”,但我还需要 4 分才能发表评论。不过我想把它弄出来,也许可以为别人省去我刚刚经历的很多麻烦。

    我发现如果你只有一个 xsd,它会在只使用 DefaultWsdl11Definition 时被合并到 wsdl 中,但是如果你使用 &lt;sws:dynamic-wsdl&gt; 块来生成 wsdl,它只会创建一个对 xsd 文件的引用,它可能会或可能不是你想要的。尝试使用 .NET 客户端访问服务时,它对我不起作用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-03
      • 2010-09-06
      • 1970-01-01
      相关资源
      最近更新 更多