Dubbo:使用 Spring 注解构建 Dubbo 服务


#Dubbo#


示例

项目结构和 Dubbo:第一个 Dubbo 项目 中的示例相同:

.
├── README.md
├── build.gradle
├── settings.gradle
├── consumer
│   ├── src
│       └── main
│           ├── java
│           │   └── demo
│           │       └── consumer
│           │           └── ConsumerMain.java
│           └── resources
│               ├── dubbo-consumer.xml
│               ├── dubbo.properties
│               └── log4j.properties
├── contract
│   ├── src
│       └── main
│           └── java
│               └── demo
│                   └── contract
│                       └── DemoService.java
├── provider
    ├── src
        └── main
            ├── java
            │   └── demo
            │       └── provider
            │           ├── DemoServiceImpl.java
            │           └── ProviderMain.java
            └── resources
                ├── dubbo-provider.xml
                ├── dubbo.properties
                └── log4j.properties

代码大部分也相同。

build.gradle

group 'com.example'
version '1.0-SNAPSHOT'

apply plugin: 'java'

sourceCompatibility = 1.8

ext {
  dubboVersion = '2.7.1'
  zookeeperVersion = '3.4.10'
  zkclientVersion = '0.10'
  junitVersion = '4.12'
}

allprojects {
  apply plugin: 'java'

  repositories {
    maven { url 'https://maven.aliyun.com/repository/public/' }
    mavenCentral()
  }

}

// 配置子项目 contract
project(":contract") {

  dependencies {

    testCompile "junit:junit:$junitVersion"

  }
}

// 配置子项目 consumer
project(":consumer") {

  dependencies {
    compile project(":contract") // 依赖子项目 contract
    compile "org.apache.dubbo:dubbo:$dubboVersion"
    compile "org.apache.dubbo:dubbo-dependencies-zookeeper:$dubboVersion"

    testCompile "junit:junit:$junitVersion"
  }

}

project(":provider") {  // 配置子项目 provider

  dependencies {

    compile project(":contract") // 依赖子项目 contract
    compile "org.apache.dubbo:dubbo:$dubboVersion"
    compile "org.apache.dubbo:dubbo-dependencies-zookeeper:$dubboVersion"

    testCompile "junit:junit:$junitVersion"
  }

}

log4j.properties

log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] %X{IP} - %m%n

dubbo.properties

dubbo.application.qos.port=33333

接口实现

在 contract 模块中,添加以下接口:

package demo.contract;

public interface DemoService {

    String sayHello(String name);

}

服务实现

provider 模块实现了 dubbo 服务。

package demo.provider;

import demo.contract.DemoService;
import org.springframework.stereotype.Service;

@Service // 这个注解不是必须的,dubbo 会自动处理,但是加上更容易读代码
public class DemoServiceImpl implements DemoService {

    @Override
    public String sayHello(String name) {
        return "Hello, " + name;
    }

}

src/main/resources 目录增加 dubbo-provider.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <dubbo:application name="hello-world-app"></dubbo:application>
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
    <dubbo:protocol name="dubbo" port="20881"/>

    <dubbo:service interface="demo.contract.DemoService" class="demo.provider.DemoServiceImpl"/>

</beans>

Dubbo:第一个 Dubbo 项目 不同的是,<dubbo:service interface="demo.DemoService" class="demo.DemoServiceImpl"/> 没有用 ref,而是用 class。

主函数:

package demo.provider;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;

import java.io.IOException;

@Configuration
@ComponentScan
@ImportResource({"dubbo-provider.xml"})
public class ProviderMain {

    public static void main(String[] args) throws IOException {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(ProviderMain.class);
        System.in.read();
    }

}

消费者(调用者)实现

在 consumer 模块的 src/main/resources 目录增加 dubbo-consumer.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <dubbo:application name="consumer-of-helloworld-app"/>
    <dubbo:consumer timeout="5000" />
    <dubbo:registry address="zookeeper://127.0.0.1:2181" check="false"/>

    <dubbo:reference id="demoService" interface="demo.contract.DemoService" check="false"/>

</beans>

编写消费逻辑:

package demo.consumer;

import demo.contract.DemoService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;

@Configuration
@ComponentScan
@ImportResource({"dubbo-consumer.xml"})
public class ConsumerMain {

    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(ConsumerMain.class);
        DemoService demoService = ctx.getBean(DemoService.class);
        String s = demoService.sayHello("张三");
        System.out.println(s);
        // 结果是输出 "Hello, 张三"
    }

}

运行效果

先执行 provider 中的ProviderMain 类,它会告诉zookeeper它可以提供demo.DemoService这个接口对应的服务,服务IP是多少,端口是多少。欢迎别的服务过来调用。

再执行 consumer 中的 ConsumerMain 类,它会去问zookeeper有没有服务提供了demo.DemoService这个接口的实现,有的话,告诉我位置(可能1个或者多个),我去调用其中一个。

然后 ConsumerMain 运行后会输出一堆结果(大部分是 dubbo 产生的日志),其中我们能看到:

Hello, 张三

结果符合预期。

纯注解

上面的实现中还是要对 dubbo 服务进行配置。有没有方式,只用注解,不用任何 xml 文件配置 ?

请参考官网网站给出的文章: 在 Dubbo 中使用注解


( 本文完 )