Dubbo API 配置方式

前言

我的項(xiàng)目 AngBoot 使用的是 SpringSecurity 做權(quán)限管理與認(rèn)證, 但是, 項(xiàng)目初衷是作為開發(fā)模板結(jié)構(gòu), 所以, 為了應(yīng)對(duì)微服務(wù)以及更靈活的使用場(chǎng)景, 我引入了 Dubbo 以提供遠(yuǎn)程認(rèn)證服務(wù). 這樣, 可以通過修改配置很容易的從我內(nèi)嵌的認(rèn)證系統(tǒng)遷移到任何一個(gè)開發(fā)者自己的認(rèn)證系統(tǒng).

今天在自己項(xiàng)目中引入 Dubbo 時(shí)遇到一個(gè)問題, 項(xiàng)目本身是 SpringBoot 項(xiàng)目, 如果需要 Dubbo 就可以使用 @EnableDubbo 以及注解配置的方式方便的引入 Dubbo 到 SpringBoot 環(huán)境, 但是, 我的需求是需要配置化,靈活, 動(dòng)態(tài)的引入 Dubbo rpc 遠(yuǎn)程服務(wù), 簡(jiǎn)單的說就是默認(rèn)使用內(nèi)嵌的模塊, 但是依然可以通過配置使用遠(yuǎn)程服務(wù), 所以直接為 SpringBoot 添加 @EnableDubbo 直接的方式使用 Dubbo 顯得并不是那么合適, 因?yàn)槟J(rèn)并沒有遠(yuǎn)程調(diào)用

參看 Dubbo 文檔可以發(fā)現(xiàn)Dubbo 的 API 配置方式, 但是官網(wǎng)寫的比較粗糙, 但是直覺猜測(cè)應(yīng)該是可以把 ApplicationConfig, RegistryConfig 等對(duì)象放入 IOC 中, 然后通過 ReferenceConfig 將遠(yuǎn)程對(duì)象拿到并加入 IOC 中, 這樣就不會(huì)對(duì)其他模塊和代碼產(chǎn)生影響. 所以寫個(gè) exmaple 進(jìn)行驗(yàn)證.

創(chuàng)建服務(wù)提供者 provider-ticket

服務(wù)提供者無所謂那種配置方式, 我們就用最快最簡(jiǎn)單的 SpringBoot + @EnableDubbo 注解進(jìn)行配置.

  • SpringBoot 入口類
@SpringBootApplication
@EnableDubbo
public class ProviderTicketApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProviderTicketApplication.class, args);
    }

}
  • 服務(wù)接口
package com.jack.ticket.service;

public interface TicketService {
    public String getTicket();
}

  • 服務(wù)實(shí)現(xiàn)
package com.jack.ticket.service;

import com.alibaba.dubbo.config.annotation.Service;
import org.springframework.stereotype.Component;

@Component // 將服務(wù)加入 IOC
@Service // 將服務(wù)發(fā)布出去
public class TicketServiceImpl implements TicketService {
    @Override
    public String getTicket() {
        return "厲害了, 我的國(guó)....";
    }
}
  • Dubbo 配置
dubbo.application.name=provider-ticket

# 注冊(cè)中心地址
dubbo.registry.address=zookeeper://127.0.0.1:2181

# 包掃描需要提供的服務(wù)
dubbo.scan.base-packages=com.jack.ticket.service
  • 開啟 Zookeeper, 啟動(dòng)服務(wù)提供者 ProviderTicketApplication
    file

API 配置創(chuàng)建服務(wù)消費(fèi)者 consumer-user-api

  • SpringBoot 入口類. 注意沒有 EnableDubbo 注解
@SpringBootApplication
public class ConsumerUserApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConsumerUserApplication.class, args);
    }

}
  • 遠(yuǎn)程服務(wù)接口
package com.jack.ticket.service;

public interface TicketService {

    String getTicket();
}
  • 創(chuàng)建一個(gè) Configuration 類去獲取遠(yuǎn)程服務(wù)
