Java HTTP 代理服务器

2023-10-30

Java HTTP 代理服务器

在当今的企业开发环境中,我们不得不与代理打交道,通常是作为系统管理员。在大多数情况下,应用程序将配置为系统的默认设置,但如果您想对应用程序进行非常严格的控制,例如代理设置,对于这种情况,Java允许使用 API。

代理服务器是像客户端应用程序和其它服务器之间的中间系统。在企业应用程序中,用于跨网络边界提供对用户内容的控制。下图演示了代理服务器的行为:

Java HTTP 代理服务器

在本主题中,我们将了解如何通过 Java 中的代理服务器进行连接。我们将遵循两种方法在 Java 中创建与代理服务器的连接。

  • 第一种方法是一种较旧的方法,它是 JVM 范围的并配置了系统属性。许多开发人员在全球范围内使用它。
  • 第二种方法是使用 Proxy 类,它通过允许基于每个连接的配置来提供更多控制。

代理 API 从 Java 5.0 开始可用。但是,旧方法仍然有效并且可以用于我们的项目。但是 Proxy 类方法更有效且可定制。

使用代理服务器的优势

代理服务器在以下情况下很有用:

  • 捕获客户端和服务器之间的流量。
  • 控制和限制上传/下载带宽以发现连接速度较慢的网站的加载。
  • 分析网络出现故障时的系统反应。
  • 更新客户端/服务器的内容。
  • 创建有关流量的统计信息。

系统属性

Java 支持不同协议的代理处理程序,例如FTP、HTTP、HTTPSSOCKs。我们可以为单个处理程序定义一个单独的代理作为主机名和端口号。Java 代理配置中提供以下系统属性:

  • proxyHost:它定义了 HTTP 代理服务器的主机名。
  • proxyPort:它定义了 HTTP 代理服务器的端口号
  • port 属性是一个可选属性,如果未提供,它将被设置为默认值 80。
  • nonProxyHosts :它为我们想要绕过代理的可用主机模式定义了一个管道分隔(“|”)。它可以应用于 HTTP 和 HTTPS 处理程序。
  • SocksProxyHost:它定义了 SOCKS 代理服务器的主机名。
  • SocksProxyPort:定义了SOCKS代理服务器的端口号。

注意:在 nonProxyHosts 的情况下,我们可以使用通配符(“*”)开始或结束主机模式。但是在Windows平台上,需要去掉“|” 分隔符。可以在此处找到所有可用代理系统属性的列表。

使用全局设置

Java 提供了几个我们在上面讨论过的系统属性来配置 JVM 范围的行为。对于特定用例,这些属性很容易实现。

我们还可以在调用 JVM 时使用命令行设置必要的属性。还有一种替代方法,可以通过在运行时调用System.setProperty()方法来设置它们。

让我们了解如何使用命令行设置它们:

使用命令行设置代理

我们还可以使用命令行参数设置代理属性。要使用命令行定义代理,请将设置作为系统属性传递,如下所示:

  1. java -Dhttp.proxyHost=127.0.0.1 -Dhttp.proxyPort=3020 com.javatpoint.networking.proxies.CommandLineProxyDemo  

通过这种方式启动进程,我们可以在 URL 上使用openConnection () 方法而无需做任何进一步的工作,如下所示:

  1. URL url = new URL(RESOURCE_URL);  
  2. URLConnection con = url.openConnection();  

使用 System.setProperty() 方法设置代理

如果我们在使用命令行时遇到困难,可以使用 System.setProperty() 方法来替代。要使用此方法设置代理,请在我们的程序中按如下方式定义它:

  1. System.setProperty("http.proxyHost", "127.0.0.1");  
  2. System.setProperty("http.proxyPort", "3020");  
  3. URL url = new URL(RESOURCE_URL);  
  4. URLConnection con = url.openConnection();  
  5. // ...  

稍后,我们可以取消设置系统属性,如果需要,它们将从我们的应用程序中删除。要取消设置系统属性,请通过在我们的程序中定义它来使其为空,如下所示:

  1. System.setProperty("http.proxyHost", null);  

Global 设置有一些限制;在这里,代理 API 的概念出现了。让我们讨论一下全局设置的局限性:

全局配置方法的局限性

全局配置方法是定义代理的最简单方法,但这种方法有一些局限性。

这种方法提供了在 JVM 范围内的实现,因此为特定协议定义的设置在JVM的生命周期内都是有效的,或者直到我们手动取消设置它们。

