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
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.8.4</version>
<exclusions>
<exclusion>
<artifactId>spring-expression</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-beans</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-aop</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>

使用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
10
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.7</version>
</dependency>

再然后就是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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>3.0.7.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>3.0.7.Final</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>
<!-- 如果要使用json序列化 -->
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson-provider</artifactId>
<version>3.0.7.Final</version>
</dependency>
<!-- 如果要使用xml序列化 -->
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxb-provider</artifactId>
<version>3.0.7.Final</version>
</dependency>
<!-- 如果要使用netty server -->
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-netty</artifactId>
<version>3.0.7.Final</version>
</dependency>
<!-- 如果要使用Sun HTTP server -->
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jdk-http</artifactId>
<version>3.0.7.Final</version>
</dependency>
<!-- 如果要使用tomcat server -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>8.0.11</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-logging-juli</artifactId>
<version>8.0.11</version>
</dependency>

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

1
2
<!--<dubbo:protocol name="dubbo" port="19880" />-->
<dubbo:protocol name="rest" server="tomcat" port="9090" />

把原来的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请求。