今天主要介绍一下Spring Boot如何和dubbo整合,因为当下springboot的开发是非常火的,所以和它组合的组件也就很多,首先看一下dubbo的介绍:
Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分业务的架构,使用这种方式可以使各个业务之间解耦合(或者最大限度地松耦合)。从服务模型的角度来看,Dubbo采用的是一种非常简单的模型,要么是提供方提供服务,要么是消费方消费服务,所以基于这一点可以抽象出服务提供方(Provider)和服务消费方(Consumer)两个角色。关于注册中心、协议支持、服务监控等内容,详见后面描述。spring-boot是近几年越来越来越流行的库,Spring Boot 可以大大提升使用 Spring 框架时的开发效率。spring-boot-starter-dubbo则是借助spring-boot高效,整合dubbo的实现,让dubbo的使用变得平民化。,如果想对dubbo做深入了解,可以去看我的dubbo系列文章:,好了直接上代码,首先看一下整体项目的结构:
看一下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">
<!--<parent>-->
<!--<artifactId>spring_boot</artifactId>-->
<!--<groupId>com.suning.springboot</groupId>-->
<!--<version>1.0-SNAPSHOT</version>-->
<!--</parent>-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring_boot_dubbo</artifactId>
<packaging>pom</packaging>
<modules>
<module>dubbo_provider</module>
<module>dubbo_consumer</module>
</modules>
<dependencies>
<!--个人开源-->
<dependency>
<groupId>com.gitee.reger</groupId>
<artifactId>spring-boot-starter-dubbo</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
注意spring boot 1.5版本只能匹配1.0.x系列,不能使用1.1.x系列,否则会报错
下面就通过模拟一个加法计算的RPC请求,首先看一下服务提供者:
定义服务接口和服务的实现:
定义服务接口:
package com.dubbo.service;
/**
* @Author 18011618
* @Date 10:54 2018/7/16
* @Function 定义计算加法的服务接口
*/
public interface IAddService {
Integer add(Integer a, Integer b);
}
定义服务的实现:
package com.dubbo.service;
import com.alibaba.dubbo.config.annotation.Service;
@Service
public class AddService implements IAddService {
public Integer add(Integer a,Integer b){
System.err.printf("方法add被调用 %s+%s", a, b);
System.err.println();
if(a==null||b==null){
return 0;
}
return a+b;
}
}
注意这里的@Service注解不是spring里面的,而是dubbo里面的,要看清楚了
看一下application.yaml的配置文件
spring:
dubbo:
application:
name: dubbo-add-provider
base-package: com.dubbo.service #dubbo服务发布者所在的包
registry:
address: 127.0.0.1 # zookeeper注册中心的地址
port: 2181 # zookeeper注册中心的端口
protocol:
name: dubbo
serialization: hessian2
provider:
retries: 0 # 服务调用重试次数
服务启动启动应用类:
package com.dubbo;
import java.util.concurrent.TimeUnit;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.annotation.Order;
@SpringBootApplication
@Order(value = 1)
public class DubboProviderApplication implements CommandLineRunner {
public static void main(String[] args) throws InterruptedException {
SpringApplication.run(DubboProviderApplication.class, args);
TimeUnit.MINUTES.sleep(3);
System.err.println("服务提供者------>>服务关闭");
}
@Override
public void run(String... args) throws Exception {
System.err.println("服务提供者------>>启动完毕");
}
}
代码很简单,但是这里实现了这个接口,它和dubbo本身没有任何关系,是基于springboot的,有啥作用呢,看看下面的场景分析:,
我们在开发过程中会有这样的场景:需要在容器启动的时候执行一些内容,比如:读取配置文件信息,数据库连接,删除临时文件,清除缓存信息,在Spring框架下是通过ApplicationListener监听器来实现的。在Spring Boot中给我们提供了两个接口来帮助我们实现这样的需求,就是CommandLineRunner和ApplicationRunner,他们的执行时机为容器启动完成的时候(容器初始化要完成的功能),这两个类都能提供类似功能,但是也是有区别的,主要就是方法里面的参数不一样,然后使用起来基本上都是也一样的,如果有多个实例的话,可以通过@Ordered来进行顺序的控制,顺序是根据value的值从小到大来执行的,使用类似于这样
生产者写完了,接下来看看对应的消费者:
这里要引用到服务提供者的服务接口有两种引用方式:
> 直接引入服务提供者的jar,这种相当来说比较重,服务提供者所有的接口都知道了
>自己定义一个包,重写一个服务接口,保证包名和接口名是一致的
比如笔者这里使用了第二种方式:
定义服务者接口:
package com.dubbo.service;
public interface IAddService {
Integer add(Integer a, Integer b);
}
定义服务消费者服务接口:
public interface IConsumerService {
Integer add(Integer a,Integer b);
}
定义服务消费者服务接口的实现:
package com.dubbo.service.consumer;
import com.dubbo.service.IAddService;
import com.reger.dubbo.annotation.Inject;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Service;
/**
* @Author 18011618
* @Description
* @Date 9:56 2018/7/16
* @Modify By
*/
@Service
public class ConsumerService implements IConsumerService,CommandLineRunner {
@Inject
private IAddService addService;
@Override
public Integer add(Integer a, Integer b) {
return addService.add(a,b);
}
@Override
public void run(String... strings) throws Exception {
int a=1;
int b =2;
System.err.printf("%s+%s=%s", a, b, addService.add(a,b));
System.err.println();
}
}
为了方便测试再写个controller:
package com.dubbo.consumer;
import com.dubbo.service.consumer.IConsumerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author 18011618
* @Description
* @Date 10:02 2018/7/16
* @Modify By
*/
@RestController
public class ConsumerController {
@Autowired
private IConsumerService consumerService;
@GetMapping("/add")
public String add(@RequestParam Integer a, @RequestParam Integer b){
return "execute add compute:"+String.valueOf(consumerService.add(a,b));
}
}
最后看一下对应的配置文件:applciation.yaml
spring:
dubbo:
application:
name: dubbo-add-consumer
base-package: com.dubbo.service # dubbo服务调用者所在的包
registry:
address: 127.0.0.1 # zookeeper注册中心的地址
port: 2181 # zookeeper注册中心的端口
consumer:
timeout: 1000
check: true # 服务启动时检查被调用服务是否可用
retries: 2
server:
port: 8088 # 服务调用重试次数
最后写一个服务消费者的启动应用类:
package com.dubbo;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DubboConsumerApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(DubboConsumerApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
System.err.println("服务调用者------>>启动完毕");
}
}
OK 到此为止代码就写完了,现在先启动,然后再启动,这个时候看消费者是否能正常启动,如果能就可以访问了,比如我这里是访问http://localhost:8088/add?a=3&b=5,然后出现的结果如下
这里消费者成功调用了远程的服务提供者,看一下控制台打印消息
这些打印消息都是因为实现了commandlinerunner接口,在容器启动的时候就完成了,OK到此就实现了dubbo和springboot的整合,
提醒:在注册的zk的过程中,一定要保持服务的提供者和在消费者模块下面的包路径是完全一致的,否则消费者就无法从zk中获取到服务实例(否则就会报no available provieder….),什么意思呢,比如就拿上面的例子来说: 中的服务接口是com.dubbo.service.IAddService,那么必须要保证在消费者的模块下面也是这个路径
还有一点,笔者的zk是本地单机版的,生产环境最好要集群模式的.,到此为止就实现了springboot和dubbo的整合
版权声明:为经博主同意不得转载,谢谢