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

如何使用Jersey实现Java微服务对非Java服务的接口请求代理转发

Jersey实现微服务接口代理转发方案

Jersey本身没有内置反向代理组件,但可以通过两种低成本方案实现你要求的路由规则,不需要引入额外网关组件,其余路径的请求也不会受影响。

路由规则适配说明

你要求的转发逻辑可以直接匹配:

  • 路径前缀为/api/microservice-b/alias-to-microservice-a/*的所有请求,拦截后转发到微服务A
  • 其余路径请求会正常走微服务B自身的资源类处理逻辑,无冲突

方案1:Jersey过滤器 + HTTP客户端实现(通用无侵入,推荐)

这个方案是最灵活的,不需要适配微服务A的接口定义,所有符合前缀的请求直接自动转发,适合接口数量多、迭代频繁的场景。

实现步骤

  1. 选择任意HTTP客户端,比如JDK11+自带的HttpClient、OkHttp、Apache HttpClient都可以,下面以JDK自带的HttpClient为例。
  2. 编写自定义请求过滤器,拦截指定前缀的请求,转发到微服务A后直接返回响应,不走后续Jersey资源匹配逻辑。

代码示例

import org.glassfish.jersey.server.ContainerRequest;
import javax.annotation.Priority;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.List;

@Provider
@Priority(1) // 优先级设为最高,保证在资源匹配前执行
public class ServiceAProxyFilter implements ContainerRequestFilter {
    // 微服务A的根地址,建议放到配置文件中读取
    private static final String SERVICE_A_BASE = "http://微服务A的IP:端口/";
    // 需要代理的路径前缀
    private static final String PROXY_PATH_PREFIX = "/api/microservice-b/alias-to-microservice-a/";
    private static final HttpClient HTTP_CLIENT = HttpClient.newHttpClient();

    @Override
    public void filter(ContainerRequestContext requestCtx) {
        String fullPath = ((ContainerRequest) requestCtx).getPath(true);
        // 非代理前缀的请求直接放过,走微服务B自身逻辑
        if (!fullPath.startsWith(PROXY_PATH_PREFIX)) {
            return;
        }
        // 拼接目标地址:去掉前缀部分,加上微服务A的根地址,同时拼接原请求的查询参数
        String targetPath = fullPath.substring(PROXY_PATH_PREFIX.length());
        String queryStr = requestCtx.getUriInfo().getRequestUri().getRawQuery();
        String targetUrl = SERVICE_A_BASE + targetPath + (queryStr != null ? "?" + queryStr : "");
        
        try {
            // 复制原请求的方法、请求体、请求头
            HttpRequest.Builder reqBuilder = HttpRequest.newBuilder()
                    .uri(URI.create(targetUrl))
                    .method(requestCtx.getMethod(), 
                            HttpRequest.BodyPublishers.ofInputStream(requestCtx::getEntityStream));
            // 复制请求头,按需过滤不需要的头(比如host、content-length等)
            requestCtx.getHeaders().forEach((key, values) -> {
                if (!List.of("host", "content-length").contains(key.toLowerCase())) {
                    values.forEach(v -> reqBuilder.header(key, v));
                }
            });
            // 发送请求到微服务A
            HttpResponse<byte[]> resp = HTTP_CLIENT.send(reqBuilder.build(), HttpResponse.BodyHandlers.ofByteArray());
            // 构建返回响应,复制微服务A返回的状态码、响应头、响应体
            Response.ResponseBuilder respBuilder = Response.status(resp.statusCode());
            resp.headers().map().forEach((key, values) -> values.forEach(v -> respBuilder.header(key, v)));
            respBuilder.entity(resp.body());
            // 直接中止后续请求处理,返回代理结果
            requestCtx.abortWith(respBuilder.build());
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            requestCtx.abortWith(Response.status(Response.Status.SERVICE_UNAVAILABLE)
                    .entity("转发请求被中断").build());
        } catch (Exception e) {
            requestCtx.abortWith(Response.status(Response.Status.BAD_GATEWAY)
                    .entity("微服务A请求失败").build());
        }
    }
}

注册配置

把写好的过滤器注册到你的Jersey配置类即可,比如使用ResourceConfig的场景:

import org.glassfish.jersey.server.ResourceConfig;

public class JerseyConfig extends ResourceConfig {
    public JerseyConfig() {
        // 注册你自己的业务资源包
        packages("com.xxx.microserviceb.resources");
        // 注册代理过滤器
        register(ServiceAProxyFilter.class);
    }
}

方案2:使用jersey-proxy-client(Jersey生态原生方案)

如果微服务A的接口数量少且迭代频率低,可以用Jersey官方的proxy-client模块,省去自己写请求、响应复制的逻辑。

实现步骤

  1. 引入jersey-proxy-client依赖,版本要和你项目使用的Jersey版本一致:
<dependency>
    <groupId>org.glassfish.jersey.ext</groupId>
    <artifactId>jersey-proxy-client</artifactId>
    <version>${jersey.version}</version>
</dependency>
  1. 手写和微服务A接口路径、入参、出参完全匹配的Java接口,接口的@Path注解前缀设置为/alias-to-microservice-a。
  2. 用WebResourceFactory生成指向微服务A地址的代理实例,注册为Jersey的资源Bean即可,Jersey会自动把匹配路径的请求转发到微服务A。

这个方案的缺点是如果微服务A是非Java项目,手写接口的维护成本比较高,适合接口规模小的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 10:24:02