启动 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;
@Service
public 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;
@Component
public 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