之前开发过程中有使用过SpringCloud,并没有使用过Dubbo,一次有缘的机会使用到了Dubbo,这次的使用没有用注册中心,采用直连的方式使用的,感觉也还奇妙的,有点像SpringCloud 的Feign 调用方式,不同的是SpringCloud采用的是http封装访问的,而Dubbo是socket TCP进行接口指定引用实现方式,也称远程过程调用。
那么什么场景下使用呢,假如我们开发时会进行模块划分,有对外的接口,供其他调用jar包使用,也有对内的业务,有公共对内和对外都有的业务,那么,外部其他模块或其他服务器要使用我们的模块,他们该怎么用呢,还是原始方式写一堆http协议?请求网络调用吗?有点麻烦,现在就可以直接Dubbo的方式让它直接能获取服务端接口实现方法,
服务端
配置文件
server:
port: 8080
dubbo:
application:
name: Lottery
version: 1.0.0
registry:
# 不需要注册中心
address: N/A
protocol:
name: dubbo
port: 20880
# 扫描模块
scan:
base-packages: cn.itedus.lottery.rpc
pom文件
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>2.7.1</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.1</version>
</dependency>
首先在服务端定义接口,发送指令的接口定义
public interface ISendCommon {
String send(String recommad);
}
然后服务端实现上边的发送指令接口,注意这里的注解Service要使用Dubbo的
package cn.itedus.lottery.interfaces;
import cn.itedus.lottery.ISendCommon;
import org.apache.dubbo.config.annotation.Service;
@Service
public class SendCommon implements ISendCommon {
@Override
public String send(String recommad) {
// 指令操作模拟
return recommad + "成功!";
}
}
服务端启动类,@EnableDubbo打开Dubbo
@SpringBootApplication
@Configurable
@EnableDubbo
public class LotteryApplication {
public static void main(String[] args) {
SpringApplication.run(LotteryApplication.class, args);
}
}
如果返回使用了实体类必须手动加上序列化才可使用,如
implements Serializable
客户端
其实客户端是同样的配置方式
dubbo:
application:
name: Lottery
version: 1.0.0
registry:
address: N/A
protocol:
name: dubbo
port: 20880
scan:
base-packages: cn.itedus.lottery.rpc
pom文件要加入服务端包的依赖,否则使用不了方法
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>2.7.1</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.1</version>
</dependency>
<!-- 依赖自写的rpc层 -->
<dependency>
<groupId>cn.itedus.lottery</groupId>
<artifactId>lottery-rpc</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
单元测试调用服务器指定接口实现业务逻辑
package cn.itedus.lottery.test;
import cn.itedus.lottery.IActivityBooth;
import cn.itedus.lottery.ISendCommon;
import cn.itedus.lottery.rpc.req.ActivityReq;
import cn.itedus.lottery.rpc.res.ActivityRes;
import com.alibaba.fastjson.JSON;
import org.apache.dubbo.config.annotation.Reference;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
/**
* @Author df
* @Date 2022/5/18 10:07
* @Version 1.0
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApiTest {
// @Reference让定义的接口引用去指向一个具体的接口实现
// 基于接口的远程调用
@Reference(interfaceClass = ISendCommon.class, url = "dubbo://127.0.0.1:20880")
private ISendCommon iSendCommon;
@Test
public void test_rpc() {
String result = iSendCommon.send("关闭");
System.out.println(result);
}
}
启动后台服务端项目,启动以后Dubbo就启动了,然后客户端单元测试访问,访问结果如下,
没有报错,成功访问到了也没有报错
Dubbo的实现方式是客户端将要请求的接口什么的都以参数的形式序列化好进行socket传输给服务端,服务端接收完毕后反序列化,然后找到接口的实现类并调用,成功后返回结果,将结果进行序列化,客户端收到后将结果反序列化后使用,在返回后你可以看下对象是proxy,其实是代理对象,创建代理对象的好处就是可以在原有对象上增强或减少功能,如序列化反序列化,包装连接请求等等。