使用dubbox为dubbo提供REST服务

Dubbo是阿里多年前开源的一套服务治理框架,在众多互联网企业里应用广泛。当当在dubbo的基础上开发了dubbox(Dubbo eXtensions),支持REST风格远程调用。本文在服务治理框架dubbo上手指南的基础上使用dubbox提供的REST服务。

首先参考服务治理框架dubbo上手指南,实现自己的dubbo服务。在此基础上,让我们来看看在Dubbo中开发REST风格的远程调用。REST的优势就不多说了,本文关注的是快速搭建环境。

光看dubbox的官方文档稍微有一点儿坑,因为它对于maven依赖的描述基本没有。Dubbo本身的维护已经不太活跃了,最新的版本是2.5.4-SNAPSHOT。当当接下了维护的重任,目前的最新版是dubbox-2.8.4,其实groupId和artifactId还是原来的不变,只是版本号有变化罢了。所以首先让我们来升级一下依赖,在helloImplpom.xml里升级dubbo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

com.alibaba
dubbo
2.8.4


spring-expression
org.springframework


spring-beans
org.springframework


spring-aop
org.springframework



使用mvn dependency:tree命令可以看到,dubbox依赖于spring的3.2.9.RELEASE版本。由于我们上一个dubbo的练习中使用了spring的4.2.4.RELEASE版本,所以会有依赖冲突。解决冲突的办法有两个,一是把我们的spring降级到dubbox依赖的3.2.9.RELEASE版本,二是使用exclusions把dubbox依赖的几个spring包都解除掉。这里我们的配置采用了后者。除了dubbox本身,我们还需要以下的依赖:

1
2
3
4
5
6
7
8
9

org.springframework
spring-core
4.2.4.RELEASE

com.101tec
zkclient
0.7

再然后就是dubbox自身的依赖,不管有用没用,先加进来再说:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

org.jboss.resteasy
resteasy-jaxrs
3.0.7.Final

org.jboss.resteasy
resteasy-client
3.0.7.Final

javax.validation
validation-api
1.0.0.GA

org.jboss.resteasy
resteasy-jackson-provider
3.0.7.Final

org.jboss.resteasy
resteasy-jaxb-provider
3.0.7.Final

org.jboss.resteasy
resteasy-netty
3.0.7.Final

org.jboss.resteasy
resteasy-jdk-http
3.0.7.Final

org.apache.tomcat.embed
tomcat-embed-core
8.0.11

org.apache.tomcat.embed
tomcat-embed-logging-juli
8.0.11

这样就把所有的依赖都解决了,现在可以修改dubbo的服务配置文件provider.xml了:

1
2
-->

把原来的dubbo协议注释掉,增加rest协议,用内置的tomcat启动,端口为9090。这里为了清晰起见,注释掉了dubbo协议,而实际上协议是可以并存的。接下来可以改造我们的HelloServiceImpl了。直接放上最后的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package org.ggg.hello.service.provider;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;

import org.ggg.hello.service.HelloService;

@Path("demo")
public class HelloServiceImpl implements HelloService {

@GET
@Path("greeting")
@Produces("application/json; charset=UTF-8")
public String sayHello(@QueryParam("name") String name) {
return "Hello " + name;
}
}

首先我们在类上增加了一个注解@Path("demo"),它指定访问HelloService的URL相对路径是/demo,即http://localhost:9090/demo。方法上也有一个@Path("greeting"),相当于访问这个方法的URL为http://localhost:9090/demo/greeting@GET就不用多说了,@Produces可以在Response Headers里增加Content-Type: application/json;charset=UTF-8。如果有必要,也可以来一个相对应的@Consumes("application/json")。在参数上还有一个注解@QueryParam("name"),有了它就可以通过URL参数的方式传值过来了。启动Provider之后,没有意外的话应该能看见控制台的日志:Starting ProtocolHandler [“http-nio-9090”],接下来就可以通过访问http://localhost:9090/demo/greeting?name=ggg来访问我们的服务了。屏幕上可以看到:Hello ggg

至此,我们以一个并不太RESTful的URL完成了一个REST请求。