如何从JAX-RS拦截器/过滤器中获取代理资源接口的@Path注解值
JAX-RS获取路径模板及匹配资源接口的解决方案
服务端请求拦截场景(使用ContainerRequestFilter)
JAX-RS 2.0及以上版本规范原生提供了路径模板获取能力,不需要依赖具体实现的扩展API:
- 从请求上下文获取
UriInfo对象,调用getMatchedTemplates()方法可以拿到匹配到的所有层级路径模板(按方法级到类级的顺序返回) - 倒序拼接模板列表即可得到完整的原始路径模板,不会包含实际请求的参数值
示例代码:
@Provider public class TracingContainerFilter implements ContainerRequestFilter { @Override public void filter(ContainerRequestContext requestContext) throws IOException { UriInfo uriInfo = requestContext.getUriInfo(); List<UriTemplate> matchedTemplates = uriInfo.getMatchedTemplates(); // 倒序拼接得到 类级路径+方法级路径 的完整模板 StringBuilder pathTemplate = new StringBuilder(); for (int i = matchedTemplates.size() - 1; i >= 0; i--) { pathTemplate.append(matchedTemplates.get(i).toString()); } // 生成的分组名称格式示例:GET /user/{id} String traceGroupName = requestContext.getMethod() + " " + pathTemplate; // 写入链路追踪平台即可 } }
客户端请求拦截场景(使用ClientRequestFilter)
如果是使用JAX-RS客户端代理(就是你示例中定义的UserClient这类接口生成的代理调用),可以通过具体实现的上下文属性拿到被调用的接口方法,反射读取注解拼接路径模板:
- RestEasy代理客户端可从上下文获取属性
org.jboss.resteasy.client.jaxrs.internal.proxy.method得到被调用的Method对象 - Jersey代理客户端可从上下文获取属性
org.glassfish.jersey.client.proxy.method得到被调用的Method对象
示例代码:
@Provider public class TracingClientFilter implements ClientRequestFilter { @Override public void filter(ClientRequestContext requestContext) throws IOException { // 以RestEasy代理客户端为例 Method invokedMethod = (Method) requestContext.getProperty("org.jboss.resteasy.client.jaxrs.internal.proxy.method"); if (invokedMethod != null) { Path classPathAnno = invokedMethod.getDeclaringClass().getAnnotation(Path.class); Path methodPathAnno = invokedMethod.getAnnotation(Path.class); String classPath = classPathAnno == null ? "" : classPathAnno.value(); String methodPath = methodPathAnno == null ? "" : methodPathAnno.value(); String pathTemplate = classPath + methodPath; String traceGroupName = requestContext.getMethod() + " " + pathTemplate; // 写入链路追踪平台即可 } } }
注意事项
- 如果路径模板带参数正则约束,比如
@Path("/user/{id : [0-9a-f-]{36}}"),可以自行通过字符串替换去掉正则部分,只保留参数名即可 - 如果需要拿到完整的匹配资源接口/方法,服务端可以通过
UriInfo.getMatchedResources()获取到实例,再反射拿到对应的接口方法
内容的提问来源于stack exchange,提问作者Mitch Kent
相关产品推荐
相关产品推荐

