构建一个最基础的Dubbo程序,目的是为了快速入门,了解Dubbo的运行机制以及熟悉Dubbo项目工程结构。
准备
- 开发环境:JDK8、Eclipse(Idea)、SpringBoot
- 开发结构:遵照Dubbo官方建议,服务消费者 + API层 + 服务提供者
- 项目工程:dubbo-interface + dubbo-provider + dubbo-web
其中工程结构及说明如下:
工程名称 | 说明 |
---|---|
dubbo-interface | 程序接口层,主要定义: 1.模型对象(即实体类) 2.业务接口 |
dubbo-provider | 服务提供者: 需要引用接口层,并实现接口方法,配置为dubbo服务; 然后将服务对外暴露出去(通常将服务注册到注册中心),供服务消费者使用。 |
dubbo-web | 服务消费者: 需要引用接口层,配置注册中心,通过注册中心来使用接口的服务来实现业务逻辑。 |
创建接口层工程
接口层主要定义了对象模型、服务接口,所以可以使用Maven直接创建一个普通的Jar工程。这里使用的Idea来创建:
首先定义工程名称:
下一步:
确认无误后下一步:
最后点击完成即可。
工程创建好后,需要定义对象模型以及服务接口,这里以用户为例,工程结构如下:
创建一个User实体类:
package cn.zealon.app.user.entity;
import java.io.Serializable;
import java.util.Date;
public class User implements Serializable {
private static final long serialVersionUID=1L;
private String id;
private String userId;
private String userName;
private Date created;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
}
一个用户服务接口:
package cn.zealon.app.user.service;
import cn.zealon.app.user.entity.User;
public interface UserService {
/**
* 按userId查找一个用户
* @param userId
* @return
*/
public User getUserById(String userId);
/**
* 修改一个用户
* @param user
* @return
*/
public int updateUser(User user);
}
到这里,最基本的接口工程已经完成了。
创建服务提供者工程
- 服务提供者需要使用到接口层,所以需要将接口层的代码打包放在服务提供者项目工程中;
- 开发接口层代码所定义的接口的具体实现;
- 配置dubbo服务,发布到注册中心;
创建工程
这里使用SpringBoot来构建工程,新建一个Module: 输入好工程名称,点击下一步: 这里只选择了一些必要的依赖,比如Mysql、Mybatis等等,点击下一步: 最后确认无误后,点击完成即可。
引入Maven依赖
SpringBoot初始化里的依赖明显不够用,还需要手动的将dubbo、zookeeper等依赖引入,还有需要将接口层的依赖也加进去,如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!--dubbo-->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
<!--zookeeper client-->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!--阿里 Druid Spring Boot Starter依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!-- json -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.43</version>
</dependency>
<!-- JDBC驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--接口项目依赖-->
<dependency>
<groupId>cn.zealon</groupId>
<artifactId>dubbo-interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
安装注册中心
注册中心可以选择zookeeper(当然也可以选择Multicast),这样可以初步的对dubbo注册中心机制有个理解。那么zookeeper的安装和启动就不概述了。
进行配置
需要的依赖引入后,这时候我们可以进行配置了;打开applicable.yml(applicable.properties):
分别配置了数据源、dubbo注册中心、mybatis的扫描包。如下:
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://xx.xx.xx.xx:3306/biz_db?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: xxxx
#dubbo配置
dubbo:
application:
name: dubbo-provider
registry: zookeeper://xx.xx.xx.xx:2181
mybatis:
mapper-locations: classpath*:mappers/*.xml
实现接口
好了,准备的差不多了,开始实现接口服务,首先创建一个mybatis的dao层接口UserMapper:
package cn.zealon.app.user.dao;
import cn.zealon.app.user.entity.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface UserMapper {
@Insert("insert into org_user(id,userid,user_Name,created) values(#{id},#{userId},#{userName},#{created})")
public int insert(User user);
@Select("select id,userId,user_name userName,created from org_user where userId=#{userId} ")
public User getUserById(String userId);
}
然后创建接口实现UserServiceImpl:
package cn.zealon.app.user.server.impl;
import cn.zealon.app.user.entity.User;
import cn.zealon.app.user.service.UserService;
import com.alibaba.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import cn.zealon.app.user.dao.UserMapper;
import org.springframework.stereotype.Component;
@Service
@Component
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public User getUserById(String userId) {
return userMapper.getUserById(userId);
}
@Override
public int updateUser(User user) {
return userMapper.insert(user);
}
}
需要注意的是,@Service注解不在是Spring里面的了,而是com.alibaba.dubbo.config.annotation包下的注解,使用@Component来做为Spring组件装配Bean。
最后在SpringBoot启动入口中,加入dubbo相关的注解:
package cn.zealon;
import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import com.alibaba.dubbo.config.spring.context.annotation.EnableDubboConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableDubboConfig
@EnableDubbo
public class DubboProviderApplication {
public static void main(String[] args) {
SpringApplication.run(DubboProviderApplication.class, args);
}
}
好了,这时候最基本的服务提供者工程就创建完了。
创建服务消费者工程
这里说明一下,工程的创建基本同上,包括Maven依赖的引用等等,只是稍有不同(消费端主要是编写Controller层的代码,所以可能会依赖一些Thymeleaf等模板引擎,而不需要依赖Mybatis、Mysql等),这里就直接贴代码了。
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>cn.zealon</groupId>
<artifactId>dubbo-web</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>dubbo-web</name>
<description>dubbo-web for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--dubbo-->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
<!--zookeeper client-->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
<!-- json -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.43</version>
</dependency>
<!--接口项目依赖-->
<dependency>
<groupId>cn.zealon</groupId>
<artifactId>dubbo-interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.yml:
server:
port: 80
spring:
application:
name: dubbo-web
dubbo:
application:
name: dubbo-web
registry:
address: zookeeper://xx.xx.xx.xx:2181
重点是实现接口的调用,这里定义一个UserController:
package cn.zealon.app.user.controller;
import cn.zealon.app.user.entity.User;
import cn.zealon.app.user.service.UserService;
import com.alibaba.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
import java.util.UUID;
@RestController
@RequestMapping("user")
public class UserController {
@Reference
private UserService userService;
@RequestMapping("detail/{userId}")
public User getUserByUserId(@PathVariable String userId){
return userService.getUserById(userId);
}
@PostMapping("update")
public Object update(User user){
user.setId(UUID.randomUUID().toString().replace("-",""));
user.setCreated(new Date());
userService.updateUser(user);
return user;
}
}
其中@Reference注解来完成消费端的服务引用,由于我们注册中心在配置文件中配置好了,所以只要实现接口层的服务声明就可以实现服务自动发现,和使用了。
整体测试
首先启动服务提供者应用: 可以观察日志,看到UserService已经注册到zookeeper中了。
然后启动服务消费者应用: 观察日志可以看到,消费者已经成功的订阅了UserService服务,并且tomcat启动无异常,那么说明现在可以进行测试了。
测试资源地址:user/detail/{userId}
请求类型:Get
那么可以再浏览器中进行完成测试,请求如下:
已经成功的查询到数据结果,嗯到这里,最基本的dubbo应用就已经搭建好了。
作者: Zealon
崇尚简单,一切简单自然的事物都是美好的。