Spring 整合 Dubbo

PPG007 ... 2021-12-27 About 4 min

# Spring 整合 Dubbo

实际开发中往往存在很多接口,Dubbo 通过动态代理为接口生成代理对象,并在调用时利用 Netty 发送请求获取结果,调用的是服务提供者的接口实现类,因此消费者与提供者是面向接口交互的,为了开发方便,避免同一个接口在生产者消费者中多次重复定义的情况,将共用的接口、实体类全部放在一个工程中,并通过 Maven 管理在生产者消费者中引用。

# 定义接口模块

导入依赖

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.18</version>
</dependency>
1
2
3
4
5

定义一个实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class User implements Serializable {

    static final long serialVersionUID = 114514L;

    private Integer id;

    private String username;

    private String password;

    private Date birthday;

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

定义两个接口,一个由生产者实现,一个由消费者实现

public interface IUserService {

    /**
     * 获取用户年龄
     * @param user user 对象
     * @return 年龄
     */
    Integer getAge(User user);
}
1
2
3
4
5
6
7
8
9
public interface IUserServiceConsumer {

    /**
     * 消费者调用提供者方法输出结果
     */
    void demo();
}
1
2
3
4
5
6
7

# 定义服务提供者

# 导入依赖,引入 API 接口模块及 Dubbo

依赖问题:

当前 Maven 仓库中包含 com.alibaba.dubbo 以及 org.apache.dubbo

  • 当引用阿里巴巴的 Dubbo 依赖时,需要再引入 Netty,且如果要使用 ZooKeeper 还要引入 ZooKeeper 依赖,这样引入 curator-framework 一个依赖即可:
<dependency>
    <artifactId>UserService-API</artifactId>
    <groupId>org.example</groupId>
    <version>1.0-SNAPSHOT</version>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>dubbo</artifactId>
    <version>2.6.10</version>
</dependency>

<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-framework</artifactId>
    <version>5.1.0</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  • 当引用 Apache 的 Dubbo 时,不需要再引入 Netty 但要引入 ZooKeeper,Apache为我们提供了一个集成依赖:dubbo-dependencies-zookeeper
<dependency>
    <artifactId>UserService-API</artifactId>
    <groupId>org.example</groupId>
    <version>1.0-SNAPSHOT</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo -->
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo</artifactId>
    <version>2.7.13</version>
</dependency>
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-dependencies-zookeeper</artifactId>
    <version>2.7.13</version>
    <type>pom</type>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  • 如果使用了阿里巴巴 Dubbo 同时使用了 Apache 的集成依赖,要再引入 Netty:
<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>4.1.55.Final</version>
</dependency>
1
2
3
4
5
  • 如果使用了 Apache 的 Dubbo 同时使用了 curator-framework,要再引入 curator-recipes。
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>5.2.0</version>
</dependency>
1
2
3
4
5

由于 curator-recipes 中包含了 curator-framework,所以可以不引入 curator-framework。

Dubbo 中包含了 Spring 所以不需要显式引入 Spring。

实现接口

public class UserServiceImpl implements IUserService {

    @Override
    public Integer getAge(User user) {
        Calendar birthday = Calendar.getInstance();
        birthday.setTime(user.getBirthday());
        Calendar now= Calendar.getInstance();
        return now.get(Calendar.YEAR) - birthday.get(Calendar.YEAR);
    }

}
1
2
3
4
5
6
7
8
9
10
11

# 使用 xml 配置 Spring 并启动

<?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"
       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">
    <dubbo:application name="user-service-provider"/>
    <dubbo:registry address="127.0.0.1:2181" protocol="zookeeper"/>
    <dubbo:protocol name="dubbo" port="8848"/>
    <bean id="userService" class="service.impl.UserServiceImpl">

    </bean>
    <dubbo:monitor protocol="registry"/>
    <dubbo:service interface="service.IUserService" ref="userService"/>
</beans>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Main {
    public static void main(String[] args) throws IOException {
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("beans.xml");
        classPathXmlApplicationContext.start();
        System.in.read();
    }
}
1
2
3
4
5
6
7

# 注解配置(2.6.3 版本以上)

定义properties文件,内容就是xml的内容

dubbo.application.name=user-service-provider
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
1
2
3
4

启动类

public class Main {
    public static void main(String[] args) throws IOException {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(ProviderConfiguration.class);
        annotationConfigApplicationContext.start();
        System.in.read();
    }
}

1
2
3
4
5
6
7
8

引用阿里巴巴dubbo时:

配置类

@Configuration//com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo
@EnableDubbo(scanBasePackages = "service.impl")
@PropertySource("classpath:dubbo-provider.properties")
public class ProviderConfiguration {


}
1
2
3
4
5
6
7

接口实现类

@Service//com.alibaba.dubbo.config.annotation.Service
public class UserServiceImpl implements IUserService {

    @Override
    public Integer getAge(User user) {
        Calendar birthday = Calendar.getInstance();
        birthday.setTime(user.getBirthday());
        Calendar now= Calendar.getInstance();
        return now.get(Calendar.YEAR) - birthday.get(Calendar.YEAR);
    }

}
1
2
3
4
5
6
7
8
9
10
11
12

引入Apache dubbo时:

配置类

@Configuration
//引入的是org.apache.dubbo.config.spring.context.annotation.EnableDubbo
@EnableDubbo(scanBasePackages = "service.impl")
@PropertySource("classpath:dubbo-provider.properties")
public class ProviderConfiguration {


}
1
2
3
4
5
6
7
8

接口实现类

使用DubboService注解

@DubboService
public class UserServiceImpl implements IUserService {

    @Override
    public Integer getAge(User user) {
        Calendar birthday = Calendar.getInstance();
        birthday.setTime(user.getBirthday());
        Calendar now= Calendar.getInstance();
        return now.get(Calendar.YEAR) - birthday.get(Calendar.YEAR);
    }

}
1
2
3
4
5
6
7
8
9
10
11
12

# 定义消费者

# 导入依赖

依赖关系与生产者相同

# 使用 xml 配置 Spring 并调用

<?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://dubbo.apache.org/schema/dubbo"
       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
       https://www.springframework.org/schema/context/spring-context.xsd
       http://dubbo.apache.org/schema/dubbo
       http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <dubbo:application name="user-service-consumer"/>
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
    <dubbo:reference interface="service.IUserService" id="userService"/>
    <!--直连-->
    <dubbo:monitor address="localhost:8888"/>

<!--    <dubbo:monitor protocol="registry"/>-->
    <context:component-scan base-package="service"/>
    <context:annotation-config/>

</beans>
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

接口实现类

@Service//spring
public class UserServiceConsumerImpl implements IUserServiceConsumer{


    private IUserService userService;

    @Autowired//会报错但是没问题
    public void setUserService(IUserService userService) {
        this.userService = userService;
    }

    @Override
    public void demo() {
        User user = new User();
        Calendar instance = Calendar.getInstance();
        instance.set(Calendar.YEAR,2000);
        Date bir = instance.getTime();
        user.setBirthday(bir);
        System.out.println(userService.getAge(user));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

启动类

public class Main {
    public static void main(String[] args) throws IOException {
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("beans.xml");
        classPathXmlApplicationContext.start();
        IUserServiceConsumer bean = classPathXmlApplicationContext.getBean(IUserServiceConsumer.class);
        bean.demo();
        System.in.read();
    }
}
1
2
3
4
5
6
7
8
9

# 使用注解配置

启动类:

public class Main {
    public static void main(String[] args) throws IOException {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(ConsumerConfiguration.class);
        IUserServiceConsumer serviceConsumer = annotationConfigApplicationContext.getBean(IUserServiceConsumer.class);
        serviceConsumer.demo();

        System.in.read();
    }
}
1
2
3
4
5
6
7
8
9

properties文件

dubbo.application.name=user-service-consumer
dubbo.registry.address=zookeeper://127.0.0.1:2181
1
2

使用阿里巴巴dubbo

配置类

@Configuration
@PropertySource("classpath:dubbo-consumer.properties")
@EnableDubbo(scanBasePackages = "service")
@ComponentScan(basePackages = "service")
public class ConsumerConfiguration {
}
1
2
3
4
5
6

消费者接口实现类

@Service//spring
public class UserServiceConsumerImpl implements IUserServiceConsumer{


    private IUserService userService;

    @Reference//dubbo
    public void setUserService(IUserService userService) {
        this.userService = userService;
    }

    @Override
    public void demo() {
        User user = new User();
        Calendar instance = Calendar.getInstance();
        instance.set(Calendar.YEAR,2000);
        Date bir = instance.getTime();
        user.setBirthday(bir);
        System.out.println(userService.getAge(user));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

使用Apache dubbo

配置类

@Configuration
@PropertySource("classpath:dubbo-consumer.properties")
@EnableDubbo(scanBasePackages = "service")//org.apache.dubbo.config.spring.context.annotation.EnableDubbo
@ComponentScan(basePackages = "service")
public class ConsumerConfiguration {
}
1
2
3
4
5
6

消费者接口实现类

@Service
public class UserServiceConsumerImpl implements IUserServiceConsumer{


    private IUserService userService;

    @DubboReference
    public void setUserService(IUserService userService) {
        this.userService = userService;
    }

    @Override
    public void demo() {
        User user = new User();
        Calendar instance = Calendar.getInstance();
        instance.set(Calendar.YEAR,2000);
        Date bir = instance.getTime();
        user.setBirthday(bir);
        System.out.println(userService.getAge(user));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Last update: December 27, 2021 14:40
Contributors: PPG007