dubbo消费者调用报错java.lang.RuntimeException: You must use at least one, but no more than one http method

服务提供者启动成功后,启动消费者时报错:

com.alibaba.dubbo.registry.integration.RegistryDirectory -  [DUBBO] Failed to refer invoker for interface

You must use at least one, but no more than one http method annotation on:

    at org.jboss.resteasy.client.jaxrs.ProxyBuilder.createClientInvoker(ProxyBuilder.java:76) ~[resteasy-client-3.0.7.Final.jar:?]
    at org.jboss.resteasy.client.jaxrs.ProxyBuilder.proxy(ProxyBuilder.java:52) ~[resteasy-client-3.0.7.Final.jar:?]
    at org.jboss.resteasy.client.jaxrs.ProxyBuilder.build(ProxyBuilder.java:120) ~[resteasy-client-3.0.7.Final.jar:?]
    at org.jboss.resteasy.client.jaxrs.internal.ClientWebTarget.proxy(ClientWebTarget.java:72) ~[resteasy-client-3.0.7.Final.jar:?]
    at com.alibaba.dubbo.rpc.protocol.rest.RestProtocol.doRefer(RestProtocol.java:161) ~[dubbo-2.8.3.jar:2.8.3]
    at com.alibaba.dubbo.rpc.protocol.AbstractProxyProtocol.refer(AbstractProxyProtocol.java:88) ~[dubbo-2.8.3.jar:2.8.3]
    at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper.refer(ProtocolFilterWrapper.java:62) ~[dubbo-2.8.3.jar:2.8.3]
    at com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper.refer(ProtocolListenerWrapper.java:65) ~[dubbo-2.8.3.jar:2.8.3]
    at com.alibaba.dubbo.rpc.Protocol$Adpative.refer(Protocol$Adpative.java) ~[dubbo-2.8.3.jar:2.8.3]
    at com.alibaba.dubbo.registry.integration.RegistryDirectory.toInvokers(RegistryDirectory.java:395) [dubbo-2.8.3.jar:2.8.3]
    at com.alibaba.dubbo.registry.integration.RegistryDirectory.refreshInvoker(RegistryDirectory.java:224) [dubbo-2.8.3.jar:2.8.3]
    at com.alibaba.dubbo.registry.integration.RegistryDirectory.notify(RegistryDirectory.java:195) [dubbo-2.8.3.jar:2.8.3]
    at com.alibaba.dubbo.registry.support.AbstractRegistry.notify(AbstractRegistry.java:449) [dubbo-2.8.3.jar:2.8.3]


进入源码中查看ProxyBuilder.createClientInvoker的前后执行代码,调用这个方法是ProxyBuilder.proxy(final Class<T> iface, WebTarget base, final ProxyConfig config),iface是被代理的接口

public static <T> T proxy(final Class<T> iface, WebTarget base, final ProxyConfig config)
{
     if (iface.isAnnotationPresent(Path.class))
     {
        Path path = iface.getAnnotation(Path.class);
        if (!path.value().equals("") && !path.value().equals("/"))
        {
           base = base.path(path.value());
        }
     }
   HashMap<Method, MethodInvoker> methodMap = new HashMap<Method, MethodInvoker>();
   for (Method method : iface.getMethods())
   {
        MethodInvoker invoker;
        Set<String> httpMethods = IsHttpMethod.getHttpMethods(method);
        if ((httpMethods == null || httpMethods.size() == 0) && method.isAnnotationPresent(Path.class) && method.getReturnType().isInterface())
        {
           invoker = new SubResourceInvoker((ResteasyWebTarget)base, method, config);
        }
        else
        {
           invoker = createClientInvoker(iface, method, (ResteasyWebTarget)base, config);
        }
        methodMap.put(method, invoker);
   }

   Class<?>[] intfs =
   {
         iface
   };

   ClientProxy clientProxy = new ClientProxy(methodMap);
   // this is done so that equals and hashCode work ok. Adding the proxy to a
   // Collection will cause equals and hashCode to be invoked. The Spring
   // infrastructure had some problems without this.
   clientProxy.setClazz(iface);

   return (T) Proxy.newProxyInstance(config.getLoader(), intfs, clientProxy);
}

该方法中的条件method.isAnnotationPresent(Path.class)判断方法上是否有@Path注解,由于代码中@Path及相关注解都是在实现类和实现类的方法中,获取不到返回false进入createClientInvoker方法:

private static <T> ClientInvoker createClientInvoker(Class<T> clazz, Method method, ResteasyWebTarget base, ProxyConfig config)
{
   Set<String> httpMethods = IsHttpMethod.getHttpMethods(method);
   if (httpMethods == null || httpMethods.size() != 1)
   {
      throw new RuntimeException("You must use at least one, but no more than one http method annotation on: " + method.toString());
   }
   ClientInvoker invoker = new ClientInvoker(base, clazz, method, config);
   invoker.setHttpMethod(httpMethods.iterator().next());
   return invoker;
}

而IsHttpMethod.getHttpMethods(method)首先要从方法上获取注解,getHttpMethods方法代码如下:

public static Set<String> getHttpMethods(Method method)
{
   HashSet<String> methods = new HashSet<String>();
   for (Annotation annotation : method.getAnnotations())
   {
      HttpMethod http = annotation.annotationType().getAnnotation(HttpMethod.class);
      if (http != null) methods.add(http.value());
   }
   if (methods.size() == 0) return null;
   return methods;
}

但是手上的项目中,该类上仅有两个方法上添加了@Path、@Post、@Produces等注解,且该类为实现类,编译打包后proxy接口时找不到注解,问题找到了。

问题解决:将该类上的@Path、@Post、@Produces等注解转移到接口上,并给该接口其他没有注解的方法上也全部加上@Path和@Post、@Get等注解后问题解决

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值