Часто Java-приложение должно подключаться к Интернету. Наиболее распространенный пример происходит, когда он читает файл XML и ему нужно загрузить свою схему.
Я за прокси-сервером. Как я могу настроить свою JVM на использование прокси?
Часто Java-приложение должно подключаться к Интернету. Наиболее распространенный пример происходит, когда он читает файл XML и ему нужно загрузить свою схему.
Я за прокси-сервером. Как я могу настроить свою JVM на использование прокси?
Из документации Java (а не javadoc API):
http://download.oracle.com/javase/6/docs/technotes/guides/net/proxies.html
Установите JVM-флаги http.proxyHost
и http.proxyPort
при запуске JVM в командной строке.
Обычно это делается в оболочке script (в Unix) или файле bat (в Windows). Вот пример с оболочкой Unix script:
JAVA_FLAGS=-Dhttp.proxyHost=10.0.0.100 -Dhttp.proxyPort=8800
java ${JAVA_FLAGS} ...
При использовании таких контейнеров, как JBoss или WebLogic, мое решение заключается в редактировании сценариев запуска, предоставляемых поставщиком.
Многие разработчики знакомы с Java API (javadocs), но во многих случаях остальная часть документации игнорируется. Он содержит много интересной информации: http://download.oracle.com/javase/6/docs/technotes/guides/
Обновление: Если вы не хотите использовать прокси для решения некоторых локальных/интрасети хостов, посмотрите комментарий от @Tomalak:
Также не забудьте свойство http.nonProxyHosts!
-Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com|etc"
Чтобы использовать настройку прокси-сервера системы:
java -Djava.net.useSystemProxies=true ...
Или программно:
System.setProperty("java.net.useSystemProxies", "true");
Источник: http://docs.oracle.com/javase/7/docs/api/java/net/doc-files/net-properties.html
Программно установить прокси-сервер HTTP/HTTPS и/или SOCKS:
...
public void setProxy() {
if (isUseHTTPProxy()) {
// HTTP/HTTPS Proxy
System.setProperty("http.proxyHost", getHTTPHost());
System.setProperty("http.proxyPort", getHTTPPort());
System.setProperty("https.proxyHost", getHTTPHost());
System.setProperty("https.proxyPort", getHTTPPort());
if (isUseHTTPAuth()) {
String encoded = new String(Base64.encodeBase64((getHTTPUsername() + ":" + getHTTPPassword()).getBytes()));
con.setRequestProperty("Proxy-Authorization", "Basic " + encoded);
Authenticator.setDefault(new ProxyAuth(getHTTPUsername(), getHTTPPassword()));
}
}
if (isUseSOCKSProxy()) {
// SOCKS Proxy
System.setProperty("socksProxyHost", getSOCKSHost());
System.setProperty("socksProxyPort", getSOCKSPort());
if (isUseSOCKSAuth()) {
System.setProperty("java.net.socks.username", getSOCKSUsername());
System.setProperty("java.net.socks.password", getSOCKSPassword());
Authenticator.setDefault(new ProxyAuth(getSOCKSUsername(), getSOCKSPassword()));
}
}
}
...
public class ProxyAuth extends Authenticator {
private PasswordAuthentication auth;
private ProxyAuth(String user, String password) {
auth = new PasswordAuthentication(user, password == null ? new char[]{} : password.toCharArray());
}
protected PasswordAuthentication getPasswordAuthentication() {
return auth;
}
}
...
Помните, что прокси-серверы HTTP и прокси-серверы SOCKS работают на разных уровнях сетевого стека, поэтому вы можете использовать один или другой или оба.
Вы можете установить эти флаги программно следующим образом:
if (needsProxy()) {
System.setProperty("http.proxyHost",getProxyHost());
System.setProperty("http.proxyPort",getProxyPort());
} else {
System.setProperty("http.proxyHost","");
System.setProperty("http.proxyPort","");
}
Просто верните правильные значения из методов needsProxy()
, getProxyHost()
и getProxyPort()
и вы можете вызывать этот фрагмент кода, когда захотите.
JVM использует прокси для выполнения HTTP-вызовов
System.getProperties().put("http.proxyHost", "someProxyURL");
System.getProperties().put("http.proxyPort", "someProxyPort");
Это может использовать настройки прокси пользователя
System.setProperty("java.net.useSystemProxies", "true");
Вы можете установить некоторые свойства прокси-сервера как параметры jvm
-Dhttp.proxyPort = 8080, proxyHost и т.д.
но если вам нужно пройти через аутентификационный прокси, вам понадобится аутентификатор, подобный этому примеру:
ProxyAuthenticator.java
import java.net.*;
import java.io.*;
public class ProxyAuthenticator extends Authenticator {
private String userName, password;
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(userName, password.toCharArray());
}
public ProxyAuthenticator(String userName, String password) {
this.userName = userName;
this.password = password;
}
}
Example.java
import java.net.Authenticator;
import ProxyAuthenticator;
public class Example {
public static void main(String[] args) {
String username = System.getProperty("proxy.authentication.username");
String password = System.getProperty("proxy.authentication.password");
if (username != null && !username.equals("")) {
Authenticator.setDefault(new ProxyAuthenticator(username, password));
}
// here your JVM will be authenticated
}
}
Основываясь на этом ответе: http://mail-archives.apache.org/mod_mbox/jakarta-jmeter-user/200208.mbox/%[email protected]%3E
Комбинируя Сортировщик и Джавабретт /Leonel отвечает:
java -Dhttp.proxyHost=10.10.10.10 -Dhttp.proxyPort=8080 -Dhttp.proxyUser=username -Dhttp.proxyPassword=password -jar myJar.jar
чтение XML файла и загрузка его схемы
Если вы рассчитываете на получение схем или DTD через Интернет, вы создаете медленное, чатное, хрупкое приложение. Что происходит, когда этот удаленный сервер, на котором размещен файл, принимает запланированные или незапланированные простои? Ваше приложение ломается. Это нормально?
См. http://xml.apache.org/commons/components/resolver/resolver-article.html#s.catalog.files
URL для схем и тому подобное лучше всего рассматривать как уникальные идентификаторы. Не как запросы на реальный доступ к этому файлу удаленно. Сделайте некоторые поисковые запросы Google в "каталоге XML". Каталог XML позволяет локально размещать такие ресурсы, устраняя медлительность, храбрость и хрупкость.
Это в основном постоянная кешированная копия удаленного контента. И это нормально, поскольку удаленный контент никогда не изменится. Если когда-либо будет обновление, оно будет иметь другой URL-адрес. Сделать фактический поиск ресурса через Интернет особенно глупым.
Установите для свойства java.net.useSystemProxies
значение true
. Вы можете установить его, например, через переменную среды JAVA_TOOL_OPTIONS. В Ubuntu вы можете, например, добавить следующую строку в .bashrc
:
export JAVA_TOOL_OPTIONS+ = "-Djava.net.useSystemProxies = true"
Я тоже за брандмауэром, это сработало для меня!
System.setProperty("http.proxyHost", "proxy host addr");
System.setProperty("http.proxyPort", "808");
Authenticator.setDefault(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("domain\\user","password".toCharArray());
}
});
URL url = new URL("http://www.google.com/");
URLConnection con = url.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(
con.getInputStream()));
// Read it ...
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
Ниже показано, как установить в Java прокси-сервер с прокси-пользователем и паролем прокси из командной строки, что является очень распространенным случаем. Не стоит сохранять пароли и хосты в коде, как правило, в первую очередь.
Передача системных свойств в командной строке с помощью -D и установка их в коде с помощью System.setProperty("имя", "значение") эквивалентны.
Но учтите это
Пример, который работает:
C:\temp>java -Dhttps.proxyHost=host -Dhttps.proxyPort=port -Dhttps.proxyUser=user -Dhttps.proxyPassword="password" -Djavax.net.ssl.trustStore=c:/cacerts -Djavax.net.ssl.trustStorePassword=changeit com.andreas.JavaNetHttpConnection
Но следующее не работает:
C:\temp>java com.andreas.JavaNetHttpConnection -Dhttps.proxyHost=host -Dhttps.proxyPort=port -Dhttps=proxyUser=user -Dhttps.proxyPassword="password" -Djavax.net.ssl.trustStore=c:/cacerts -Djavax.net.ssl.trustStorePassword=changeit
Разница лишь в расположении системных свойств! (до и после занятий)
Если у вас есть специальные символы в пароле, вы можете поместить его в кавычки "@MyPass123%", как в примере выше.
Если вы получаете доступ к службе HTTPS, вы должны использовать https.proxyHost
, https.proxyPort
и т.д.
Если вы http.proxyHost
к службе HTTP, вы должны использовать http.proxyHost
, http.proxyPort
и т.д.
Добавьте это, прежде чем подключаться к URL-адресу за прокси-сервером.
System.getProperties().put("http.proxyHost", "someProxyURL");
System.getProperties().put("http.proxyPort", "someProxyPort");
System.getProperties().put("http.proxyUser", "someUserName");
System.getProperties().put("http.proxyPassword", "somePassword");
Это небольшое обновление, но поскольку Java 7, прокси-соединения теперь могут быть созданы программно, а не через свойства системы. Это может быть полезно, если:
Здесь надуманный пример в groovy:
// proxy configuration read from file resource under "proxyFileName"
String proxyFileName = "proxy.txt"
String proxyPort = "1234"
String url = "http://www.promised.land"
File testProxyFile = new File(proxyFileName)
URLConnection connection
if (!testProxyFile.exists()) {
logger.debug "proxyFileName doesn't exist. Bypassing connection via proxy."
connection = url.toURL().openConnection()
} else {
String proxyAddress = testProxyFile.text
connection = url.toURL().openConnection(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyAddress, proxyPort)))
}
try {
connection.connect()
}
catch (Exception e) {
logger.error e.printStackTrace()
}
Полная ссылка: http://docs.oracle.com/javase/7/docs/technotes/guides/net/proxies.html
Если вы хотите "Socks Proxy", сообщите аргументы VM "socksProxyHost" и "socksProxyPort".
например.
java -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=8080 org.example.Main
Недавно я открыл способ разрешить JVM использовать настройки прокси-сервера браузера. Что вам нужно сделать, так это добавить ${java.home}/lib/deploy.jar
в свой проект и запустить библиотеку следующим образом:
import com.sun.deploy.net.proxy.DeployProxySelector;
import com.sun.deploy.services.PlatformType;
import com.sun.deploy.services.ServiceManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public abstract class ExtendedProxyManager {
private static final Log logger = LogFactory.getLog(ExtendedProxyManager.class);
/**
* After calling this method, proxy settings can be magically retrieved from default browser settings.
*/
public static boolean init() {
logger.debug("Init started");
// Initialization code was taken from com.sun.deploy.ClientContainer:
ServiceManager
.setService(System.getProperty("os.name").toLowerCase().indexOf("windows") != -1 ? PlatformType.STANDALONE_TIGER_WIN32
: PlatformType.STANDALONE_TIGER_UNIX);
try {
// This will call ProxySelector.setDefault():
DeployProxySelector.reset();
} catch (Throwable throwable) {
logger.error("Unable to initialize extended dynamic browser proxy settings support.", throwable);
return false;
}
return true;
}
}
После этого настройки прокси доступны для Java API через java.net.ProxySelector
.
Единственная проблема с этим подходом заключается в том, что вам нужно запустить JVM с помощью deploy.jar
в bootclasspath, например. java -Xbootclasspath/a:"%JAVA_HOME%\jre\lib\deploy.jar" -jar my.jar
. Если кто-то знает, как преодолеть это ограничение, дайте мне знать.
Это работает для меня:
public void setHttpProxy(boolean isNeedProxy) {
if (isNeedProxy) {
System.setProperty("http.proxyHost", getProxyHost());
System.setProperty("http.proxyPort", getProxyPort());
} else {
System.clearProperty("http.proxyHost");
System.clearProperty("http.proxyPort");
}
}
P/S: Я основываюсь на ответе GHad.
Как указано в других ответах, если вам нужно использовать прокси-серверы с проверкой подлинности, нет надежного способа сделать это с использованием переменных командной строки - что раздражает, если вы используете приложение другого пользователя и не хотите беспорядок с исходным кодом.
Будет ли Iverson предлагать полезное предложение в Использование HttpProxy для подключения к хосту с предварительной проверкой подлинности используйте этот инструмент для управления прокси-сервером, например Proxifier (http://www.proxifier.com/ для Mac OS X и Windows).
Например, с помощью Proxifier вы можете настроить его только для перехвата java-команд, которые должны управляться и перенаправляться через его (аутентифицированный) прокси. Вы захотите установить значения proxyHost и proxyPort в этом случае пустым, например, перейдите в -Dhttp.proxyHost= -Dhttp.proxyPort=
к вашим java-командам.
Кроме того, если вы всегда хотите загрузить одну и ту же схему, вы можете добавить схему в свой путь к классам (файловая система или JAR), а затем использовать пользовательский EntityResolver
См. здесь для более полного обсуждения этого подхода.
Изменить: см. @me.yahoo.com/a/0QMxE обсуждение CatalogResolver, в котором используется подход EntityResolver:
CatalogResolver cr = new CatalogResolver();
...
yourParser.setEntityResolver(cr)
Вы можете использовать переменные JVM http.proxy *, если вы находитесь в автономной JVM, но НЕ ДОЛЖНЫ модифицировать свои сценарии запуска и/или делать это на своем сервере приложений (за исключением, может быть, jboss или tomcat). Вместо этого вы должны использовать JAVA Proxy API (не System.setProperty) или использовать собственные параметры конфигурации поставщика. И WebSphere, и WebLogic имеют очень определенные способы настройки прокси, которые намного мощнее, чем J2SE. Кроме того, для WebSphere и WebLogic вы, вероятно, сломаете свой сервер приложений небольшими способами, переопределив сценарии запуска (в частности, процессы взаимодействия с сервером, так как вы можете сказать им также использовать свой прокси-сервер...).
Я думаю, что настройка WINHTTP также будет работать.
У многих программ, включая обновления Windows, возникают проблемы с прокси-сервером. При настройке WINHTTP всегда будет исправлять такие проблемы.