You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Java/Kotlin中实现嵌入式请求转发代理?求方案及示例

可行的嵌入式代理方案及示例

1. Spring Boot(最简嵌入式方案)

自带嵌入式容器(Tomcat/Jetty/Undertow),快速实现转发逻辑,适合快速开发场景。

Kotlin示例

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.client.RestTemplate

@SpringBootApplication
@RestController
class ProxyApplication {
    private val restTemplate = RestTemplate()
    private val targetBaseUrl = "http://localhost:5051"

    // 匹配所有以/my/path开头的请求,转发到目标服务器
    @RequestMapping("/my/path/**")
    fun forwardRequest(@PathVariable("**") path: String): Any {
        val targetUrl = "$targetBaseUrl/$path"
        // 可扩展处理请求头、请求体,默认转发基础请求信息
        return restTemplate.getForObject(targetUrl, Any::class.java)
    }
}

fun main(args: Array<String>) {
    runApplication<ProxyApplication>(*args) {
        setDefaultProperties(mapOf("server.port" to 9090))
    }
}

若需处理POST/PUT等请求,可添加对应@RequestMapping方法,或不指定请求方法并补充请求体转发逻辑。

2. OkHttp 轻量代理(无容器依赖)

无需嵌入式容器,直接基于OkHttp实现HTTP服务器+转发逻辑,资源占用极低。

Kotlin示例

import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import okhttp3.HttpUrl.Companion.toHttpUrl
import com.sun.net.httpserver.HttpServer
import java.net.InetSocketAddress

fun main() {
    val server = HttpServer.create(InetSocketAddress(9090), 0)
    val client = OkHttpClient()
    val targetBase = "http://localhost:5051".toHttpUrl()

    // 注册/my/path路径处理器
    server.createContext("/my/path") { exchange ->
        val requestPath = exchange.requestURI.path.removePrefix("/my/path")
        val targetUrl = targetBase.newBuilder().encodedPath(requestPath).build()

        // 构建转发请求,保留原请求头和请求体
        val forwardRequest = Request.Builder()
            .url(targetUrl)
            .method(exchange.requestMethod, exchange.requestBody.takeIf { it != -1 }?.let {
                okhttp3.RequestBody.create(null, exchange.requestBody)
            })
            .apply {
                exchange.requestHeaders.forEach { key, values ->
                    values.forEach { addHeader(key, it) }
                }
            }
            .build()

        // 发送请求并返回原始响应
        client.newCall(forwardRequest).execute().use { response ->
            exchange.sendResponseHeaders(response.code, response.body?.contentLength() ?: -1)
            response.body?.byteStream()?.copyTo(exchange.responseBody)
            exchange.close()
        }
    }

    server.start()
    println("Proxy running on http://localhost:9090")
}

3. Netty(高性能并发场景)

适合高并发请求场景,基于NIO实现,性能优于传统容器。

Java示例(简化版)

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.*;
import java.net.URI;

public class NettyProxyServer {
    private static final String TARGET_HOST = "localhost";
    private static final int TARGET_PORT = 5051;
    private static final int PROXY_PORT = 9090;

    public static void main(String[] args) throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
             .channel(NioServerSocketChannel.class)
             .childHandler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 public void initChannel(SocketChannel ch) {
                     ChannelPipeline p = ch.pipeline();
                     p.addLast(new HttpRequestDecoder());
                     p.addLast(new HttpResponseEncoder());
                     p.addLast(new ProxyHandler());
                 }
             });

            ChannelFuture f = b.bind(PROXY_PORT).sync();
            f.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    private static class ProxyHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) {
            // 移除/my/path前缀,拼接目标路径
            String path = req.uri().replaceFirst("^/my/path", "");
            URI targetUri = URI.create("http://" + TARGET_HOST + ":" + TARGET_PORT + path);

            // 构建客户端连接到目标服务器
            Bootstrap clientBootstrap = new Bootstrap();
            clientBootstrap.group(ctx.channel().eventLoop())
                           .channel(ctx.channel().getClass())
                           .handler(new ChannelInitializer<SocketChannel>() {
                               @Override
                               protected void initChannel(SocketChannel ch) {
                                   ch.pipeline().addLast(new HttpResponseDecoder());
                                   ch.pipeline().addLast(new HttpRequestEncoder());
                                   ch.pipeline().addLast(new ClientHandler(ctx.channel()));
                               }
                           });

            // 连接成功后转发请求
            clientBootstrap.connect(TARGET_HOST, TARGET_PORT).addListener((ChannelFutureListener) future -> {
                if (future.isSuccess()) {
                    future.channel().writeAndFlush(req.retain());
                } else {
                    ctx.channel().close();
                }
            });
        }
    }

    private static class ClientHandler extends SimpleChannelInboundHandler<FullHttpResponse> {
        private final Channel proxyChannel;

        public ClientHandler(Channel proxyChannel) {
            this.proxyChannel = proxyChannel;
        }

        @Override
        protected void channelRead0(ChannelHandlerContext ctx, FullHttpResponse resp) {
            // 将目标服务器的原始响应返回给JCEF浏览器
            proxyChannel.writeAndFlush(resp.retain());
        }

        @Override
        public void channelInactive(ChannelHandlerContext ctx) {
            proxyChannel.close();
        }
    }
}

4. Vert.x(响应式轻量方案)

基于事件驱动的响应式框架,资源占用低,适合嵌入式场景。

Kotlin示例

import io.vertx.core.Vertx
import io.vertx.ext.web.Router
import io.vertx.ext.web.client.WebClient

fun main() {
    val vertx = Vertx.vertx()
    val client = WebClient.create(vertx)
    val router = Router.router(vertx)
    val targetBase = "http://localhost:5051"

    // 匹配所有/my/path下的请求
    router.route("/my/path/*").handler { ctx ->
        val path = ctx.request().path().removePrefix("/my/path")
        val targetUrl = "$targetBase$path"

        // 转发请求,保留原请求头和请求体
        client.request(ctx.request().method(), targetUrl)
            .putHeaders(ctx.request().headers())
            .send(ctx.request().body())
            .onSuccess { response ->
                ctx.response()
                    .setStatusCode(response.statusCode())
                    .putHeaders(response.headers())
                    .end(response.body())
            }
            .onFailure { ctx.response().setStatusCode(500).end("Proxy error") }
    }

    vertx.createHttpServer().requestHandler(router).listen(9090) {
        if (it.succeeded()) {
            println("Proxy running on http://localhost:9090")
        }
    }
}

内容的提问来源于stack exchange,提问作者Shin938

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 13:55:21