自定义spring-boot-starter-dubbox

司空叶五
2023-12-01

项目背景

  1. 公司越来越多的项目采用spring-boot+dubbox的soa服务架构,由于dubbox本身没有spring-boot的starter,故写出一个spring-boot-starter-dubbox提供给各方项目使用。
  2. 自定义的spring-boot的dubbox starter,为spring-boot相关的项目使用dubbox提供简易的方式并集成spring-boot的auto configuration。

代码

DubboAutoConfiguration

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.utils.ReferenceConfigCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* JThink@JThink
*
* @author JThink
* @version 0.0.1
* @desc dubbo auto configuration
* @date 2016-12-15 15:08:57
*/
@Configuration
@EnableConfigurationProperties(DubboProperties.class)
@ConditionalOnClass(DubboService.class)
public class DubboAutoConfiguration {

  @Autowired
  private DubboProperties dubboProperties;

  @Bean
  public ReferenceConfigCache referenceConfigCache() {
  return ReferenceConfigCache.getCache();
  }

  @Bean
  public ApplicationConfig applicationConfig() {
  return new ApplicationConfig(this.dubboProperties.getName());
  }

  @Bean
  public RegistryConfig registryConfig() {
  RegistryConfig registryConfig = new RegistryConfig(this.dubboProperties.getAddress());
  registryConfig.setCheck(this.dubboProperties.isCheck());
  registryConfig.setRegister(this.dubboProperties.isRegister());
  registryConfig.setProtocol(this.dubboProperties.getProtocol());

  return registryConfig;
  }

  @Bean
  public ProtocolConfig protocolConfig() {
  if (null == this.dubboProperties.getProtocolName() || null == this.dubboProperties.getPayload()) {
  return null;
  }
  ProtocolConfig protocolConfig = new ProtocolConfig();
  protocolConfig.setPort(-1);
  protocolConfig.setPayload(this.dubboProperties.getPayload());
  return protocolConfig;
  }

  @Bean
  public DubboService dubboService(ApplicationConfig applicationConfig, RegistryConfig registryConfig, ProtocolConfig protocolConfig, ReferenceConfigCache referenceConfigCache) {
  if (null == protocolConfig) {
  return new DubboService(applicationConfig, registryConfig, this.dubboProperties, referenceConfigCache);
  }
  return new DubboService(applicationConfig, registryConfig, protocolConfig, this.dubboProperties, referenceConfigCache);
  }

}

DubboProperties

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
* JThink@JThink
*
* @author JThink
* @version 0.0.1
* @desc
* @date 2016-12-15 15:09:15
*/
@ConfigurationProperties(prefix = "spring.service.dubbo.registry")
public class DubboProperties {

  private String name;
  private String address;
  private boolean check;
  private boolean register;
  private String protocol;
  private Integer retries;
  private Integer timeOut;
  private String protocolName;
  private Integer payload;

  public String getName() {
  return name;
  }

  public void setName(String name) {
  this.name = name;
  }

  public String getAddress() {
  return address;
  }

  public void setAddress(String address) {
  this.address = address;
  }

  public boolean isCheck() {
  return check;
  }

  public void setCheck(boolean check) {
  this.check = check;
  }

  public boolean isRegister() {
  return register;
  }

  public void setRegister(boolean register) {
  this.register = register;
  }

  public String getProtocol() {
  return protocol;
  }

  public void setProtocol(String protocol) {
  this.protocol = protocol;
  }

  public Integer getRetries() {
  return retries;
  }

  public void setRetries(Integer retries) {
  this.retries = retries;
  }

  public Integer getTimeOut() {
  return timeOut;
  }

  public void setTimeOut(Integer timeOut) {
  this.timeOut = timeOut;
  }

  public String getProtocolName() {
  return protocolName;
  }

  public void setProtocolName(String protocolName) {
  this.protocolName = protocolName;
  }

  public Integer getPayload() {
  return payload;
  }

  public void setPayload(Integer payload) {
  this.payload = payload;
  }
}

DubboService

import com.alibaba.dubbo.config.*;
import com.alibaba.dubbo.config.utils.ReferenceConfigCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
* JThink@JThink
*
* @author JThink
* @version 0.0.1
* @desc 提供暴露和获取service的方法
* @date 2016-12-15 14:23:24
*/
public class DubboService {

  private static final Logger LOGGER = LoggerFactory.getLogger(DubboService.class);

  private ApplicationConfig applicationConfig;
  private RegistryConfig registryConfig;
  private ProtocolConfig protocolConfig;
  private DubboProperties dubboProperties;
  private ReferenceConfigCache referenceConfigCache;
  private static Map<Class<?>, ReferenceConfig<?>> referenceConfigMap = new ConcurrentHashMap<Class<?>, ReferenceConfig<?>>();

