Dubbo 3 于 Spring MVC 下使用注解配置

Posted sp42a

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dubbo 3 于 Spring MVC 下使用注解配置相关的知识,希望对你有一定的参考价值。

入门

Dubbo 是做 RPC 的,基于 Socket + 高性能协议,肯定比 HTTP 调用快多。我当期架构逐渐向分布式靠近,——其实也不是最赶什么微服务的潮流,只是觉得写好的代码,如果不独立,都是依附在某个某个项目中(即“单体”)的话,则很不稳定,有点变化的不好维护。还是独立部署运行比较稳定可用。另外一点好处是,微服务其实可以减少代码重复!你想想看,各个模块哦都独立运行了,变成一个个项目,就是把这模块高度抽象提炼,最大限度复用当期的服务或者组件。

项目是 Spring MVC 5,没有也没必要使用 Spring Boot,但使用注解下配置几乎是一样的。网上很多教程都是说 Dubbo v2.X 于 Spring MVC 下 xml 配置的,本文完全抛弃 xml,采用 Java 注解来配置。

直连方式

同时本文使用最简单的直连方式,无须配置什么 ZooKeeper 注册中心。直连方式是配置 url 指向提供者,将绕过注册中心,支持多个 url。


顺便科普一下,注册中心是什么:

就像发送http请求一样,消费端只要知道服务提供方的 ip 地址和端口号,就可以发起远程 RPC 调用,但如果服务提供方服务器迁移或者增加节点,又或者某个节点故障维修,那会导致消费端不可用,所以需要一个注册中心来统一管理。消费端从注册中心拿到正常提供服务的所有服务提供者,服务提供者向注册中心注册,并保持心跳,当某个提供者不可用时,将提供者剔除,并通知所有消费者,或者消费者定时询问注册中心。Monitor 暂时不讨论。

用法

还记得 Java RMI 吗?定义接口,序列化数据,远程请求,很神奇,就像在本地调用一样。当前 Dubbo 就是 RMI 加强版。跟 RMI 一样,客户端(消费端)只需要写接口,不用写实现,即可执行返回结果,实现的逻辑由服务端提供并返回。

定义一个简单的 GreetingService 接口,里面只有一个简单的方法 sayHello 向调用者问好。这个接口无论消费端还是服务端都需要的,你可以把它放在一个公共的项目/包。

public interface GreetingService 
	String sayHello(String name);

服务端:服务实现

实现 GreetingService 接口,并通过 @DubboService 来标注其为 Dubbo 的一个服务。

import org.apache.dubbo.config.annotation.DubboService;

@DubboService
public class AnnotatedGreetingService implements GreetingService 
	public String sayHello(String name) 
		System.out.println("::::::::::::" + name);
		return "hello, " + name;
	

注意 AnnotatedGreetingService 实现了接口 GreetingService

配置服务端

像普通 Bean 那样配置 Dubbo 的相关配置。注意 scanBasePackages 要配置到能扫描到上述的业务类 AnnotatedGreetingService

import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.ProviderConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableDubbo(scanBasePackages = "com.ajaxjs")
public class ProviderConfiguration 
	@Bean // #2
	public ApplicationConfig applicationConfig() 
		ApplicationConfig app = new ApplicationConfig();
		app.setName("dubbo-annotation-provider");

		return app;
	

	@Bean // #1
	public ProviderConfig providerConfig() 
		ProviderConfig provider = new ProviderConfig();
		provider.setTimeout(1000);

		return provider;
	

	@Bean // #3
	public RegistryConfig registryConfig() 
		RegistryConfig registry = new RegistryConfig();
		registry.setAddress("N/A"); // 直连

		return registry;
	

	@Bean // #4
	public ProtocolConfig protocolConfig() 
		ProtocolConfig protocol = new ProtocolConfig();
		protocol.setName("dubbo");
		protocol.setPort(20880);

		return protocol;
	

至此服务端的配置就 OK 了。运行 Spring 就会启动 Dubbo 服务,运行 Tomcat 也是会。或者你写个单测也行,不需要调用什么,Spring 注入 Dubbo bean 时候就启动了。单测例子如下。

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

@ContextConfiguration(locations =  "classpath*:applicationContext.xml" )
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class TestRpcServer 

	@Test
	public void test() throws Exception 
		System.out.println("Dubbo Server Running!");
//		Thread.sleep(100000);
		System.in.read(); // #4
	

成功运行日志显示如下。

配置消费端

与服务端的类似。

import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ConsumerConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableDubbo(scanBasePackages = "com.ajaxjs.cms")
public class DubboConsumerConfiguration 
	@Bean
	public ApplicationConfig applicationConfig() 
		ApplicationConfig app = new ApplicationConfig();
		app.setName("dubbo-annotation-consumer");

		return app;
	

	@Bean 
	public ConsumerConfig consumerConfig() 
		ConsumerConfig con = new ConsumerConfig();
		con.setTimeout(3000);

		return con;
	

	/**
	 * 注册中心配置
	 * 
	 * @return
	 */
	@Bean
	public RegistryConfig registryConfig() 
		RegistryConfig registry = new RegistryConfig();
		registry.setAddress("N/A"); // 直连

		return registry;
	

消费端服务定义

这个就是你要调用的定义,不需要写实现,就是简单的接口。

import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Component;

import com.ajaxjs.rpc.GreetingService;

@Component
public class GreetingServiceConsumer 
	@DubboReference(url = "dubbo://127.0.0.1:20880")
    private GreetingService greetingService;

    public String doSayHello(String name) 
        return greetingService.sayHello(name);
    

比较重要的是 @DubboReference 注解,这里指定 Dubbo 服务端地址。开始我就是没配置这里,搞了很久。

循例写单测:

import static org.junit.Assert.assertNotNull;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

import com.ajaxjs.cms.GreetingServiceConsumer;

@ContextConfiguration(locations =  "classpath*:applicationContext.xml" )
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class TestRpcConsumer 
	@Autowired
	private GreetingServiceConsumer greetingServiceConsumer;

	@Test
	public void test() 
		String hello = greetingServiceConsumer.doSayHello("World!"); // #4
		System.out.println("result: " + hello); // #5
		assertNotNull(hello);
	

使用技巧

  • 单测时候不想加载 Dubbo,加快速度,把注解 @EnableDubbo 注释掉就可以。

小结

Dubbo 很轻,Jar 包只有 3m 多,铁定用它了~

参见:

以上是关于Dubbo 3 于 Spring MVC 下使用注解配置的主要内容,如果未能解决你的问题,请参考以下文章

Dubbo 3 于 Spring MVC 下使用注解配置

spring+spring mvc+mybatis+mysql+dubbo整合开发任务流程后台管理系统

Spring MVC 3 有视图组件吗?

BAT:Java架构师必备的学习流程图(Spring/TCP/JVM/Spring MVC/JDBC/Spring Clound/Dubbo)

如何使用Dubbo服务和集成Spring

基于dubbo的SOA项目改造