使用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还是原来的不变,只是版本号有变化罢了。所以首先让我们来升级一下依赖,在 helloImpl
的 pom.xml
里升级dubbo:
<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本身,我们还需要以下的依赖:
<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自身的依赖 ,不管有用没用,先加进来再说:
<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
了:
<!--<dubbo:protocol name="dubbo" port="19880" />--> <dubbo:protocolname="rest"server="tomcat"port="9090" />
把原来的dubbo协议注释掉,增加rest协议,用内置的tomcat启动,端口为9090。这里为了清晰起见,注释掉了dubbo协议,而实际上协议是可以并存的。接下来可以改造我们的 HelloServiceImpl
了。直接放上最后的代码:
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请求。