JFinal与Dubbo集成(无Spring)

此文意在记录自己手撸 JFinalDubbo 在无 Spring 环境下集成时遇到的各种问题. 文笔不好, 可能思路比较跳跃, 大家见谅哈

JFinal

JFinal 是一个 web + orm 的一个开发框架, 其提供了很好的模板引擎与数据库的支持, 当然这不是本文的重点, 重点是将 Dubbo 在无 Spring 环境下集成进 JFinal

Dubbo

Dubbo 是阿里开源的 RPC 框架, 其成熟的生态环境以及阿里的技术支持, 使得其成为国内不可或缺的 RPC 框架. 它提供了很好的 Spring 支持, 但本文的重点是在无 Spring 环境下集成, 所以我们将不采用 Spring 的 配置支持, 转用 Dubbo API 的 调用形式, 也给一些非 Spring 运行环境下的技术, 提供比较通用的配置解决方案.

Dubbo API

Dubbo 官方提供的 Quick Start 文档中, 有提供我们最基础 Dubbo API 调用使用文档, 但此文最大的问题就是没有给出其必须的依赖, 所以在实际运行过程中, 会发现各种 ClassNotFoundException, 对此, 我表示让我们不使用 Spring 那一套的真的很苦逼哦.

好了, 你可能会说, Dubbo 官方 不是提供了Dubbo All 这个完整版的Dubbo的依赖么, 哈哈哈, 恭喜你, 喜提第一坑, Dubbo All 可是依赖 spring-framework的哦, 所以这个方案我们得 pass 了, 可以看看这个 issue 我们的场景和他差不多


Demo 开发

依赖说明

好了, 让我们进入正题, 说明下需要选择的lib, 可能有些描述不正确, 可以提出一起探讨.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# dubbo 公共基础库, 必选
dubbo-common-2.6.3.jar
# dubbo 配置 API , 必选
dubbo-config-api-2.6.3.jar
# dubbo 注册中心 API , 必选
dubbo-registry-api-2.6.3.jar
# dubbo zookeeper 注册中心, 如果注册中心是zookeeper, 必选
dubbo-registry-zookeeper-2.6.3.jar
# dubbo 默认 注册中心, 如果注册中心是dubbo, 必选
dubbo-registry-default-2.6.3.jar
# dubbo 远程调用 API , 必选
dubbo-remoting-api-2.6.3.jar
# dubbo 远程调用 netty, 可选
dubbo-remoting-netty-2.6.3.jar
# dubbo 远程调用 zookeeper, 如果注册中心是zookeeper, 必选
dubbo-remoting-zookeeper-2.6.3.jar
# dubbo RPC协议 API , 必选
dubbo-rpc-api-2.6.3.jar
# dubbo 路由基础库, 必选
dubbo-cluster-2.6.3.jar
# dubbo RPC Dubbo 协议, 可选
dubbo-rpc-dubbo-2.6.3.jar
# dubbo 数据序列化 API, 必选
dubbo-serialization-api-2.6.3.jar
# dubbo 数据序列化 hessian2 实现, 必选
dubbo-serialization-hessian2-2.6.3.jar
# dubbo hessian2 依赖, 必选
hessian-lite-3.2.4.jar
# dubbo netty 依赖, 必选
netty-3.2.10.Final.jar
# dubbo zookeeper 依赖, 如果注册中心是zookeeper, 必选
zookeeper-3.4.13.jar
# dubbo curator 依赖, 必选
curator-client-4.0.1.jar
# dubbo curator 依赖, 必选
curator-framework-4.0.1.jar
# dubbo javassist 依赖, 必选
javassist-3.23.1-GA.jar

服务 API

1
2
3
4
5
public interface DemoService {

String sayHello(String name);

}

可查看源码

服务提供者

1
2
3
4
5
6
7
8
9
10
11
12
13
@Service(
version = "${demo.service.version}",
application = "${dubbo.application.id}",
protocol = "${dubbo.protocol.id}",
registry = "${dubbo.registry.id}"
)
public class DefaultDemoService implements DemoService {

public String sayHello(String name) {
return "Hello, " + name + " (from Spring Boot)";
}

}

可查看源码

服务调用者(JFinal中实现)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

private DemoService demoService;

public void dubbo()
{
if (demoService == null)
{
initByDefaultRegistry();
}
renderJson(demoService.sayHello("Sky"));
}

private synchronized void initByDefaultRegistry()
{
// 当前应用配置
ApplicationConfig application = new ApplicationConfig();
application.setName("oss");

// 连接注册中心配置
RegistryConfig registry = new RegistryConfig();
// registry.setAddress("localhost:12345");
registry.setProtocol("dubbo");
registry.setId("dubbo");

// 注意:ReferenceConfig为重对象,内部封装了与注册中心的连接,以及与服务提供方的连接

// 引用远程服务
ReferenceConfig<DemoService> reference = new ReferenceConfig<DemoService>(); // 此实例很重,封装了与注册中心的连接以及与提供者的连接,请自行缓存,否则可能造成内存和连接泄漏
reference.setApplication(application);
reference.setProtocol("dubbo");
reference.setInjvm(false);
reference.setRegistry(registry); // 多个注册中心可以用setRegistries()
reference.setUrl("localhost:12345");
reference.setInterface(DemoService.class);
reference.setVersion("1.0.0");

// 和本地bean一样使用xxxService
demoService = reference.get(); // 注意:此代理对象内部封装了所有通讯细节,对象较重,请缓存复用
}

源码仓库

Demo 启动后, 可以看到消费端利用 Dubbo API的调用方式实现了与服务提供者连通, 并成功使用服务, 实现了自己的目的, 在无 spring 的JFinal环境下, 使用 dubbo 服务.