【问题标题】:Is there a way to config relative address attribute for <jaxws:client> tag?有没有办法为 <jaxws:client> 标签配置相对地址属性?
【发布时间】:2011-07-28 09:27:21
【问题描述】:

我遇到了一个看似简单但无法解决的问题。

我需要使用 CXF 配置 Spring MVC Web 应用程序,以便可以将其部署在多个位置(不同的 servlet 容器、不同的端口)。一切正常,但在我配置 JAX-WS 客户端的 CXF 的 XML 配置中,标签需要具有指定绝对 URL 的“地址”属性才能工作。

代码如下:

<jaxws:client id="wsClient" serviceClass="com.foo.WebServiceInterface" address="http://localhost:8092/WSApp/WebServiceImplPort" />    

有没有办法将地址更改为相对地址或任何其他简单的解决方案来实现我的目标?谢谢!

【问题讨论】:

    标签: xml spring configuration client cxf


    【解决方案1】:

    如果您使用 maven(甚至可能在 ant 中)进行部署,您可以使用 xml 文件中的属性并在您的 pom 中启用资源过滤来为每个环境设置此参数。

    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
        <!-- Turn on filtering of test resources to allow the correct environment for unit tests -->
        <testResources>
            <testResource>
                <directory>src/test/resources</directory>
                <filtering>true</filtering>
            </testResource>
        </testResources>
    </build>
    

    另一个选项在实际创建客户端引用时的代码中,有一个参数化选项可以在创建客户端引用时传递 URL。

    SomeServiceClientEP client = new SomeServiceClientEP(url, qname);
    dynamicallySetEndpoint((BindingProvider) SomeService, destinationURL);
    
    /**
     * Change the destination endpoint url for some service to the
     * provided in the <i>destinationURL</i> parameter
     * 
     * @param service
     *            The {@link SomeService} JAXWS proxy for accessing the
     *            service
     * @param destinationURL
     *            The URL of the SomeService to send the
     *            request to. If the URL contains ?wsdl at the end it will be
     *            stripped prior to attempting delivery
     */
    protected void dynamicallySetEndpoint( BindingProvider service, final String destinationURL) {
        Map<String,Object> rc = service.getRequestContext();
        // Strip the ?wsdl off the end of the URL
        String url = destinationURL;
        if (destinationURL.toLowerCase().matches(WsdlSuffixPattern)) {
            url = destinationURL.substring(0, destinationURL.length() - WsdlSuffix.length());
        }
        rc.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url);
    }
    

    【讨论】:

      【解决方案2】:

      嗯,在哪里放置配置是一个有争议的问题,这取决于品味。 依赖 maven 资源过滤器需要在每次部署中再次打包战争。对我来说,这不是一个选择。

      选项 1 弹簧配置文件

      您可以根据您的部署设置定义不同的弹簧配置文件,例如在属性文件中定义部署休息服务的位置。

      <beans profile="develop">
         <context:property-placeholder location="classpath:develop-config.properties" />
      </beans>
      
      <beans profile="production">
        <context:property-placeholder location="classpath:production-config.properties" />
      </beans>
      
      <jaxws:client id="wsClient" serviceClass="com.foo.WebServiceInterface" address="${address}" /> 
      

      production-config.properties 可能有:

      address=http://localhost:8092/WSApp/WebServiceImplPort
      

      要激活您最喜欢的个人资料: 使用 -Dspring.profiles.active=production 启动应用程序

      选项 2 弹簧环境

      Spring 引入了一种以编程方式启用或激活配置文件的机制。这可用于为每个环境读取不同的配置文件。或者,您可以为您的 spring 上下文 java 系统变量或操作系统环境变量提供服务。 如果您想关注12 factor application guideline关于配置。他们说配置应该放在环境变量上。 或者更确切地说,您更喜欢 1 战多部署方法。这是你的选择。

      import org.springframework.context.ApplicationContextInitializer;
      import org.springframework.core.env.ConfigurableEnvironment;
      import org.springframework.core.env.MapPropertySource;
      import org.springframework.core.io.support.ResourcePropertySource;
      import org.springframework.web.context.ConfigurableWebApplicationContext;
      
      public class EnviromentDiscovery implements org.springframework.context.ApplicationContextInitializer.ApplicationContextInitializer<org.springframework.context.ApplicationContextInitializer.ConfigurableWebApplicationContext> {
      
          public void initialize(ConfigurableWebApplicationContext ctx) {
              ConfigurableEnvironment environment = ctx.getEnvironment();      
              // This variable has the same meaning as host, but i can be redefined in
              // case of cluster deployment.
              String hostname= InetAddress.getLocalHost().getHostName();
              logger.info("Application deployed int host {} using context path: {}", engineName, contextPath);
              // You should define a method which load your config.properties according your own criteria depending for example on your hostname.
              InputStream configurationSource = getResourceAsStream(hostname);
              Properties config = new Properties();
              config.load(configurationSource);        
              // Take your address endpoint
              String address = config.getProperty("address");
              Map<String, Object> props = new HashMap<>();
              props.put("address", address);
      
              MapPropertySource mapSource = new MapPropertySource("props", props);
              // Voilá! your property address is available under spring context!
              environment.getPropertySources().addLast(mapSource);
              ctx.registerShutdownHook();
          }
      }
      

      现在您的上下文文件如下所示:

      别忘了在你的 web.xml 中添加

        <context-param>
          <param-name>contextInitializerClasses</param-name>
          <param-value>net.sf.gazpachoquest.bootstrap.EnviromentDiscovery</param-value>
        </context-param>
      

      有关Spring environment here 的更多信息:或者如果您想查看my proof of concept here

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-05-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多