Quarkus 中使用 JAX-RS 客户端处理可变长度路径参数的正确方式

在 quarkus 的 microprofile rest client 中,若需调用路径深度动态、含多级斜杠(如 `/json/employees/dwight/jobs/...`)的 rest 接口,直接传入含 `/` 的字符串会导致自动 url 编码(如 `/` → `%2f`),破坏原始路径语义;正确解法是结合 jax-rs 路径正则表达式与 `@pathparam`,精

准捕获未编码的完整子路径。

要实现真正“透传”任意长度、含多级斜杠的路径片段(例如 /employees/Dwight/jobs/assistantRegionalManager/salary),关键在于让 JAX-RS 路由引擎将整个路径段视为一个原子单元,而非按 / 拆分解析。此时不能依赖默认的路径参数行为(它会将 / 视为分隔符并自动编码),而应使用 JAX-RS 内置的正则路径约束(Path Regex)机制。

✅ 正确写法如下:

@Path("/json")
@RegisterRestClient(configKey = "json-api")
public interface JsonService {

    @GET
    @Path("/{varPath:.+}")  // ← 核心:".+" 匹配一个或多个任意字符(含 '/'),且不触发分段编码
    Response getJson(@PathParam("varPath") String endpoint);
}
  • {varPath:.+} 中的 :.+ 是 JAX-RS 标准语法,表示该路径参数需匹配正则 .+(即非空、贪婪匹配所有后续字符,包括 /);

  • @PathParam("varPath") String 直接接收原始路径片段,不会被客户端自动 URL 编码 —— 因为 JAX-RS 运行时已将其作为整体捕获,绕过了逐段解析逻辑;

  • 示例调用:

    JsonService client = RestClientBuilder.newBuilder()
        .baseUri(URI.create("https://api.example.com"))
        .build(JsonService.class);
    
    Response res1 = client.getJson("employees/Dwight/jobs/assistantRegionalManager/salary");
    Response res2 = client.getJson("games/theLastOfUs/rating");

    将分别发出请求:

    • GET /json/employees/Dwight/jobs/assistantRegionalManager/salary
    • GET /json/games/theLastOfUs/rating

⚠️ 注意事项:

  • ❌ 不要使用 @Encoded:它仅影响 @QueryParam 或 @MatrixParam 的编码行为,对 @PathParam 无效;
  • ❌ 避免 /{varPath}(无正则):JAX-RS 会将其按 / 切分为多个空参数,导致 404 或错误解析;
  • ❌ 不要传入 List:Quarkus REST Client 不支持该类型作为 @PathParam 绑定目标,编译或运行时报错;
  • ✅ 确保服务端路由也支持通配(如 Spring Boot 用 @GetMapping("/json/**"),或 Quarkus 服务端用 @Path("/json/{path:.+}")),否则响应 404 与客户端无关;
  • ? 若路径含敏感字符(如空格、#、?),仍需由调用方预处理(如 URLEncoder.encode(..., "UTF-8")),但本场景中纯路径语义的 / 已被正则保障原样传递。

总结:可变长嵌套路径的本质是「路径段透传」,而非「参数拼接」。唯一可靠、标准、零侵入的方案就是 JAX-RS 路径正则 /{param:regex} —— 它既是规范要求,也是 Quarkus、OpenLiberty、Thorntail 等主流 MicroProfile 实现的通用能力。