为了克服这个限制,如果需要,打开和关闭设置可能很有吸引力。但是,有必要确保采取措施防止多线程程序中的并发问题。

因此,作为替代方案,代理 API 更高效,并提供对代理配置的更多控制。

使用代理 API 设置代理

Java Proxy 类提供了一种基于连接配置代理的便捷方法。如果我们使用 Proxy 类设置代理,它将覆盖现有的 JVM 范围代理设置。

使用 Proxy 类的 Proxy.Type() 方法可以定义三种类型的代理:

  1. HTTP 代理(使用 HTTP 协议)
  2. SOCKS 代理(使用 SOCKS 协议)
  3. 直接代理(这是一个明确配置的没有代理的直接连接)。

让我们了解这些代理:

1) HTTP 代理

要使用 HTTP 代理,请使用代理包装 SocketAddress 实例并提供类型为Proxt.Type.HTTP。现在,我们可以简单地将代理实例传递给URLConnection.openConnection()。考虑以下代码:

  1. URL weburl = new URL(URL_STRING);  
  2. Proxy webProxy   
  3.   = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 3020));  
  4. HttpURLConnection webProxyConnection   
  5.   = (HttpURLConnection) weburl.openConnection(webProxy);  

现在,我们将连接到 URL_STRING,然后通过托管在 127.0.0.1:3020 的代理服务器路由该连接。

2) 直接代理

直接代理对于直接连接到主机很有用。在这种情况下,我们必须显式绕过可以使用静态“proxy.NO_PROXY”实例全局配置的代理。在内部,代理 API 使用 Proxy.Type.Direct 类型创建一个新的代理实例。

考虑以下代码:

  1. HttpURLConnection directConnection   
  2.   = (HttpURLConnection) weburl.openConnection(Proxy.NO_PROXY);  

基本上,如果没有全局配置的代理,那么这将与不带参数调用 openConnection() 相同。

3) 袜子代理

Socks 代理在处理 URLConnection 时以类似于 HTTP 变体的方式工作。在 Socks 代理中,首先我们使用 Proxy.Type.SOCKS 类型用代理包装一个 SocketAddress 实例。之后,将 Proxy 实例传递给 URLConnection.openConnection。考虑以下代码:

  1. Proxy socksProxy   
  2.   = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("127.0.0.1", 1080));  
  3. HttpURLConnection socksConnection   
  4.   = (HttpURLConnection) weburl.openConnection(socksProxy);  

我们还可以在连接到 TCP 套接字时使用 SOCKs 代理。为此,我们需要使用 Proxy 实例来创建 Socket。之后,目标 SocketAddress 实例被传递给 Socket.connect() 方法。

考虑以下代码:

  1. Socket proxySocket = new Socket(socksProxy);  
  2. InetSocketAddress socketHost   
  3.   = new InetSocketAddress(SOCKET_SERVER_HOST, SOCKET_SERVER_PORT);  
  4. proxySocket.connect(socketHost);  

创建简单代理服务器的 Java 程序

TestProxyServer.java:

import java.io.*;
import java.net.*;

public class TestProxyServer {
	public static void main(String[] args) throws IOException {
		try {
			String host = "localhost";
			int remoteport = 80;
			int localport = 8026;
			// Printing a start-up message
			System.out.println("Starting proxy for " + host + ":" + remoteport + " on port " + localport);
			// And start running the server
			runServer(host, remoteport, localport); // never returns
		} catch (Exception e) {
			System.err.println(e); // Prints the standard errors
		}
	}