  public DubboService(ApplicationConfig applicationConfig, RegistryConfig registryConfig, ProtocolConfig protocolConfig, DubboProperties dubboProperties, ReferenceConfigCache referenceConfigCache) {
  this.applicationConfig = applicationConfig;
  this.registryConfig = registryConfig;
  this.protocolConfig = protocolConfig;
  this.dubboProperties = dubboProperties;
  this.referenceConfigCache = referenceConfigCache;
  }

  public DubboService(ApplicationConfig applicationConfig, RegistryConfig registryConfig, DubboProperties dubboProperties, ReferenceConfigCache referenceConfigCache) {
  this.applicationConfig = applicationConfig;
  this.registryConfig = registryConfig;
  this.dubboProperties = dubboProperties;
  this.referenceConfigCache = referenceConfigCache;
  }

  /**
  * 将服务暴露出去
  * @param service
  * @param serviceImpl
  * @param <T>
  */
  public <T> void export(Class<?> service, T serviceImpl) {
  ServiceConfig<T> serviceConfig = new ServiceConfig<T>();

  serviceConfig.setInterface(service);
  serviceConfig.setRef(serviceImpl);

  serviceConfig.setApplication(this.applicationConfig);
  serviceConfig.setRegistry(this.registryConfig);
  serviceConfig.setProtocol(this.protocolConfig);
  serviceConfig.setTimeout(this.dubboProperties.getTimeOut());
  serviceConfig.setRetries(this.dubboProperties.getRetries());

  serviceConfig.export();
  }

  /**
  * 获取dubbo暴露的service
  * @param clazz
  * @param <T>
  * @return
  */
  @SuppressWarnings("unchecked")
  public <T> T get(Class<T> clazz) {
  ReferenceConfig<?> referenceConfig = referenceConfigMap.get(clazz);

  if (null == referenceConfig) {
  synchronized (clazz) {
  referenceConfig = referenceConfigMap.get(clazz);
  if (null == referenceConfig) {
  referenceConfig = getReferenceConfig(clazz);
  referenceConfigMap.put(clazz, referenceConfig);
  }
  }
  }

  T t = null;
  try{
  t = (T) referenceConfigCache.get(referenceConfig);
  } catch (Exception e) {
  LOGGER.info("dubbo 获取远程服务异常", e);
  }
  return t;
  }

  private <T> ReferenceConfig<T> getReferenceConfig(Class<T> clazz) {
  ReferenceConfig<T> reference = new ReferenceConfig<T>();
  reference.setApplication(applicationConfig);
  reference.setRegistry(registryConfig);
  reference.setRetries(dubboProperties.getRetries());
  reference.setInterface(clazz);
  reference.setTimeout(dubboProperties.getTimeOut());
  return reference;
  }
}

spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.jthink.spring.boot.starter.dubbox.DubboAutoConfiguration

github地址

https://github.com/JThink/spring-boot-starter-dubbox

打包

修改相关的maven私服地址

gradle clean install uploadArchives

使用方式

依赖

compile "jthink:spring-boot-starter-dubbox:0.0.1"

集成

在spring-boot项目的application.properties文件中加入相关的配置项,并赋予正确的值
- spring.service.dubbo.registry.name=xxx
- spring.service.dubbo.registry.address=ip1:2181,ip2:2181,ip3:2181
- spring.service.dubbo.registry.check=true
- spring.service.dubbo.registry.register=true
- spring.service.dubbo.registry.protocol=zookeeper
- spring.service.dubbo.registry.retries=0
- spring.service.dubbo.registry.timeout=60000
- spring.service.dubbo.registry.protocolName=dubbo
- spring.service.dubbo.registry.payload=10485760

使用

生产者

  1. 将上述配置项赋予正确的值
  2. 接口定义
public interface ServiceE {

  public String invokeE();
}
  1. 服务实现
@Service
public class ServiceEImpl implements ServiceE {

  private static final Logger LOGGER = LoggerFactory.getLogger(ServiceEImpl.class);

  @Override
  public String invokeE() {
  LOGGER.info("调用服务E");
  return "E";
  }
}
  1. 暴露服务
@Configuration
public class DubboConfiguration {

  @Autowired
  private DubboService dubboService;
  @Autowired
  private ServiceE serviceEImpl;

  @PostConstruct
  public void exportDubboService() {
  this.dubboService.export(ServiceE.class, this.serviceEImpl);
  }
}

消费者

  1. 将上述配置项赋予正确的值(最后两项配置项无需配置)
  2. 服务引用
@Configuration
public class DubboConfiguration {

  @Autowired
  private DubboService dubboService;

  @Bean
  public ServiceE serviceE() {
  return this.dubboService.get(ServiceE.class);
  }
}
  1. 服务调用
@Service
public class ServiceCImpl implements ServiceC {

  private static final Logger LOGGER = LoggerFactory.getLogger(ServiceCImpl.class);

  @Autowired
  private ServiceE serviceE;

  @Override
  public String invokeC() {
  LOGGER.info("调用服务E");
  return this.serviceE.invokeE();
  }
}
 类似资料: