简体   繁体   English

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

[英]How can I use an HTTP proxy for a JAX-WS request without setting a system-wide property?

I have an application that needs to make a SOAP client request to a system on the Internet, so it needs to go though our HTTP proxy.我有一个应用程序需要向 Internet 上的系统发出 SOAP 客户端请求,因此它需要通过我们的 HTTP 代理。

One can do this by setting system-wide values such as system properties:可以通过设置系统范围的值(例如系统属性)来做到这一点:

// 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);

Or by setting the default ProxySelector (also a system-wide setting):或者通过设置默认的 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));

Neither of these is a wise choice if there is the possibility of other subsystems wanting to access web servers via different HTTP proxies or without any proxy.如果其他子系统可能希望通过不同的 HTTP 代理或没有任何代理访问 Web 服务器,那么这两种方法都不是明智的选择。 Using the ProxySelector would let me configure which connections use the proxy, but I would have to figure that out for every single thing in the huge application.使用ProxySelector可以让我配置哪些连接使用代理,但我必须为庞大的应用程序中的每一件事都弄清楚这一点。

A reasonable API would have a method that took a java.net.Proxy object just like the java.net.Socket(java.net.Proxy proxy) constructor does.一个合理的 API 应该有一个方法,它接受一个java.net.Proxy对象,就像java.net.Socket(java.net.Proxy proxy)构造函数所做的那样。 That way the necessary settings are local to the part of the system that needs to set them.这样,必要的设置对于需要设置它们的系统部分来说是本地的。 Is there some way to do this with a JAX-WS?有没有办法用 JAX-WS 做到这一点?

I do not want to set a system-wide proxy configuration.我不想设置系统范围的代理配置。

I recommend using a custom ProxySelector.我建议使用自定义 ProxySelector。 I had the same problem and it works great and is super flexible.我遇到了同样的问题,效果很好,而且非常灵活。 It's simple too.也很简单。

Here's my CustomProxySelector:这是我的 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);
    }
}

If you are using JAX-WS you might be able to set the socket factory used by the underlying HttpURLConnection.如果您使用 JAX-WS,您可能能够设置底层 HttpURLConnection 使用的套接字工厂。 I see vague signs that this is possible for SSL (see HTTPS SSLSocketFactory ) but I'm not certain if you can do that for regular HTTP connections (or quite frankly how that even works: the JAXWSProperties class they reference appears to be a non-standard JDK class).我看到模糊的迹象表明这对于 SSL 是可能的(请参阅HTTPS SSLSocketFactory ),但我不确定您是否可以为常规 HTTP 连接做到这一点(或者坦率地说,它甚至是如何工作的:他们引用的 JAXWSProperties 类似乎是一个非-标准 JDK 类)。

If you can set the socket factory then you can configure a custom socket factory that uses the specific proxy you want.如果您可以设置套接字工厂,那么您可以配置使用您想要的特定代理的自定义套接字工厂。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM