回顾
大家好,我是老马。
上一节我们一起学习了 5 分钟入门 spring cloud 实战笔记。
本文大家一起来学习下 dubbo 的入门案例,共计 3 种方式,总有一款适合你!
Dubbo
Dubbo是一个分布式的高性能RPC框架,可为应用程序提供服务导入/导出功能。
架构
节点角色说明
调用关系说明
-
服务容器负责启动,加载,运行服务提供者。
-
服务提供者在启动时,向注册中心注册自己提供的服务。
-
服务消费者在启动时,向注册中心订阅自己所需的服务。
-
注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
-
服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
-
服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
这样直接看一遍还是没啥感觉,我们通过 3 种方式的入门案例,加深一下大家的理解。
根据官方的 example 例子
启动服务注册中心
启用内嵌的 zk 服务,或者使用 zookeeper 作为注册中心。
package com.github.houbb.dubbo.learn.zk;
import java.io.File;
import java.util.Properties;
import java.util.UUID;
import org.apache.zookeeper.server.ServerConfig;
import org.apache.zookeeper.server.ZooKeeperServerMain;
import org.apache.zookeeper.server.quorum.QuorumPeerConfig;
public class EmbeddedZooKeeper {
public static void main(String[] args) throws Exception {
int port = 2181;
if (args.length == 1) {
port = Integer.parseInt(args[0]);
}
Properties properties = new Properties();
File file = new File(System.getProperty("java.io.tmpdir")
+ File.separator + UUID.randomUUID());
file.deleteOnExit();
properties.setProperty("dataDir", file.getAbsolutePath());
properties.setProperty("clientPort", String.valueOf(port));
QuorumPeerConfig quorumPeerConfig = new QuorumPeerConfig();
quorumPeerConfig.parseProperties(properties);
ZooKeeperServerMain zkServer = new ZooKeeperServerMain();
ServerConfig configuration = new ServerConfig();
configuration.readFrom(quorumPeerConfig);
try {
zkServer.runFromConfig(configuration);
System.out.println("----------------- EmbeddedZooKeeper started on port 2181");
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
}
maven 依赖
上面的 maven 依赖如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.example</groupId>
<artifactId>dubbo-learn</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>dubbo-learn-zk</artifactId>
<properties>
<zookeeper.version>3.8.0</zookeeper.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>parent</artifactId>
<version>${zookeeper.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>${zookeeper.version}</version>
<exclusions>
<exclusion>
<artifactId>netty-handler</artifactId>
<groupId>io.netty</groupId>
</exclusion>
<exclusion>
<artifactId>netty-transport-native-epoll</artifactId>
<groupId>io.netty</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-client</artifactId>
</dependency>
<dependency>
<groupId>jline</groupId>
<artifactId>jline</artifactId>
</dependency>
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
</dependency>
<dependency>
<groupId>org.xerial.snappy</groupId>
<artifactId>snappy-java</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<mainClass>org.apache.dubbo.samples.EmbeddedZooKeeper</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
基于 api 实现
个人理解最简单的 dubbo 入门案例应该是基于 api 的定义实现,因为 dubbo 是完全可以独立于 spring 存在的。
虽然 dubbo 可以和 spring 进行很好的整合,但是最基本的 api 定义显然更容易理解。
pom.xml 定义
引入最基本的依赖
<properties>
<source.level>1.8</source.level>
<target.level>1.8</target.level>
<dubbo.version>2.7.7</dubbo.version>
<junit.version>4.12</junit.version>
<maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${source.level}</source>
<target>${target.level}</target>
</configuration>
</plugin>
</plugins>
</build>
接口定义
接口作为客户端和服务端之间的约定,如下:
public interface DemoService {
String say();
}
越抽象越简单,意味着越稳定。
一般公司中,服务端系统都会将接口打包上传到公司的私服 neuxs 仓库,便于客户端下载使用。
服务端
服务端针对上面的接口,实现如下:
public class DemoServiceImpl implements DemoService {
@Override
public String say() {
return "hello";
}
}
服务端启动该代码:
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import java.util.concurrent.CountDownLatch;
public class Server {
private static String zookeeperHost = System.getProperty("zookeeper.address", "127.0.0.1");
public static void main(String[] args) throws Exception {
ServiceConfig<DemoService> service = new ServiceConfig<>();
service.setApplication(new ApplicationConfig("first-dubbo-provider"));
service.setRegistry(new RegistryConfig("zookeeper://" + zookeeperHost + ":2181"));
service.setInterface(DemoService.class);
service.setRef(new DemoServiceImpl());
service.export();
System.out.println("dubbo service started");
new CountDownLatch(1).await();
}
}
这里我们依赖了 zookeeper 作为注册中心,你需要首先启动 zookeeper。
客户端
客户端和服务端的唯一依赖就是接口,这样以后服务端变更客户端基本可以不关心。
这位分布式系统中的协作开发,提供了极大的便利性。
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
/**
* @author 老马啸西风
* @since 1.0.0
*/
public class Client {
private static String zookeeperHost = System.getProperty("zookeeper.address", "127.0.0.1");
public static void main(String[] args) {
ReferenceConfig<DemoService> reference = new ReferenceConfig<>();
reference.setApplication(new ApplicationConfig("first-dubbo-consumer"));
reference.setRegistry(new RegistryConfig("zookeeper://" + zookeeperHost + ":2181"));
reference.setInterface(DemoService.class);
DemoService service = reference.get();
String message = service.say();
System.out.println(message);
}
}
日志输出如下:
hello
虽说用起来非常简单,但是底层的原理还是相对比价复杂的。我们后续会展开 rpc 手写实现系列,感兴趣的可以关注一波。
spring xml 配置
说明
spring xml 配置曾经风靡一时,我们这里作为经典版本给大家演示一下。
毕竟 dubbo 和 spring 的整合,使用起来才是更加方便。
宝剑配英雄,更能章显威力。
maven 依赖
这次需要和 spring 整合,所以新增了 spring 的相关依赖。
<properties>
<maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>
<source.level>1.8</source.level>
<target.level>1.8</target.level>
<dubbo.version>2.7.7</dubbo.version>
<spring.version>4.3.16.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${source.level}</source>
<target>${target.level}</target>
</configuration>
</plugin>
</plugins>
</build>
接口定义和实现
和上面一样,此处不再赘述。
内嵌 zk
这里官方 demo 引入了一个内嵌的 zk 类 EmbeddedZooKeeper
,这样基本的学习演示,就可以不用下载 apache zookeeper 了。
服务端
服务端作为服务的提供者,声明如下:
public class BasicProvider {
public static void main(String[] args) throws Exception {
new EmbeddedZooKeeper(2181, false).start();
// wait for embedded zookeeper start completely.
Thread.sleep(1000);
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-demo-provider.xml");
context.start();
System.out.println("dubbo service started");
new CountDownLatch(1).await();
}
}
其中 dubbo-demo-provider.xml
是 xml 配置,如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder/>
<dubbo:application name="demo-provider"/>
<dubbo:registry address="zookeeper://${zookeeper.address:127.0.0.1}:2181"/>
<bean id="demoService" class="com.github.houbb.dubbo.learn.basic.DemoServiceImpl"/>
<dubbo:service interface="com.github.houbb.dubbo.learn.basic.DemoService" ref="demoService"/>
</beans>
这里就是暴露了对应的接口服务,并且指定了 zk 的注册地址。
客户端
实现如下:
package com.github.houbb.dubbo.learn.basic;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class BasicConsumer {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-demo-consumer.xml");
context.start();
DemoService demoService = (DemoService) context.getBean("demoService");
String hello = demoService.say();
System.out.println(hello);
}
}
其中 dubbo-demo-consumer.xml
的实现如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder/>
<dubbo:application name="demo-consumer"/>
<dubbo:registry address="zookeeper://${zookeeper.address:127.0.0.1}:2181"/>
<dubbo:reference id="demoService" check="true" interface="com.github.houbb.dubbo.learn.basic.DemoService"/>
</beans>
这里指定了 zk 的地址,并且指定了 DemoService 对应的 dubbo 实现依赖。
测试
首先启动服务端,然后启动客户端。
启动客户端时报错如下:
[DUBBO] qos-server can not bind localhost:22222, dubbo version: 2.6.4, current host: 169.254.68.252
java.net.BindException: Address already in use: bind
[DUBBO] Fail to start qos server: , dubbo version: 2.6.4, current host: 169.254.68.252
java.net.BindException: Address already in use: bind
- 问题原因
Qos=Quality of Service,qos是Dubbo的在线运维命令,可以对服务进行动态的配置、控制及查询。
consumer启动时qos-server也是使用的默认的22222端口,但是这时候端口已经被provider给占用了,所以才会报错的。
- 解决方案
我们将 dubbo-demo-consumer.xml
application 配置进行调整,指定一个不同的端口即可。
<!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
<dubbo:application name="demo-consumer">
<dubbo:parameter key="qos.enable" value="true" />
<dubbo:parameter key="qos.accept.foreign.ip" value="false" />
<dubbo:parameter key="qos.port" value="33333" />
</dubbo:application>
重新启动测试通过。
spring @Bean 方式
当然,如果你不喜欢 xml,也可使用配置扥方式。
package com.github.houbb.dubbo.learn.basic.annotation;
import com.github.houbb.dubbo.learn.basic.DemoService;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class DubboConfig {
@Bean
public ApplicationConfig applicationConfig() {
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName("consumer-of-helloworld-app");
return applicationConfig;
}
@Bean
public RegistryConfig registryConfig() {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setAddress("zookeeper://127.0.0.1:2181");
return registryConfig;
}
@Bean
public ReferenceConfig<DemoService> demoServiceConfig() {
ReferenceConfig<DemoService> referenceConfig = new ReferenceConfig<>();
referenceConfig.setApplication(applicationConfig());
referenceConfig.setRegistry(registryConfig());
referenceConfig.setInterface(DemoService.class);
referenceConfig.setCheck(true);
referenceConfig.setCluster("");
return referenceConfig;
}
@Bean
public DemoService demoService() {
return demoServiceConfig().get();
}
}
有些配置可以合并简化。
启动类:
import com.github.houbb.dubbo.learn.basic.DemoService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class ConsumerApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DubboConfig.class);
context.start();
DemoService demoService = context.getBean(DemoService.class);
String hello = demoService.say();
System.out.println(hello);
}
}
这样也是可以的。
注解版本
说明
个人最喜欢的还是注解版本,实现起来更加优雅。
定义
接口定义和内嵌的 zk 和上面一样,不再赘述。
服务端
代码
注意,这里使用 @DubboService
修饰实现类。
package com.github.houbb.dubbo.learn.annotation.provider;
import com.github.houbb.dubbo.learn.annotation.api.DemoService;
import org.apache.dubbo.config.annotation.DubboService;
/**
* @author 老马啸西风
* @since 1.0.0
*/
@DubboService
public class DemoServiceImpl implements DemoService {
@Override
public String say() {
return "hello";
}
}
服务端配置类:
package com.github.houbb.dubbo.learn.annotation.provider;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
/**
* @author binbin.hou
* @since 1.0.0
*/
@Configuration
@EnableDubbo(scanBasePackages = "com.github.houbb.dubbo.learn.annotation.provider")
@PropertySource("classpath:dubbo-provider.properties")
public class ProviderConfiguration {
}
这里通过 @EnableDubbo
执行扫包操作。
- dubbo-provider.properties 配置
内容如下:
dubbo.application.name=annotation-provider
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
客户端
package com.github.houbb.dubbo.learn.annotation.consumer;
import com.github.houbb.dubbo.learn.annotation.api.DemoService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Component;
/**
* @author 老马啸西风
* @since 1.0.0
*/
@Component
public class AnnotationAction {
@DubboReference
private DemoService demoService;
public String say() {
return demoService.say();
}
}
这里通过 @DubboReference
注解注入依赖的服务。
客户端配置注解如下:
package com.github.houbb.dubbo.learn.annotation.consumer;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
/**
* @author 老马啸西风
* @since 1.0.0
*/
@Configuration
@EnableDubbo(scanBasePackages = "com.github.houbb.dubbo.learn.annotation.client")
@PropertySource("classpath:dubbo-consumer.properties")
@ComponentScan(value = {"com.github.houbb.dubbo.learn.annotation.consumer"})
public class ConsumerConfiguration {
}
其中 dubbo-consumer.properties
配置如下:
# dubbo-consumer.properties
dubbo.application.name=annotation-consumer
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.consumer.timeout=3000
测试
启动服务端
package com.github.houbb.dubbo.learn.annotation;
import com.github.houbb.dubbo.learn.annotation.provider.ProviderConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.concurrent.CountDownLatch;
public class AnnotationProviderBootstrap {
public static void main(String[] args) throws Exception {
new EmbeddedZooKeeper(2181, false).start();
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderConfiguration.class);
context.start();
System.out.println("dubbo service started.");
new CountDownLatch(1).await();
}
}
日志如下:
dubbo service started.
启动客户端
package com.github.houbb.dubbo.learn.annotation;
import com.github.houbb.dubbo.learn.annotation.consumer.AnnotationAction;
import com.github.houbb.dubbo.learn.annotation.consumer.ConsumerConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class AnnotationConsumerBootstrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerConfiguration.class);
context.start();
final AnnotationAction annotationAction = (AnnotationAction) context.getBean("annotationAction");
System.out.println("hello : " + annotationAction.say());
}
}
日志如下:
hello : hello
小结
本次的 dubbo 入门实战到这里就告一段落了。
dubbo 让远程服务调用起来像本地一样自然,和 spring 整合为我们提供了更大的编程便利性。
后续我们将和大家一起实现属于自己的 RPC 框架,感兴趣的小伙伴可以关注一波,实时获得最新消息。
希望本文对你有所帮助,如果喜欢,欢迎点赞收藏转发一波。
我是老马,期待与你的下次相遇。
Dubbo admin
You can download the code from https://github.com/alibaba/dubbo
, and package the dubbo-admin
houbinbindeMacBook-Pro:dubbo-admin houbinbin$ pwd
/Users/houbinbin/it/code/dubbo/dubbo-admin
houbinbindeMacBook-Pro:dubbo-admin houbinbin$ mvn package -Dmaven.skip.test=true
Download dubbo-admin-2.5.4-SNAPSHOT.war
into tomcat/webapps, and rename to ROOT.war
- config tomcat
edit the tomcat port(default is 8080) after these:
<!-- A "Connector" represents an endpoint by which requests are received
and responses are returned. Documentation at :
Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
Java AJP Connector: /docs/config/ajp.html
APR (HTTP/AJP) Connector: /docs/apr.html
Define a non-SSL/TLS HTTP/1.1 Connector on port 8080
-->
change the content to:
<Connector port="8888" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" URIEncoding="UTF-8"/>
- start tomcat
houbinbindeMacBook-Pro:bin houbinbin$ pwd
/Users/houbinbin/it/tools/tomcat/tomcat8/bin
houbinbindeMacBook-Pro:bin houbinbin$ sh startup.sh
Using CATALINA_BASE: /Users/houbinbin/it/tools/tomcat/tomcat8
Using CATALINA_HOME: /Users/houbinbin/it/tools/tomcat/tomcat8
Using CATALINA_TMPDIR: /Users/houbinbin/it/tools/tomcat/tomcat8/temp
Using JRE_HOME: /Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home
Using CLASSPATH: /Users/houbinbin/it/tools/tomcat/tomcat8/bin/bootstrap.jar:/Users/houbinbin/it/tools/tomcat/tomcat8/bin/tomcat-juli.jar
Tomcat started.
- visit dobbo admin in browser
URL: localhost:8888
root/root
Hello World
zookeeper
First of all, you need start your zookeeper.
houbinbindeMacBook-Pro:bin houbinbin$ ./zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /Users/houbinbin/it/tools/zookeeper/server1/zookeeper-3.4.9/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
houbinbindeMacBook-Pro:bin houbinbin$ pwd
/Users/houbinbin/it/tools/zookeeper/server1/zookeeper-3.4.9/bin
houbinbindeMacBook-Pro:bin houbinbin$ jps
32082
34610 QuorumPeerMain
34613 Jps
30221 Bootstrap
provider
File tree
|____main
| |____java
| | |____com
| | | |____ryo
| | | | |____model
| | | | | |____User.java
| | | | |____Provider.java
| | | | |____service
| | | | | |____impl
| | | | | | |____UserServiceImpl.java
| | | | | |____UserService.java
| |____resources
| | |____app-core.xml
| | |____applicationContext-beans.xml
| | |____applicationContext-dubbo-provider.xml
| | |____log4j2.xml
|____test
---- pom.xml
User.java
@Data
public class User implements Serializable {
private Long id;
private String username;
}
UserService.java
public interface UserService {
User getUser(Long id);
}
UserServiceImpl.java
@Service("userService")
public class UserServiceImpl implements UserService {
public User getUser(Long id) {
User user = new User();
user.setId(id);
user.setUsername("name"+id);
return user;
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ryo</groupId>
<artifactId>dubbo-provider</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<plugin.tomcat.version>2.2</plugin.tomcat.version>
<maven-surefire-plugin.version>2.18.1</maven-surefire-plugin.version>
<!--spring-->
<spring.version>4.2.6.RELEASE</spring.version>
<!--log4j-->
<log4j.version>2.6</log4j.version>
</properties>
<dependencies>
<!--spring-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.4</version>
</dependency>
<!--log4j-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>${plugin.tomcat.version}</version>
<configuration>
<port>8081</port>
<path>/</path>
<uriEncoding>${project.build.sourceEncoding}</uriEncoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<skipTests>true</skipTests>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
</plugins>
</build>
</project>
app-core.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="applicationContext-dubbo-customer.xml"/>
<import resource="applicationContext-beans.xml"/>
</beans>
applicationContext-beans.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--自动扫描 no need to include the <context:annotation-config>-->
<context:component-scan base-package="com.ryo"/>
</beans>
applicationContext-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-2.5.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="dubbo-provider"/>
<!-- 使用zookeeper注册中心暴露服务地址 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!-- 监听注册 -->
<dubbo:monitor protocol="registry"/>
<!-- 用dubbo协议在20880端口暴露服务 -1 == 20880 -->
<dubbo:protocol name="dubbo" port="-1" />
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="com.ryo.service.UserService" ref="userService"
version="0.0.0" retries="0" timeout="10000"/>
</beans>
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="DEBUG">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
- Main()
public class Provider {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"app-core.xml"});
context.start();
System.out.println("dubbo-provider start...");
System.in.read(); // 按任意键退出
}
}
start the main()
dubbo-provider start...
- visit the dubbo-admin
If you see this, you are success of half…
customer
Well, customer is most the same as provider. It’s File tree:
.
|____main
| |____java
| | |____com
| | | |____ryo
| | | | |____model
| | | | | |____User.java
| | | | |____service
| | | | | |____UserService.java
| |____resources
| | |____app-core.xml
| | |____applicationContext-beans.xml
| | |____applicationContext-dubbo-customer.xml
| | |____log4j2.xml
|____test
| |____java
| | |____com
| | | |____ryo
| | | | |____service
| | | | | |____UserServiceTest.java
applicationContext-dubbo-customer.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-2.5.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="dubbo-customer"/>
<!-- 使用zookeeper注册中心暴露服务地址 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!-- 监听注册 -->
<dubbo:monitor protocol="registry"/>
<!-- 用dubbo协议在20880端口暴露服务 -1 == 20880 -->
<dubbo:protocol name="dubbo" port="-1" />
<!-- 声明需要消费的服务接口 -->
<dubbo:reference interface="com.ryo.service.UserService" id="userService"/>
</beans>
UserServiceTest.java
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:/app-core.xml"})
@Log4j2
public class UserServiceTest {
@Resource
private UserService userService;
@Test
public void getUserTest() {
User user = userService.getUser(2L);
log.info("user info:{}", user);
}
}
result
23:31:47.259 [main] INFO com.ryo.service.UserServiceTest - user info:User{id=2, username='name2'}
Process finished with exit code 0
Multi-Maven & Nexus
As you can see, the User.java
and UserService.java
we have write it twice.
We can make it into jar
, and use it.
- Provider
- Provider interface jar
$ cd facade
$ mvn clean install
houbinbindeMacBook-Pro:target houbinbin$ pwd
/Users/houbinbin/IT/code/provider/facade/target
houbinbindeMacBook-Pro:target houbinbin$ ls
classes facade-1.0-SNAPSHOT.jar generated-sources maven-archiver maven-status
Into local
We can add the facade-1.0-SNAPSHOT.jar
into maven local repository
mvn install:install-file -Dfile=${jar-path} -DgroupId=com.ryo -DartifactId=${artifactId} -Dversion=${version} -Dpackaging=jar
then
mvn install:install-file -Dfile=/Users/houbinbin/IT/code/provider/facade/target/facade-1.0-SNAPSHOT.jar -DgroupId=com.ryo -DartifactId=facade -Dversion=1.0-SNAPSHOT -Dpackaging=jar
...
[INFO] --- maven-install-plugin:2.4:install-file (default-cli) @ standalone-pom ---
[INFO] Installing /Users/houbinbin/IT/code/provider/facade/target/facade-1.0-SNAPSHOT.jar to /Users/houbinbin/.m2/repository/com/ryo/facade/1.0-SNAPSHOT/facade-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.280 s
[INFO] Finished at: 2016-09-27T23:10:42+08:00
[INFO] Final Memory: 9M/309M
[INFO] ------------------------------------------------------------------------
Use the
facade-1.0-SNAPSHOT.jar
in customer
- pom.xml
<dependency>
<groupId>com.ryo</groupId>
<artifactId>facade</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
- customer tree
|____main
| |____java
| |____resources
| | |____app-core.xml
| | |____applicationContext-beans.xml
| | |____applicationContext-dubbo-customer.xml
| | |____log4j2.xml
|____test
| |____java
| | |____com
| | | |____ryo
| | | | |____facade
| | | | | |____UserFacadeTest.java
- UserFacadeTest.java
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:/app-core.xml"})
@Log4j2
public class UserFacadeTest {
@Autowired
private UserFacade userFacade;
@Test
public void getUserTest() {
UserResponse userResponse = userFacade.getUser(2L);
log.info("userResponse:{}", userResponse);
}
}
result:
23:21:11.040 [main] INFO com.ryo.facade.UserFacadeTest - userResponse:UserResponse(id=2, username=name2)
Process finished with exit code 0