Wiele razy aplikacja Java musi łączyć się z Internetem. Najczęstszy przykład ma miejsce, gdy czyta plik XML i musi pobrać jego schemat.
Jestem za serwerem proxy. Jak mogę ustawić moją JVM do używania proxy?
Wiele razy aplikacja Java musi łączyć się z Internetem. Najczęstszy przykład ma miejsce, gdy czyta plik XML i musi pobrać jego schemat.
Jestem za serwerem proxy. Jak mogę ustawić moją JVM do używania proxy?
Odpowiedzi:
Z dokumentacji Java ( nie API javadoc):
http://download.oracle.com/javase/6/docs/technotes/guides/net/proxies.html
Ustaw flagi JVM http.proxyHost
i http.proxyPort
podczas uruchamiania JVM w wierszu polecenia. Zwykle odbywa się to w skrypcie powłoki (w systemie Unix) lub w pliku bat (w systemie Windows). Oto przykład ze skryptem powłoki Uniksa:
JAVA_FLAGS=-Dhttp.proxyHost=10.0.0.100 -Dhttp.proxyPort=8800
java ${JAVA_FLAGS} ...
Podczas korzystania z kontenerów takich jak JBoss lub WebLogic, moim rozwiązaniem jest edycja skryptów startowych dostarczonych przez dostawcę.
Wielu programistów zna Java API (javadocs), ale wiele razy reszta dokumentacji jest pomijana. Zawiera wiele interesujących informacji: http://download.oracle.com/javase/6/docs/technotes/guides/
Aktualizacja: jeśli nie chcesz używać proxy do rozwiązania niektórych hostów lokalnych / intranetowych, sprawdź komentarz z @Tomalak:
Nie zapomnij również o właściwości http.nonProxyHosts!
-Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com|etc"
http.nonProxyHosts
nieruchomości! (zastosowanie tak: -Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com|etc"
)
http.proxyUser
i http.proxyPassword
nie są właściwościami systemu Java. Są dla klienta HTTP Apache.
https.proxyHost
i https.proxyPort
dla HTTPs.
Aby użyć systemowego ustawienia proxy:
java -Djava.net.useSystemProxies=true ...
Lub programowo:
System.setProperty("java.net.useSystemProxies", "true");
Źródło: http://docs.oracle.com/javase/7/docs/api/java/net/doc-files/net-properties.html
Aby programowo ustawić serwer proxy HTTP / HTTPS i / lub 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;
}
}
...
Pamiętaj, że proxy HTTP i proxy SOCKS działają na różnych poziomach w stosie sieciowym, więc możesz użyć jednego lub drugiego lub obu.
Możesz ustawić te flagi programowo w ten sposób:
if (needsProxy()) {
System.setProperty("http.proxyHost",getProxyHost());
System.setProperty("http.proxyPort",getProxyPort());
} else {
System.setProperty("http.proxyHost","");
System.setProperty("http.proxyPort","");
}
Wystarczy zwrócić odpowiednie wartości z metod needsProxy()
, getProxyHost()
a getProxyPort()
można nazwać ten fragment kodu, kiedy tylko chcesz.
JVM używa proxy do wykonywania połączeń HTTP
System.getProperties().put("http.proxyHost", "someProxyURL");
System.getProperties().put("http.proxyPort", "someProxyPort");
Może to korzystać z serwera proxy ustawień użytkownika
System.setProperty("java.net.useSystemProxies", "true");
System.setProperty
zamiastSystem.getProperties().put(...)
Możesz ustawić niektóre właściwości dotyczące serwera proxy jako parametry jvm
-Dhttp.proxyPort = 8080, proxyHost itp.
ale jeśli potrzebujesz przekazać przez proxy uwierzytelniające, potrzebujesz uwierzytelnienia takiego jak ten przykład:
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
}
}
Na podstawie tej odpowiedzi: http://mail-archives.apache.org/mod_mbox/jakarta-jmeter-user/200208.mbox/%3C494FD350388AD511A9DD00025530F33102F1DC2C@MMSX006%3E
Ustaw java.net.useSystemProxies
właściwość na true
. Możesz to ustawić na przykład za pomocą zmiennej środowiskowej JAVA_TOOL_OPTIONS . W Ubuntu możesz na przykład dodać następujący wiersz .bashrc
:
eksportuj JAVA_TOOL_OPTIONS + = "-Djava.net.useSystemProxies = true"
Poniżej pokazano, jak ustawić w Javie proxy z użytkownikiem proxy i hasłem proxy z wiersza poleceń, co jest bardzo częstym przypadkiem. Zasadniczo nie należy zapisywać haseł i hostów w kodzie.
Przekazywanie właściwości systemu w wierszu poleceń za pomocą -D i ustawianie ich w kodzie za pomocą System.setProperty („nazwa”, „wartość”) jest równoważne.
Ale zauważ to
Przykład, który działa:
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
Ale następujące działania nie działają :
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
Jedyną różnicą jest położenie właściwości systemu! (przed i po zajęciach)
Jeśli masz hasło specjalne, możesz wpisać je w cudzysłowie „@ MyPass123%”, jak w powyższym przykładzie.
Jeśli masz dostęp do usługi HTTPS, trzeba użyć https.proxyHost
, https.proxyPort
etc.
Jeśli masz dostęp do usługi HTTP, trzeba użyć http.proxyHost
, http.proxyPort
etc.
odczytuje plik XML i musi pobrać jego schemat
Jeśli liczysz na pobieranie schematów lub DTD przez Internet, budujesz powolną, gadatliwą, delikatną aplikację. Co się stanie, gdy zdalny serwer hostujący plik zajmie planowane lub nieplanowane przestoje? Twoja aplikacja się psuje. Czy to w porządku?
Zobacz http://xml.apache.org/commons/components/resolver/resolver-article.html#s.catalog.files
Adresy URL schematów i tym podobne najlepiej traktować jako unikalne identyfikatory. Nie jako żądania zdalnego dostępu do tego pliku. Wyszukaj w Google „Katalog XML”. Katalog XML pozwala hostować takie zasoby lokalnie, co rozwiązuje powolność, spryt i kruchość.
Jest to zasadniczo trwale buforowana kopia zdalnej zawartości. I to jest w porządku, ponieważ zdalna zawartość nigdy się nie zmieni. Jeśli kiedykolwiek pojawi się aktualizacja, będzie ona dostępna pod innym adresem URL. Sprawienie, by faktyczne pobieranie zasobów przez Internet było szczególnie głupie.
Jestem również za firewallem, to zadziałało dla mnie !!
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();
Jeśli chcesz użyć „Socks Proxy”, poinformuj o argumentach maszyny wirtualnej „socksProxyHost” i „socksProxyPort”.
na przykład
java -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=8080 org.example.Main
Dodaj to, zanim połączysz się z adresem URL za serwerem proxy.
System.getProperties().put("http.proxyHost", "someProxyURL");
System.getProperties().put("http.proxyPort", "someProxyPort");
System.getProperties().put("http.proxyUser", "someUserName");
System.getProperties().put("http.proxyPassword", "somePassword");
http.proxyUser
i http.proxyPassword
nie są właściwościami systemu Java. Są dla klienta HTTP Apache.
System.setProperty
zamiastSystem.getProperties().put(...)
Jest to niewielka aktualizacja, ale od wersji Java 7 połączenia proxy można teraz tworzyć programowo, a nie za pomocą właściwości systemu. Może to być przydatne, jeśli:
Oto wymyślony przykład w 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()
}
Pełny opis: http://docs.oracle.com/javase/7/docs/technotes/guides/net/proxies.html
Ostatnio odkryłem sposób, w jaki JVM może korzystać z ustawień proxy przeglądarki. Musisz dodać ${java.home}/lib/deploy.jar
do projektu i zainicjować bibliotekę w następujący sposób:
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;
}
}
Następnie ustawienia proxy są dostępne dla Java API poprzez java.net.ProxySelector
.
Jedynym problemem związanym z tym podejściem jest to, że musisz uruchomić JVM deploy.jar
w ścieżce rozruchowej, np java -Xbootclasspath/a:"%JAVA_HOME%\jre\lib\deploy.jar" -jar my.jar
. Jeśli ktoś wie, jak pokonać to ograniczenie, daj mi znać.
xbootclasspath
wskazywałoby na wdrożenie deploy.jar, czy nie mogę przenieść tego słoika na moją normalną ścieżkę klasy (podczas uruchamiania bez uruchamiania sieci)?
Exception in thread "main" java.lang.IllegalAccessError: class ...) cannot access class com.sun.deploy.net.proxy.DeployProxySelector (in module jdk.deploy) because module jdk.deploy does not export com.sun.deploy.net.proxy
To działa dla mnie:
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: Opieram się na odpowiedzi GHada.
Jak wskazano w innych odpowiedziach, jeśli chcesz używać uwierzytelnionych serwerów proxy, nie ma niezawodnego sposobu, aby to zrobić przy użyciu zmiennych wiersza polecenia - co jest denerwujące, jeśli używasz aplikacji innej osoby i nie chcesz zadzierać z kod źródłowy.
Czy Iverson przedstawia przydatne sugestie na temat korzystania z HttpProxy w celu połączenia się z hostem za pomocą wstępnego uwierzytelnienia w celu skorzystania z narzędzia do zarządzania proxy, takiego jak Proxifier ( http://www.proxifier.com/ dla Mac OS X i Windows).
Na przykład w Proxifier możesz ustawić, aby przechwytywał tylko polecenia Java, którymi można zarządzać i przekierowywać przez (uwierzytelnione) proxy. Będziesz jednak chciał ustawić wartości proxyHost i proxyPort na puste w tym przypadku, np. Przekaż -Dhttp.proxyHost= -Dhttp.proxyPort=
komendę java.
Możesz użyć zmiennych http.proxy * JVM, jeśli jesteś w autonomicznej JVM, ale NIE POWINIENEŚ modyfikować ich skryptów startowych i / lub robić tego na serwerze aplikacji (z wyjątkiem może jboss lub tomcat). Zamiast tego należy użyć interfejsu API serwera proxy JAVA (nie System.setProperty) lub własnych opcji konfiguracji dostawcy. Zarówno WebSphere, jak i WebLogic mają bardzo zdefiniowane sposoby konfigurowania serwerów proxy, które są znacznie potężniejsze niż J2SE. Ponadto w przypadku WebSphere i WebLogic prawdopodobnie zepsujesz serwer aplikacji w niewielki sposób, zastępując skrypty startowe (w szczególności procesy międzyoperacyjne serwera, ponieważ możesz im również powiedzieć, aby korzystali z twojego serwera proxy ...).