	/**
	 * It will run a single-threaded proxy server on the provided local port.
	 */
	public static void runServer(String host, int remoteport, int localport) throws IOException {
		// Creating a ServerSocket to listen for connections with
		ServerSocket s = new ServerSocket(localport);
		final byte[] request = new byte[1024];
		byte[] reply = new byte[4096];
		while (true) {
			Socket client = null, server = null;
			try {
				// It will wait for a connection on the local port
				client = s.accept();
				final InputStream streamFromClient = client.getInputStream();
				final OutputStream streamToClient = client.getOutputStream();

				// Create a connection to the real server.
				// If we cannot connect to the server, send an error to the
				// client, disconnect, and continue waiting for connections.
				try {
					server = new Socket(host, remoteport);
				} catch (IOException e) {
					PrintWriter out = new PrintWriter(streamToClient);
					out.print("Proxy server cannot connect to " + host + ":" + remoteport + ":\n" + e + "\n");
					out.flush();
					client.close();
					continue;
				}

				// Get server streams.
				final InputStream streamFromServer = server.getInputStream();
				final OutputStream streamToServer = server.getOutputStream();

				// a thread to read the client's requests and pass them
				// to the server. A separate thread for asynchronous.
				Thread t = new Thread() {
					public void run() {
						int bytesRead;
						try {
							while ((bytesRead = streamFromClient.read(request)) != -1) {
								streamToServer.write(request, 0, bytesRead);
								streamToServer.flush();
							}
						} catch (IOException e) {
						}

						// the client closed the connection to us, so close our
						// connection to the server.
						try {
							streamToServer.close();
						} catch (IOException e) {
						}
					}
				};

				// Start the client-to-server request thread running
				t.start();
				// Read the server's responses
				// and pass them back to the client.
				int bytesRead;
				try {
					while ((bytesRead = streamFromServer.read(reply)) != -1) {
						streamToClient.write(reply, 0, bytesRead);
						streamToClient.flush();
					}
				} catch (IOException e) {
				}
				// The server closed its connection to us, so we close our
				// connection to our client.
				streamToClient.close();
			} catch (IOException e) {
				System.err.println(e);
			} finally {
				try {
					if (server != null)
						server.close();
					if (client != null)
						client.close();
				} catch (IOException e) {
				}
			}
		}
	}
}

输出:

Starting proxy for localhost:80 on port 8026

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java HTTP 代理服务器 的相关文章

  • 使用 WebDriver 单击新打开的选项卡中的链接

    有人可以在这种情况下帮助我吗 场景是 有一个网页 我仅在新选项卡中打开所有指定的链接 现在我尝试单击新打开的选项卡中的任何一个链接 在下面尝试过 但它仅单击主 第一个选项卡中的一个链接 而不是在新选项卡中 new Actions drive
  • Base36 编码字符串?

    我一直在网上查找 但找不到解决此问题的方法 在 Python Ruby 或 Java 中 如何对以下字符串进行 Base 36 编码 nOrG9Eh0uyeilM8Nnu5pTywj3935kW 5 Ruby 以 36 为基数 s unpa
  • HAProxy SSL终止+客户端证书验证+curl/java客户端

    我希望使用我自己的自签名证书在 HAProxy 上进行 SSL 终止 并使用我创建的客户端证书验证客户端访问 我通过以下方式创建服务器 也是 CA 证书 openssl genrsa out ca key 1024 openssl req
  • 文本在指定长度后分割,但不要使用 grails 打断单词

    我有一个长字符串 需要将其解析为长度不超过 50 个字符的字符串数组 对我来说 棘手的部分是确保正则表达式找到 50 个字符之前的最后一个空格 以便在字符串之间进行彻底的分隔 因为我不希望单词被切断 public List
  • 删除优先级队列的尾部元素

    如何删除优先级队列的尾部元素 我正在尝试使用优先级队列实现波束搜索 一旦优先级队列已满 我想删除最后一个元素 优先级最低的元素 Thanks 没有简单的方法 将元素从原始元素复制到新元素 最后一个除外 PriorityQueue remov
  • Android蓝牙java.io.IOException:bt套接字已关闭,读取返回:-1

    我正在尝试编写一个代码 仅连接到运行 Android 5 0 KitKat 的设备上的 目前 唯一配对的设备 无论我尝试了多少方法 我仍然会收到此错误 这是我尝试过的最后一个代码 它似乎完成了我看到人们报告为成功的所有事情 有人能指出我做错
  • org/codehaus/plexus/archiver/jar/JarArchiver(不支持的major.minor版本49.0)-Maven构建错误

    下午大家 我在尝试构建项目时收到上述错误 我很确定这与使用 Java 1 6 编译的 Maven 最新更新有关 而我们尝试构建的项目是 1 4 项目 在此之前的插件工作没有问题 因此我将以下内容添加到 POM xml 文件中以尝试强制使用现
  • 添加到列表时有没有办法避免循环?

    我想知道这样的代码 List
  • 虽然我的类已加载,但 Class.forName 抛出 ClassNotFoundException

    代码如下 它的作用是加载我放在主目录中的 jar 文件中的所有类 import java io File import java util jar JarFile import java util jar JarEntry import j
  • 当 minifyEnabled 为 true 时 Android 应用程序崩溃

    我正在使用多模块应用程序 并且该应用程序崩溃时minifyEnabled true in the installed模块的build gradle 以下是从游戏控制台检索到的反混淆堆栈跟踪 FATAL EXCEPTION Controlle
  • 用于缓存的 Servlet 过滤器

    我正在创建一个用于缓存的 servlet 过滤器 这个想法是将响应主体缓存到memcached 响应正文由以下方式生成 结果是一个字符串 response getWriter print result 我的问题是 由于响应正文将不加修改地放
  • 如何停止执行的 Jar 文件

    这感觉像是一个愚蠢的问题 但我似乎无法弄清楚 当我在 Windows 上运行 jar 文件时 它不会出现在任务管理器进程中 我怎样才能终止它 我已经尝试过 TASKKILL 但它对我也不起作用 On Linux ps ef grep jav
  • 无法在 Java/Apache HttpClient 中处理带有垂直/管道栏的 url

    例如 如果我想处理这个网址 post new HttpPost http testurl com lists lprocess action LoadList 401814 1 Java Apache 不允许我这么做 因为它说竖线 是非法的
  • Play.application() 的替代方案是什么

    我是 Play 框架的新手 我想读取conf文件夹中的一个文件 所以我用了Play application classloader getResources Data json nextElement getFile 但我知道 play P
  • 避免 Java 中的重复导入:继承导入?

    有没有办法 继承 导入 Example 常见枚举 public enum Constant ONE TWO THREE 使用此枚举的基类 public class Base protected void register Constant
  • Lombok @Builder 不创建不可变对象?

    在很多网站上 我看到 lombok Builder 可以用来创建不可变的对象 https www baeldung com lombok builder singular https www baeldung com lombok buil
  • 我可以限制分布式应用程序发出的请求吗?

    我的应用程序发出 Web 服务请求 提供商处理的请求有最大速率 因此我需要限制它们 当应用程序在单个服务器上运行时 我曾经在应用程序级别执行此操作 一个对象跟踪到目前为止已发出的请求数量 并在当前请求超出允许的最大负载时等待 现在 我们正在
  • 使用 Java https 上传到 Imgur v3 错误

    我目前正在尝试使用他们当前的 API v3 上传到 imgur 但是我不断收到错误 错误 javax net ssl SSLException 证书中的主机名不匹配 api imgur com imgur com OR imgur com
  • ECDH使用Android KeyStore生成私钥

    我正在尝试使用 Android KeyStore Provider 生成的私有文件在 Android 中实现 ECDH public byte ecdh PublicKey otherPubKey throws Exception try
  • Java 的 PriorityQueue 与最小堆有何不同?

    他们为什么命名PriorityQueue如果你不能插入优先级 它看起来与堆非常相似 有什么区别吗 如果没有区别那为什么叫它PriorityQueue而不是堆 默认的PriorityQueue是用Min Heap实现的 即栈顶元素是堆中最小的

