如何在不设置系统范围属性的情况下将HTTP代理用于JAX-WS请求?

时间:2011-06-22 22:05:53

标签: java http soap proxy jax-ws

我有一个应用程序需要向Internet上的系统发出SOAP客户端请求,因此需要通过我们的HTTP代理。

可以通过设置系统范围的值来实现此目的,例如系统属性:

// Cowboy-style.  Blow away anything any other part of the application has set.
System.getProperties().put("proxySet", "true");
System.getProperties().put("https.proxyHost", HTTPS_PROXY_HOST);  
System.getProperties().put("https.proxyPort", HTTPS_PROXY_PORT);

或者通过设置默认的ProxySelector(也是系统范围的设置):

// More Cowboy-style!  Every thing Google has found says to do it this way!?!?!
ProxySelector.setDefault(new MyProxySelector(HTTPS_PROXY_HOST, HTTPS_PROXY_PORT));

如果其他子系统可能希望通过不同的HTTP代理或没有任何代理访问Web服务器,这些都不是明智的选择。使用ProxySelector可以让我配置哪些连接使用代理,但是我必须为巨大的应用程序中的每一件事都弄明白。

合理的API会有一个方法,就像java.net.Proxy构造函数那样接受java.net.Socket(java.net.Proxy proxy)对象。这样,必要的设置对于需要设置它们的系统部分是本地的。有没有办法用JAX-WS做到这一点?

我不想设置系统范围的代理配置。

2 个答案:

答案 0 :(得分:10)

我建议使用自定义ProxySelector。我有同样的问题,它很有效,而且非常灵活。这也很简单。

这是我的CustomProxySelector:

import org.hibernate.validator.util.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.*;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

/**
 * So the way a ProxySelector works is that for all Connections made,
 * it delegates to a proxySelector(There is a default we're going to
 * override with this class) to know if it needs to use a proxy
 * for the connection.
 * <p>This class was specifically created with the intent to proxy connections
 * going to the allegiance soap service.</p>
 *
 * @author Nate
 */
class CustomProxySelector extends ProxySelector {

private final ProxySelector def;

private Proxy proxy;

private static final Logger logger = Logger.getLogger(CustomProxySelector.class.getName());

private List<Proxy> proxyList = new ArrayList<Proxy>();

/*
 * We want to hang onto the default and delegate
 * everything to it unless it's one of the url's
 * we need proxied.
 */
CustomProxySelector(String proxyHost, String proxyPort) {
    this.def = ProxySelector.getDefault();
    proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, (null == proxyPort) ? 80 : Integer.valueOf(proxyPort)));
    proxyList.add(proxy);
    ProxySelector.setDefault(this);
}

@Override
public List<Proxy> select(URI uri) {
    logger.info("Trying to reach URL : " + uri);
    if (uri == null) {
        throw new IllegalArgumentException("URI can't be null.");
    }
    if (uri.getHost().contains("allegiancetech")) {
        logger.info("We're trying to reach allegiance so we're going to use the extProxy.");
        return proxyList;
    }
    return def.select(uri);
}

/*
* Method called by the handlers when it failed to connect
* to one of the proxies returned by select().
*/
@Override
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
    logger.severe("Failed to connect to a proxy when connecting to " + uri.getHost());
    if (uri == null || sa == null || ioe == null) {
        throw new IllegalArgumentException("Arguments can't be null.");
    }
    def.connectFailed(uri, sa, ioe);
}

}

答案 1 :(得分:5)

如果您使用的是JAX-WS,则可以设置底层HttpURLConnection使用的套接字工厂。我看到一些模糊的迹象表明这可能是SSL(参见HTTPS SSLSocketFactory)但我不确定你是否可以为常规HTTP连接做到这一点(或者坦率地说这是如何工作的:他们引用的JAXWSProperties类似乎是一个非标准的JDK类。)

如果您可以设置套接字工厂,则可以配置使用所需特定代理的自定义套接字工厂。