代理服务器是介于客户端和服务器之间的一台服务区,设置了代理服务器之后。客户端请求先被送到代理服务器,由代理服务器向真正的Web服务器发送请求,并取回客户端所需要的消息,再送回给客户端。
由于大部分代理服务器具有缓冲的功能,它会不断地将新取得的数据存储到代理服务器的本地存储器上,如果客户端所请求的数据在它的本机的存储器上已经存在而且是最新的,那么它就无须从Web服务器取数据,而是直接将本地存储器上的数据送回浏览器,这样能显著提高浏览速度。
Java使用代理服务器的两种方式:
- 直接使用Proxy创建连接
Proxy有一个构造器,Proxy(Proxy.Type type , SocketAddress sa) :其中sa参数为指定代理服务器的地址(一般使用new InetSocketAddress(IP_ADR , PORT)创建);type为该代理服务器的类型,有如下三种类型:
(1)Proxy.Type.DIRECT:表示直接连接,不使用代理;
(2)Proxy.Type.HTTP:表示支持高级协议代理,如HTTP或FTP;
(3)Proxy.Type.SOCKS:表示SOCKS代理。
一旦创建了Proxy对象之后,程序就可以在使用URLConnection打开连接时,或者创建Socket连接时传入一个Proxy对象,作为本次连接所使用的代理服务器。
例子:
public class MainActivity extends Activity
{
private Button requestBtn;
private TextView responseMsg;
private static final String PROXY_ADDR = "129.82.12.188";
private static final int PORT = 3124;
//定义需要访问的网站地址
private String urlStr = "http://www.crazyit.org";
Handler handler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
if (msg.what == 0x123)
{
responseMsg.setText(msg.obj.toString());
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
requestBtn = (Button) findViewById(R.id.request_by_proxy);
responseMsg = (TextView) findViewById(R.id.response_msg);
requestBtn.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
requestData();
}
});
}
private void requestData()
{
new Thread()
{
@Override
public void run()
{
try
{
URL url = new URL(urlStr);
//创建一个代理服务器对象
Proxy proxy = new Proxy(Proxy.Type.HTTP , new InetSocketAddress(PROXY_ADDR , PORT));
//使用指定的代理服务器打开连接
URLConnection conn = url.openConnection(proxy);
//设置超时时长
conn.setConnectTimeout(5000);
Log.d("come" , "come");
Scanner scan = new Scanner(conn.getInputStream());
StringBuilder sb = new StringBuilder();
while (scan.hasNextLine())
{
String line = scan.nextLine();
sb.append(line);
}
Message msg = new Message();
msg.what = 0x123;
msg.obj = sb.toString();
handler.sendMessage(msg);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}.start();
}
}
- 使用ProxySelector自动选择代理服务器
ProxySelector自动选择代理服务器可以避免每次打开连接时都需要显式地设置代理服务器,借助ProxySelector可以实现每次打开连接都具有默认的代理服务器。该类是一个抽象类,有如下两个抽象方法:
(1)List selector(URI uri): 根据业务需要返回代理服务器列表,如果该方法返回的集合中只包含一个Proxy,该Proxy将会作为默认的代理服务器。
(2)connectFailed(URI uri , SocketAddress sa , IOException ioe):连接代理服务器失败时的回调。系统默认的代理服务器选择器也重写了connectFailed方法,它重写的方法处理策略是:当系统设置的代理服务器失败时,默认代理选择器将会采用直连的方式连接远程资源,所以请求依然可以成功。
例子:
private void requestDataByProxySelector()
{
new Thread()
{
@Override
public void run()
{
try
{
//根据业务需求返回对应的代理服务器
ProxySelector.setDefault(new ProxySelector()
{
@Override
public List<Proxy> select(URI uri)
{
List<Proxy> result = new ArrayList<>();
result.add(new Proxy(Proxy.Type.HTTP , new InetSocketAddress(PROXY_ADDR , PORT)));
return result;
}
@Override
public void connectFailed(URI uri, SocketAddress socketAddress, IOException e)
{
Log.d("failure" , "无法连接到指定代理服务器上");
}
});
URL url = new URL(urlStr);
//没有指定代理服务器,直接打开连接
URLConnection conn = url.openConnection();
//设置超时时长
conn.setConnectTimeout(5000);
Log.d("come" , "come");
Scanner scan = new Scanner(conn.getInputStream());
StringBuilder sb = new StringBuilder();
while (scan.hasNextLine())
{
String line = scan.nextLine();
sb.append(line);
}
Message msg = new Message();
msg.what = 0x123;
msg.obj = sb.toString();
handler.sendMessage(msg);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}.start();
}