启动zookeeper

使用的是zookeeper作为注册中心,在运行dubbo项目之前需要启动zookeeper。

xml实现

xml实现是最常使用的一种方式,好处是可以通过配置文件配置注册中心,暴露协议和服务接口,开发人员不需要理会太多Dubbo框架的实现,专注业务逻辑。在公司的项目中使用的也是xml的方式,可以集中管理配置。在github上给出的dubbo-demo有例子。

github上的Dubbo项目

注解实现

maven的依赖直接使用dubbo-demo的就行,代码实现如下:

Api模块:公共的接口

public interface AnnotationService {    public void salHello(String name);}

Provider:服务提供者

服务接口的实现:

import gdut.ff.api.AnnotationService;import org.apache.dubbo.config.annotation.Reference;import org.springframework.stereotype.Component;import gdut.ff.api.AnnotationService;import org.apache.dubbo.config.annotation.Service;import org.apache.dubbo.rpc.RpcContext;@Servicepublic class AnnotationServiceImpl implements AnnotationService {    public void salHello(String name) {        System.out.println(name + " from" + RpcContext.getContext().getRemoteAddress());    }}

注意这里的@Service注解是org.apache.dubbo.config.annotation.Service,不然在扫描包的时候会扫描不到。

用注解实现xml的配置。

import org.apache.dubbo.config.ApplicationConfig;import org.apache.dubbo.config.ProtocolConfig;import org.apache.dubbo.config.ProviderConfig;import org.apache.dubbo.config.RegistryConfig;import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configuration@EnableDubbo(scanBasePackages = "gdut.ff.provider")public class ProviderConfiguration   {    @Bean    public ProviderConfig providerConfig() {        return new ProviderConfig();    }    @Bean    public ApplicationConfig applicationConfig() {        ApplicationConfig applicationConfig = new ApplicationConfig();        applicationConfig.setName("annotation-provider");        return applicationConfig;    }    //配置Zookeeper注册中心    @Bean    public RegistryConfig registryConfig() {        RegistryConfig registryConfig = new RegistryConfig();        registryConfig.setProtocol("zookeeper");        registryConfig.setAddress("127.0.0.1");        registryConfig.setPort(2181);        return registryConfig;    }    //使用Dubbo协议,20880端口监听服务    @Bean    public ProtocolConfig protocolConfig() {        ProtocolConfig protocolConfig = new ProtocolConfig();        protocolConfig.setName("dubbo");        protocolConfig.setPort(20880);        return protocolConfig;    }}

启动的时候,会调用ProviderConfiguration类,根据配置的scanBasePackages扫描对应包下的带有@Service注解的类,并进行注册。

public class AnnotationProviderMain {    public static void main(String[] args) {        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderConfiguration.class);        context.start();        try {            System.in.read();        } catch (IOException e) {            e.printStackTrace();        }    }}

(3)Consumer:服务消费者

消费者对服务接口的实现,是调用提供者的实现。这里是在一个实例AnnotationServiceImpl中用@Reference引用了api的接口AnnotationService,真正调用的时候注入的是服务提供者注册的一个AnnotationService实例。@Reference相当于Spring的@Autowired和@Resource。

import gdut.ff.api.AnnotationService;import org.apache.dubbo.config.annotation.Reference;import org.springframework.stereotype.Component;@Componentpublic class AnnotationServiceImpl {    @Reference    private AnnotationService annotationService;    public void sayHello(String name) {        annotationService.salHello(name);    }}

消费者的配置

import org.apache.dubbo.config.ApplicationConfig;import org.apache.dubbo.config.ConsumerConfig;import org.apache.dubbo.config.RegistryConfig;import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;@Configuration//指定要扫描的消费注解,会触发注入@EnableDubbo(scanBasePackages = "gdut.ff.consumer")@ComponentScan(value = {"gdut.ff.consumer"})public class ConsumerConfiguration {    @Bean    public ApplicationConfig applicationConfig() {        ApplicationConfig applicationConfig = new ApplicationConfig();        applicationConfig.setName("annotation-consumer");        return applicationConfig;    }    @Bean    public ConsumerConfig consumerConfig() {        return new ConsumerConfig();    }    @Bean    public RegistryConfig registryConfig() {        RegistryConfig registryConfig = new RegistryConfig();        registryConfig.setProtocol("zookeeper");        registryConfig.setAddress("127.0.0.1");        registryConfig.setPort(2181);        return registryConfig;    }}

启动

public class AnnotationConsumerMain {    public static void main(String[] args) {        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerConfiguration.class);        context.start();        //获取一个Bean实例        AnnotationServiceImpl bean = context.getBean(AnnotationServiceImpl.class);        bean.sayHello("liufeifei");    }}

API实现

maven的依赖直接使用dubbo-demo的就行,代码实现如下:

Provider:服务提供者

public class ApiProviderMain {    public static void main(String[] args) {        ServiceConfig<AnnotationService> service = new ServiceConfig<AnnotationService>();        service.setApplication(new ApplicationConfig("api-provider"));        service.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));        //指定暴露的接口        service.setInterface(AnnotationService.class);        //这里是直接用new一个对象来进行实例化        service.setRef(new AnnotationServiceImpl());        //暴露服务        service.export();        System.out.println("java api-provider is running");        try {            System.in.read();        } catch (IOException e) {            e.printStackTrace();        }    }}

Consumer:服务消费者

public class ApiConsumerMain {    public static void main(String[] args) {        ReferenceConfig<AnnotationService> annotationServiceReferenceConfig = new ReferenceConfig<AnnotationService>();        annotationServiceReferenceConfig.setApplication(new ApplicationConfig("api-consumer"));        annotationServiceReferenceConfig.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));        //指定要消费的服务接口        annotationServiceReferenceConfig.setInterface(AnnotationService.class);        //创建远程连接并做动态代理转换        AnnotationService annotationService = annotationServiceReferenceConfig.get();        annotationService.salHello("liufeifei");    }}

使用mvn exec:java运行maven项目

在pom.xml文件中添加exec-maven-plugin插件,并指定执行的main方法。

<build>        <plugins>            <plugin>                <groupId>org.codehaus.mojo</groupId>                <artifactId>exec-maven-plugin</artifactId>                <version>1.2.1</version>                <executions>                    <execution>                        <goals>                            <goal>java</goal>                        </goals>                    </execution>                </executions>                <configuration>                    <mainClass>gdut.ff.consumer.ApiConsumerMain</mainClass>                </configuration>            </plugin>        </plugins>    </build>

查看zookeeper有哪些注册的服务接口

windows启动zkCli.cmd。
ls / 查看根节点下有哪些节点
ls /dubbo 查看dubbo节点下有哪些注册的服务。

参考资料

《深入理解Apache Dubbo与实战》
java.lang.IllegalStateException: KeeperErrorCode = ConnectionLoss for /dubbo问题解决
@Service注解的坑
Maven统一声明版本号
查看zookeeper注册中心是否有注册服务
mvn编译java project: Failed to execute goal org.codehaus.mojo:exec-maven-plugin