หลายครั้งที่แอพ 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 ของคุณบนบรรทัดคำสั่ง โดยปกติจะทำในเชลล์สคริปต์ (ใน Unix) หรือไฟล์ bat (ใน Windows) นี่คือตัวอย่างของ Unix shell 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"
http.nonProxyHosts
ทรัพย์สิน! (การใช้งานเช่นนี้-Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com|etc"
)
http.proxyUser
และhttp.proxyPassword
ไม่ใช่คุณสมบัติของระบบ Java พวกเขามีไว้สำหรับไคลเอนต์ Apache HTTP
https.proxyHost
และhttps.proxyPort
สำหรับ HTTP
วิธีใช้การตั้งค่าพร็อกซีระบบ:
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");
System.setProperty
แทนSystem.getProperties().put(...)
คุณสามารถตั้งค่าคุณสมบัติบางอย่างเกี่ยวกับพร็อกซีเซิร์ฟเวอร์เป็นพารามิเตอร์ 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/%3C494FD350388AD511A9DD00025530F33102F1DC2C@MMSX006%3E
การรวมคำตอบของ Sorter และ javabrett / Leonel:
java -Dhttp.proxyHost=10.10.10.10 -Dhttp.proxyPort=8080 -Dhttp.proxyUser=username -Dhttp.proxyPassword=password -jar myJar.jar
ตั้งค่าคุณสมบัติการjava.net.useSystemProxies
true
คุณสามารถตั้งค่าได้เช่นผ่านตัวแปรสภาพแวดล้อมJAVA_TOOL_OPTIONS ใน Ubuntu คุณสามารถเพิ่มบรรทัดต่อไปนี้ลงใน.bashrc
:
ส่งออก JAVA_TOOL_OPTIONS + = "-Djava.net.useSystemProxies = true"
ข้อมูลต่อไปนี้แสดงวิธีตั้งค่าพร็อกซี Java พร้อมกับผู้ใช้พร็อกซีและรหัสผ่านพร็อกซีจากบรรทัดคำสั่งซึ่งเป็นกรณีทั่วไป คุณไม่ควรบันทึกรหัสผ่านและโฮสต์ในรหัสเป็นกฎในสถานที่แรก
การส่งผ่านคุณสมบัติของระบบในบรรทัดคำสั่งด้วย -D และการตั้งค่าในรหัสด้วย System.setProperty ("name", "value") เทียบเท่ากัน
แต่ให้สังเกตสิ่งนี้
ตัวอย่างที่ใช้งานได้:
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 คุณต้องใช้http.proxyHost
, http.proxyPort
ฯลฯ
อ่านไฟล์ XML และต้องการดาวน์โหลดสคีมาของมัน
หากคุณเชื่อใจในการดึงสคีมาหรือ DTD ทางอินเทอร์เน็ตคุณกำลังสร้างแอปพลิเคชันที่ช้าช่างพูดและเปราะบาง เกิดอะไรขึ้นเมื่อเซิร์ฟเวอร์ระยะไกลที่โฮสต์ไฟล์ใช้เวลาวางแผนหรือหยุดทำงานโดยไม่ได้วางแผน แอปของคุณหยุดพัก ไม่เป็นไร?
ดูhttp://xml.apache.org/commons/components/resolver/resolver-article.html#s.catalog.files
URL สำหรับ schema และสิ่งที่คล้ายกันถือว่าเป็นตัวระบุที่ดีที่สุด ไม่เป็นคำขอให้เข้าถึงไฟล์นั้นจากระยะไกล ค้นหาด้วยกูเกิ้ลจาก "แคตตาล็อก XML" แคตตาล็อก XML ช่วยให้คุณสามารถโฮสต์ทรัพยากรดังกล่าวในพื้นที่การแก้ไขความช้าความมีเสน่ห์และความเปราะบาง
โดยทั่วไปแล้วจะเป็นสำเนาเนื้อหาแคชระยะไกลอย่างถาวร และก็ไม่เป็นไรเนื่องจากเนื้อหาระยะไกลจะไม่เปลี่ยนแปลง หากมีการอัปเดตอยู่ตลอดมันจะเป็น URL อื่น ทำให้การดึงข้อมูลจริงผ่านทางอินเทอร์เน็ตโดยเฉพาะอย่างยิ่งโง่
ฉันยังอยู่หลังไฟร์วอลล์นี่มันใช้งานได้สำหรับฉัน !!
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();
หากคุณต้องการ "ถุงเท้าพร็อกซี" ให้แจ้งข้อโต้แย้ง VM "socksProxyHost" และ "socksProxyPort"
เช่น
java -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=8080 org.example.Main
เพิ่มสิ่งนี้ก่อนที่คุณจะเชื่อมต่อกับ 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");
http.proxyUser
และhttp.proxyPassword
ไม่ใช่คุณสมบัติของระบบ Java พวกเขามีไว้สำหรับไคลเอนต์ Apache HTTP
System.setProperty
แทนSystem.getProperties().put(...)
นี่เป็นการอัปเดตเล็กน้อย แต่เนื่องจาก 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
เมื่อเร็ว ๆ นี้ฉันค้นพบวิธีที่อนุญาตให้ 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
เช่น หากใครรู้วิธีเอาชนะข้อ จำกัด นี้ให้ฉันรู้
xbootclasspath
ชี้ไปที่การนำไปใช้งานจะมีผลอย่างไรฉันไม่สามารถใช้ jar นั้นไปสู่ classpath ปกติของฉัน (เมื่อทำงานโดยไม่ใช้ webstart)
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
ที่เหมาะกับฉัน:
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 Will จะให้คำแนะนำที่เป็นประโยชน์มากกว่าที่การใช้ HttpProxy เพื่อเชื่อมต่อกับโฮสต์ที่มีการตรวจสอบสิทธิ์เบื้องต้นเพื่อใช้เครื่องมือการจัดการพร็อกซี่เช่น Proxifier ( http://www.proxifier.com/สำหรับ Mac OS X และ Windows) เพื่อจัดการสิ่งนี้
ตัวอย่างเช่นด้วย Proxifier คุณสามารถตั้งค่าได้เพียงคำสั่งสกัดกั้น java ที่จะจัดการและเปลี่ยนเส้นทางผ่านพร็อกซี (รับรองความถูกต้อง) คุณจะต้องการตั้งค่า proxyHost และ proxyPort เป็นค่าว่างในกรณีนี้เช่นส่งผ่าน-Dhttp.proxyHost= -Dhttp.proxyPort=
ไปยังคำสั่ง java ของคุณ
คุณสามารถใช้ตัวแปร http.proxy * JVM หากคุณอยู่ใน JVM แบบสแตนด์อโลน แต่คุณไม่ควรแก้ไขสคริปต์เริ่มต้นและ / หรือทำสิ่งนี้ภายในแอปพลิเคชันเซิร์ฟเวอร์ของคุณ (ยกเว้นอาจเป็น jboss หรือ tomcat) แต่คุณควรใช้ JAVA Proxy API (ไม่ใช่ System.setProperty) หรือใช้ตัวเลือกการกำหนดค่าของผู้ขาย ทั้ง WebSphere และ WebLogic มีวิธีการกำหนดค่าพร็อกซีที่มีประสิทธิภาพมากกว่า J2SE นอกจากนี้สำหรับ WebSphere และ WebLogic คุณอาจทำลายแอปพลิเคชันเซิร์ฟเวอร์ของคุณด้วยวิธีเล็ก ๆ น้อย ๆ โดยการแทนที่สคริปต์เริ่มต้น
ฉันคิดว่าการกำหนดค่าWINHTTPจะทำงานได้เช่นกัน
หลายโปรแกรมรวมถึง Windows Update กำลังประสบปัญหาหลังพรอกซี โดยการตั้งค่า WINHTTP จะแก้ไขปัญหาประเภทนี้เสมอ