package com.jack.user.config;

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.jack.ticket.service.TicketService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DubboConfiguration {

   /**
    * 創(chuàng)建 ApplicationConfig 對(duì)象.
    * 將其加入 IOC 并不是必須的, 因?yàn)橹挥性讷@取遠(yuǎn)程對(duì)象時(shí)才需要該實(shí)例,
    * 因此, 當(dāng)遠(yuǎn)程服務(wù)較多需要多次獲取時(shí)將該實(shí)例加入 IOC 才顯得有必要,
    * 當(dāng)然, 你也可以將其作為成員屬性持有復(fù)用.
    */
   @Bean
   public ApplicationConfig applicationConfig() {
      ApplicationConfig application = new ApplicationConfig();
      application.setName("consumer-user");

      return application;
   }

   /**
    * 創(chuàng)建 RegistryConfig 以配置注冊(cè)中心信息.
    * @see DubboConfiguration#applicationConfig() 同樣的加入 IOC 不是必須的
    */
   @Bean
   public RegistryConfig registryConfig() {
      RegistryConfig registry = new RegistryConfig();
      registry.setAddress("zookeeper://127.0.0.1:2181");

      return registry;
   }

   /**
    * 獲取遠(yuǎn)程服務(wù)對(duì)象.
    * 實(shí)際上, 如果遠(yuǎn)程對(duì)象只調(diào)用一次, 也沒有必要加入 IOC, 在使用時(shí)獲取一次就好了,
    * 但是大部分場(chǎng)景都是需要多次重復(fù)調(diào)用的, 而且獲取遠(yuǎn)程服務(wù)對(duì)象的代價(jià)昂貴, 所以,
    * 將其加入 IOC 容器以復(fù)用很明顯是較好實(shí)踐, 獲取可以自行緩存.
    */
   @Bean
   public TicketService ticketService() {
      // 此實(shí)例很重,封裝了與注冊(cè)中心的連接以及與提供者的連接,請(qǐng)自行緩存,否則可能造成內(nèi)存和連接泄漏
      ReferenceConfig<TicketService> reference = new ReferenceConfig<>();
      reference.setApplication(applicationConfig());
      // 多個(gè)注冊(cè)中心可以用setRegistries()
      reference.setRegistry(registryConfig());
      reference.setInterface(TicketService.class);

      // 和本地bean一樣使用 TicketService
      // 注意:此代理對(duì)象內(nèi)部封裝了所有通訊細(xì)節(jié),對(duì)象較重,請(qǐng)緩存復(fù)用
      TicketService ticketService = reference.get();

      return ticketService;
   }
}
  • 創(chuàng)建 UserService 使用遠(yuǎn)程服務(wù)對(duì)象

由于遠(yuǎn)程服務(wù)對(duì)象已經(jīng)被獲取并加入到當(dāng)前 IOC 中, 所以就可以通過 @Autowired 進(jìn)行依賴注入.

package com.jack.user.service;

import com.jack.ticket.service.TicketService;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    public final TicketService ticketService;

    public UserService(TicketService ticketService) {
        this.ticketService = ticketService;
    }

    public void buyTicket() {
        String ticket = ticketService.getTicket();

        System.out.println("買到票了, ticket: " + ticket);
    }
}
  • 運(yùn)行測(cè)試
package com.jack.user.service;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTests {

    @Autowired
    private UserService userService;

    @Test
    public void testBuyTicket() {
        Assert.assertNotNull("init user service failed...", userService);
        userService.buyTicket();
    }

}
file

總結(jié)

至此, Dubbo 的 API 配置方式就介紹完了, 我們可以在 Spring/SpringBoot 環(huán)境中方便的使用和配合 Spring 的 Conditional 靈活的進(jìn)行擴(kuò)展式編程以是自己的項(xiàng)目/產(chǎn)品可以應(yīng)對(duì)更多使用場(chǎng)景.

更多請(qǐng)關(guān)注我的項(xiàng)目 AngBoot

日常求贊: 歡迎大家點(diǎn)贊, 評(píng)論, 關(guān)注, 轉(zhuǎn)發(fā). 要是能給點(diǎn)贊賞就更好了, 哈哈哈.... https://blog.csdn.net/DreamLi1314

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容