有没有办法为<jaxws:client>标签配置相对地址属性?</jaxws:client>

时间:2011-07-28 09:27:21

标签: xml spring configuration client cxf

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

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

以下是代码:

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

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

2 个答案:

答案 0 :(得分:0)

如果使用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);
}

答案 1 :(得分:0)

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

选项1 Spring个人资料

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

<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有关配置的信息。他们说配置应该放在Enviroment变量上。 或者更确切地说,您更喜欢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