随机推荐

  • JDK历史所有版本下载地址(附Oracle帐号)

    由于有时在新的电脑或者服务器上需要安装新的JDK 但现在下载JDK已经没有之前方便了 需要登录才能下载 今天在这里我就来把jdk所有的版本下载地址与帐号列出来 方便大家下载 JDK所有版本下载地址 Java SE 14 Java SE 13
  • 逆向工具常用操作

    IDA 加载文件 Windows 下 用IDA加载文件之后 会在文件同目录下生成几个文件 id0 二叉树数据库 id1 文件包含描述每个程序字节的标志 nam 包含IDA Name 窗口的数据库 til 本地数据库有关信息 常用快捷键 快捷
  • 1120 哈夫曼树的创建遍历查找当前节点的编码

    package com import java util ArrayList import java util Collections import java util LinkedList import java util Stack 类
  • 阿里架构精心整理出来一份(Nginx实战.pdf)资料,请签收

    前言 Nginx 很火 因为它就像一个万能药 在任何存在性能需求的场合总能找见它的身影 它可以轻松在百万并发连接下实现高吞吐量的 Web 服务 同时 类似于 OpenResty 和 Tengine 这样的第三方模块群 进一步发展出了新生态
  • sql注入详解

    目录 前言 一 漏洞原因分析 二 漏洞危害 三 sql注入防范 四 如何挖掘sql注入漏洞 五 常见的注入手法 联合查询 union注入 报错注入 基于布尔的盲注 基于时间的盲注 HTTP头注入 宽字节注入 堆叠查询 二阶注入 六 sql注
  • ElsticSearch学习:ElasticSearch基本概念

    ElasticSearch肯定要和我们常用的MySQL这些关系型数据库对比 ES是面向文档的 下面是一个对比 关系型数据库 例如MySQL ElasticSearch 数据库 database 索引 indicies 表 tables ty
  • substr函数用法详解

    substr string start lt length gt 从string的start位置开始提取字符串 length 要提取字符串的长度 若length为以下任意条件之一时 返回start位置到串尾的所有字符 length不指定 l
  • 解决ubuntu(16.04版本)和windows电脑之间无法复制粘贴问题

    1 执行下列命令 sudo apt get autoremove open vm tools sudo apt get install open vm tools desktop 安装过程中 yes或者y一路通过 2 然后重启ubuntu就
  • 七夕王者服务器维护,2017年8月8日维护公告,七夕限量飞行祥瑞冰晶魅灵部分服务器放出...

    原标题 2017年8月8日维护公告 七夕限量飞行祥瑞冰晶魅灵部分服务器放出 亲爱的玩家朋友 为保证服务器的运行稳定和服务质量 梦幻西游 所有服务器将于2017年8月8日上午8 00停机 进行每周例行的维护工作 预计维护时间为上午8 00至9
  • db2常用的时间操作(数据库查询)

    请注意 使用时 请把文中空格替换 文中的空格有误 获取当前日期 select current date from sysibm sysdummy1 values current date 获取当前日期 select current time
  • onnx 模型转换与 onnxruntime 和caffe2 推理速度比较

    onnx 模型转换与 onnxruntime 和caffe2 推理速度比较 背景 1 模型转换 2 PC端运行onnx模型 背景 pytorch 模型通常包括网络结构 py文件和模型参数文件 pth 通常需要转换为onnx格式再向其他终端或
  • 【算法】广度/宽度优先搜索(BFS)

    挺好的一篇文章 讲的挺清楚 广度 宽度优先搜索 BFS 算法入门 郭志伟 SYSU raphealguo at qq com 2012 04 27 1 前言 广度优先搜索 也称宽度优先搜索 缩写BFS 以下采用广度来描述 是连通图的一种遍历
  • 针对VS2019无法登录问题

    摘要 针对VS2019无法登录问题提出一种可行有效的解决方法 VS2019在提供30天试用期后 会要求用户登录后才能使用 但VS2019提供的登录微软账户方法非常不友好 本文将通过更改登录设置方法实现VS2019的简单快捷登录 问题描述 一
  • dotNet基于office实现word转pdf

    20171228 WordToPdf byDotNet 基于Office的实现步骤 主要是利用了 office com 组件中的 Microsoft Office Interop word dll 动态链接库文件可以通过 c 代码实现对 w
  • 科普文章|通过Polkassembly平台使用MetaMask参与Moonbeam链上民主治理

    Moonriver上的Runtime 1200升级引入了一个民主预编译的功能 允许网络参与者使用MetaMask钱包参与链上治理投票 此外 近期Polkassembly与Mooriver集成 这是一个供任何人可以讨论并参与基于Substra
  • scala机器学习实战(一) 保险数据预测分析

    scala机器学习之保险数据预测分析 数据资料来源 此文章数据内容来源于Scala Machine Learning Projects 2018版 一书 本书分为是一个章节 本文章内容来自于第一章节 书本链接 Scala Machine L
  • unity图片相似度2

    using System Collections using System Collections Generic using System IO using UnityEngine using UnityEngine UI public
  • OneOS 定位功能测评+开发详解

    本文分享自中移OneOS微信公众号 定位功能测评 开发详解 本期严同学为了给大家展现 OnePos定位服务能力 复现地铁轨迹线路 坐了大半天的地铁 老辛苦了 这期视频大家一定要看看喔 点此跳转演示视频 想要一比一复原开发流程的小伙伴 可以看
  • Windows10 屏幕底部有一条蓝线挡住任务栏底部解决办法

    Windows10 屏幕底部有一条蓝线挡住任务栏底部解决办法 网上无效解决办法 跳出睡眠模式 网上无效解决办法 1 任务栏设置 选择总是隐藏标签 这个在我这一版的Windows10早就没有这个选项了 其他的选项也都没有用 2 屏幕物理损坏或
  • Java HTTP 代理服务器

    Java HTTP 代理服务器 在当今的企业开发环境中 我们不得不与代理打交道 通常是作为系统管理员 在大多数情况下 应用程序将配置为系统的默认设置 但如果您想对应用程序进行非常严格的控制 例如代理设置 对于这种情况 Java允许使用 AP