超详细springboot整合dubbo

记录一次springboot整合dubbo的过程,本文代码 github 地址
https://github.com/liaozq0426/springboot-dubbo.git

项目结构说明

项目结构如下图所示
图1.项目结构图
springboot-dubbo是一个maven的多模块项目,各个模块的作用如下

  1. springboot-dubbo-service 模块为dubbo服务接口项目,之所以将接口单独创建一个项目,是因为dubbo接口既需要被dubbo服务实现类实现,也需要被消费者引用,也就是说dubbo接口项目会被多个项目使用。
  2. springboot-dubbo-service-impl 模块为 dubbo 服务的实现,它所有的 service实现类都实现了springboot-dubbo-service 中的接口
  3. springboot-dubbo-customer 模块为消费者项目,在实际开发中,dubbo往往会采用分布式的方式部署,即服务提供者和消费者部署在不同的服务器,消费者还可能有多个,以实现负载均衡。

编写父项目

创建一个simple类型的maven项目,勾选下图红色框中的选项,点击next
图2.创建父项目
填写maven项目信息,如下图
图3.maven项目信息
其中要注意的的是,打包类型需要选择pom,因为父项目中不需要写任何逻辑代码。填写好后点击Finish按钮即可。
父项目只需要保留pom.xml文件,其余内容全部删除,pom.xml所需依赖如下

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.3.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<spring-boot-starter-parent.version>2.1.3.RELEASE</spring-boot-starter-parent.version>
		<mybatis-spring-boot-starter.version>1.3.2</mybatis-spring-boot-starter.version>
		<spring-boot-starter-log4j.version>1.3.8.RELEASE</spring-boot-starter-log4j.version>
		<druid-spring-boot-starter.version>1.1.10</druid-spring-boot-starter.version>
		<xstream.version>1.4.9</xstream.version>
		<commons-beanutils.version>1.9.3</commons-beanutils.version>
		<dubbo-spring-boot-starter.version>2.0.0</dubbo-spring-boot-starter.version>
		<dubbo.version>2.6.2</dubbo.version>
		<javassist.version>3.20.0-GA</javassist.version>
		<curator-framework.version>4.0.1</curator-framework.version>
		<curator-recipes.version>4.0.1</curator-recipes.version>
		<fastjson.version>1.2.48</fastjson.version>
		<commons-pool2.version>2.6.1</commons-pool2.version>
		<zookeeper.version>3.5.0-alpha</zookeeper.version>
		<javax.servlet-api.version>4.0.1</javax.servlet-api.version>
	</properties>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-starter-web</artifactId>
				<version>${spring-boot-starter-parent.version}</version>
			</dependency>
			<dependency>
				<groupId>org.mybatis.spring.boot</groupId>
				<artifactId>mybatis-spring-boot-starter</artifactId>
				<version>${mybatis-spring-boot-starter.version}</version>
			</dependency>
			<dependency>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-starter-log4j</artifactId>
				<version>${spring-boot-starter-log4j.version}</version>
			</dependency>
			<dependency>
				<groupId>com.alibaba</groupId>
				<artifactId>druid-spring-boot-starter</artifactId>
				<version>${druid-spring-boot-starter.version}</version>
			</dependency>
			<dependency>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-configuration-processor</artifactId>
				<version>${spring-boot-starter-parent.version}</version>
				<optional>true</optional>
			</dependency>
			<dependency>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-actuator</artifactId>
				<version>${spring-boot-starter-parent.version}</version>
			</dependency>
			<dependency>
				<groupId>com.alibaba.boot</groupId>
				<artifactId>dubbo-spring-boot-starter</artifactId>
				<version>${dubbo-spring-boot-starter.version}</version>
			</dependency>
			<dependency>
				<groupId>com.alibaba</groupId>
				<artifactId>dubbo</artifactId>
				<version>${dubbo.version}</version>
			</dependency>
			<dependency>
				<groupId>com.thoughtworks.xstream</groupId>
				<artifactId>xstream</artifactId>
				<version>${xstream.version}</version>
			</dependency>
			<dependency>
				<groupId>commons-beanutils</groupId>
				<artifactId>commons-beanutils</artifactId>
				<version>${commons-beanutils.version}</version>
			</dependency>
			<dependency>
				<groupId>org.javassist</groupId>
				<artifactId>javassist</artifactId>
				<version>${javassist.version}</version>
			</dependency>
			<dependency>
				<groupId>org.apache.curator</groupId>
				<artifactId>curator-framework</artifactId>
				<version>${curator-framework.version}</version>
			</dependency>
			<dependency>
				<groupId>org.apache.curator</groupId>
				<artifactId>curator-recipes</artifactId>
				<version>${curator-recipes.version}</version>
			</dependency>
			<dependency>
				<groupId>com.alibaba</groupId>
				<artifactId>fastjson</artifactId>
				<version>${fastjson.version}</version>
			</dependency>
			<dependency>
				<groupId>org.apache.commons</groupId>
				<artifactId>commons-pool2</artifactId>
				<version>${commons-pool2.version}</version>
			</dependency>
			<dependency>
				<groupId>org.apache.zookeeper</groupId>
				<artifactId>zookeeper</artifactId>
				<version>${zookeeper.version}</version>
			</dependency>
			<dependency>
				<groupId>javax.servlet</groupId>
				<artifactId>javax.servlet-api</artifactId>
				<version>${javax.servlet-api.version}</version>
			</dependency>
		</dependencies>
	</dependencyManagement>
	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-maven-plugin</artifactId>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>

至此,父项目编写完毕。

编写服务接口模块

鼠标选中springboot-dubbo项目,单击鼠标右键,选择创建一个maven module
图4.创建服务方模块
点击next按钮,进入下一步
图5.填写服务接口项目名
填写项目模块名称为springboot-dubbo-service,点击next
图6.配置接口模块信息
这里Group Id 与父项目保持一致,Packaging 选择 jar,因为服务接口不涉及web相关,因此将打包方式设为jar即可。填写好信息后点击Finish即可完成接口模块的创建。

我们在接口项目中定义一个User实体类

package com.gavin.dubbo.pojo;

import java.io.Serializable;
import java.util.Date;

public class User implements Serializable{

	private Integer userId;

	private String userName;

	private String password;

	private Date createTime;

	public Integer getUserId() {
		return userId;
	}

	public void setUserId(Integer userId) {
		this.userId = userId;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public Date getCreateTime() {
		return createTime;
	}

	public void setCreateTime(Date createTime) {
		this.createTime = createTime;
	}

}

注意,被dubbo所使用的实体类必须要实现序列化接口,不然dubbo运行时会报错。

接下来我们创建一个dubbo接口UserDubboService,接口中有两个方法分别用于插入用户和查询用户列表

package com.gavin.dubbo.service;

import java.util.List;

import com.gavin.dubbo.pojo.User;

public interface UserDubboService {
	
	public int insertUser(User user);
	
	public List<User> selectUsers(User user);
	
}

至此,服务接口项目就编写完成了。

PS:在实际开发中,pojo也可以单独创建一个模块,专门用来存放实体类,然后在接口模块中引入pojo模块。

编写服务提供者模块

服务提供者模块,也就是对接口模块的实现。同样的我们在springboot-dubbo中创建一个名称为springboot-dubbo-service-impl 的模块,创建方法和接口模块相同,在此不再赘述,唯一要注意的点是打包类型的选择,服务实现即可以打jar成包发布,也可以打成war包发布

  1. 如果想要部署在tomcatweb容器中运行,则需要打成war包,打包类型选择war
  2. 如果直接以jar包的方式部署,则打包类型选择jar

这里我使用war的方式来进行开发,个人还是比较习惯部署在tomcat中运行,便于修改配置容器参数、启停服务、查看日志等操作。

编写pom文件内容,使用到的依赖如下

	<!-- 打包方式,如想打成jar包,则改为jar -->
	<packaging>war</packaging>


	<dependencies>
		<!-- 引入springboot-dubbo-service接口项目 -->
		<dependency>
			<groupId>com.gavin</groupId>
			<artifactId>springboot-dubbo-service</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<exclusions>
				<!-- 排除自带的logback依赖 -->
				<exclusion>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-starter-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<!-- 启用log4j -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-log4j</artifactId>
		</dependency>
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <!-- 部署时不使用 -->
            <scope>provided</scope>	
        </dependency>
        <dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid-spring-boot-starter</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>com.alibaba.boot</groupId>
			<artifactId>dubbo-spring-boot-starter</artifactId>
			<exclusions>
				<exclusion>
					<artifactId>zookeeper</artifactId>
					<groupId>org.apache.zookeeper</groupId>
				</exclusion>
				<exclusion>
					<groupId>com.alibaba</groupId>
					<artifactId>dubbo</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>dubbo</artifactId>
		</dependency>
		<dependency>
			<groupId>com.thoughtworks.xstream</groupId>
			<artifactId>xstream</artifactId>
		</dependency>
		<dependency>
			<groupId>commons-beanutils</groupId>
			<artifactId>commons-beanutils</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
		<dependency>
			<groupId>com.google.code.gson</groupId>
			<artifactId>gson</artifactId>
		</dependency>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
		</dependency>
		<dependency>
			<groupId>dom4j</groupId>
			<artifactId>dom4j</artifactId>
		</dependency>
		<dependency>
			<groupId>org.javassist</groupId>
			<artifactId>javassist</artifactId>
		</dependency>
		<dependency>
			<groupId>org.apache.curator</groupId>
			<artifactId>curator-framework</artifactId>
		</dependency>
		<dependency>
			<groupId>org.apache.curator</groupId>
			<artifactId>curator-recipes</artifactId>
			<exclusions>
				<exclusion>
					<groupId>org.apache.zookeeper</groupId>
					<artifactId>zookeeper</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.apache.zookeeper</groupId>
			<artifactId>zookeeper</artifactId>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
		</dependency>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-pool2</artifactId>
		</dependency>
	</dependencies>

创建spring配置文件application.yml,内容如下,其中数据库使用的是mysql,数据库连接池使用的是阿里druid

spring:
  profiles:
    active: dev
    

---
#开发环境

#服务器相关配置
server:
  port: 8080
  tomcat:
    uri-encoding: UTF-8

#mybatis配置
mybatis:
  mapper-locations: classpath:mapper/*.xml    
#spring配置
spring:
  profiles: dev
  http:
    encoding:
      charset: UTF-8
      enabled: true
      force: true
  aop:
    auto: true
  #数据源
  datasource:
    druid:
      filters: mergeStat,wall
      initial-size: 5
      max-active: 50
      min-idle: 5
      max-wait: 6000
      validation-query: SELECT 'x'
      test-on-borrow: true
      test-on-return: true
      test-while-idle: true
      time-between-eviction-runs-millis: 60000
      min-evictable-idle-time-millis: 300000
      remove-abandoned: true
      remove-abandoned-timeout: 1800
      log-abandoned: true
      web-stat-filter:
        enabled: true
        url-pattern: /*
        exclusions: '*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*'
      stat-view-servlet:
        enabled: true
        url-pattern: /druid/*
        reset-enable: false
        login-username: admin
        login-password: 123456
      dubbo:
        url: jdbc:mysql://localhost:3306/dubbo?characterEncoding=utf8&serverTimezone=CTT
        username: root
        password: root
        driverClassName: com.mysql.cj.jdbc.Driver

#dubbo配置        
dubbo: 
  registry: 
    address: zookeeper://localhost:2181
  protocol:
    address: localhost
    port: 38080

创建log4j.properties文件,这里我是用的是log4j框架,使用logback也可,可以根据自己需要修改,配置内容如下

#set log levels
log4j.rootLogger = INFO , console , debug , error

#console
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern = %-d{yyyy-MM-dd HH\:mm\:ss} [%p]-[%c] [%l] %m%n
 
#log file
log4j.appender.debug = org.apache.log4j.DailyRollingFileAppender
log4j.appender.debug.File = ${user.home}/app/logs/springboot-dubbo-service.log
log4j.appender.debug.Append = true
log4j.appender.debug.Threshold = debug
log4j.appender.debug.layout = org.apache.log4j.PatternLayout
log4j.appender.debug.layout.ConversionPattern = %-d{yyyy-MM-dd HH\:mm\:ss} [%p]-[%c] [%l] %m%n
 
#exception
log4j.appender.error = org.apache.log4j.DailyRollingFileAppender
log4j.appender.error.File = ${user.home}/app/logs/springboot-dubbo-service_error.log
log4j.appender.error.Append = true
log4j.appender.error.Threshold = ERROR
log4j.appender.error.layout = org.apache.log4j.PatternLayout
log4j.appender.error.layout.ConversionPattern = %-d{yyyy-MM-dd HH\:mm\:ss} [%p]-[%c] [%l] %m%n
 
 
#stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %l %c%n%p: %m%n
ˆ†
#jdbc
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Connection = DEBUG
log4j.logger.java.sql.Statement = DEBUG
log4j.logger.java.sql.PreparedStatement = DEBUG
log4j.logger.java.sql.ResultSet = DEBUG

#jdbcTemplate
log4j.logger.com.crtis.ktwechat.mapper=DEBUG
log4j.logger.org.springframework.jdbc.core.JdbcTemplate=debug
log4j.logger.org.springframework.jdbc.core.StatementCreatorUtils=Trace

接下来编写springboot项目启动类DubboServiceApplication以及ServletInitializer,其中后者用于tomcat容器中启动springboot项目

package com.gavin.dubbo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import com.alibaba.dubbo.config.spring.context.annotation.DubboComponentScan;

@SpringBootApplication
@DubboComponentScan("com.gavin.dubbo.service.impl")	// 扫描注册dubbo服务
public class DubboServiceApplication {
	public static void main(String[] args) {
		SpringApplication.run(DubboServiceApplication.class, args);
	}
}

package com.gavin.dubbo;

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

/**
 * @title 用于tomcat启动springboot程序
 * @author gavin
 * @date 2019年8月27日
 */
public class ServletInitializer extends SpringBootServletInitializer {
	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
		return application.sources(DubboServiceApplication.class);
	}
}

创建数据源,代码如下

package com.gavin.dubbo.cfg.db;

import java.sql.SQLException;

import javax.sql.DataSource;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;


/**
 * @title 创建数据源
 * @author gavin
 * @date 2019年8月27日
 */
@Configuration
@MapperScan(basePackages= {"com.gavin.dubbo.mapper"})	// 扫描mapper接口
public class DruidConfiguration {
	
	@ConfigurationProperties(prefix="spring.datasource.druid.dubbo")
	@Bean(name="dubbo")
	public DataSource dataSource() throws SQLException{
		return DruidDataSourceBuilder.create().build();
	}
}

编写dubbo服务配置类DubboConfiguration,代码如下,代码注释中有各项配置的详细说明

package com.gavin.dubbo.cfg.dubbo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.RegistryConfig;

/**
 * @title dubbo服务配置
 * @author gavin
 * @date 2019年8月27日
 */
@Configuration
public class DubboConfiguration {
	
	// 注册中心地址
	@Value("${dubbo.registry.address}")
	private String registryAddress;
	
	// dubbo服务地址
	@Value("${dubbo.protocol.address}")
	private String protocolAddress;
	
	// dubbo服务端口
	@Value("${dubbo.protocol.port}")
	private int protocolPort;
	
	
	/**
	 * @title 服务配置
	 * @author gavin
	 * @date 2019年8月27日
	 * @return
	 */
	@Bean
	public ApplicationConfig applicationConfig() {
		ApplicationConfig applicationConfig = new ApplicationConfig();
		// 指定一个服务名
		applicationConfig.setName("springboot-dubbo-service");
		// 设置Qos端口并且关闭,防止运行过程报错
		applicationConfig.setQosEnable(false);
		applicationConfig.setQosAcceptForeignIp(false);
		applicationConfig.setQosPort(22222);
		return applicationConfig;
	}
	
	/**
	 * @title 注册中心配置
	 * @author gavin
	 * @date 2019年8月27日
	 * @return
	 */
	@Bean
	public RegistryConfig registryConfig() {
		RegistryConfig  registryConfig = new RegistryConfig();
		registryConfig.setAddress(this.registryAddress);
		// 指定连接zookeeper的客户端
		registryConfig.setClient("curator");
		// 设置超时时间
		registryConfig.setTimeout(30000);
		return registryConfig;
	}
	
	/**
	 * @title 协议配置
	 * @author gavin
	 * @date 2019年8月30日
	 * @return
	 */
	@Bean
	public ProtocolConfig protocalConfig() {
		ProtocolConfig protocolConfig = new ProtocolConfig();
		// 指定协议为dubbo
		protocolConfig.setName("dubbo");
		// 指定dubbo服务地址
		protocolConfig.setHost(this.protocolAddress);
		// 指定dubbo服务端口
		protocolConfig.setPort(this.protocolPort);
		return protocolConfig;
	}

	public String getRegistryAddress() {
		return registryAddress;
	}

	public void setRegistryAddress(String registryAddress) {
		this.registryAddress = registryAddress;
	}

	public String getProtocolAddress() {
		return protocolAddress;
	}

	public void setProtocolAddress(String protocolAddress) {
		this.protocolAddress = protocolAddress;
	}

	public int getProtocolPort() {
		return protocolPort;
	}

	public void setProtocolPort(int protocolPort) {
		this.protocolPort = protocolPort;
	}
}

再创建dubbo服务销毁类DubboPreDestory,用于解决dubbo服务部署在tomcat中,tomcat自动重启时端口占用错误

package com.gavin.dubbo.cfg.dubbo;

import javax.annotation.PreDestroy;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

import com.alibaba.dubbo.registry.dubbo.DubboRegistryFactory;
import com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol;

/**
 * @title dubbo服务销毁配置,用于解决dubbo服务部署在tomcat中,tomcat自动重启时端口占用错误
 * @author gavin
 * @date 2019年8月27日
 */
@Component
public class DubboPreDestory {
	
	private Logger logger = Logger.getLogger(this.getClass());
	
	@PreDestroy
	public void destroy() {
		logger.info("dubbo实例销毁中....");
		DubboRegistryFactory.destroyAll();
		DubboProtocol.getDubboProtocol().destroy();
		logger.info("dubbo服务销毁完成!");
	}
}

创建UserMapper接口,代码如下

package com.gavin.dubbo.mapper;

import java.util.List;

import com.gavin.dubbo.pojo.User;

public interface UserMapper {
	
	public int insert(User user);
	
	public List<User> select(User user);
}

创建UserMapper.xml文件,内容如下

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gavin.dubbo.mapper.UserMapper">
	<insert id="insert" parameterType="com.gavin.dubbo.pojo.User">
		INSERT INTO user 
		(
			userName
			,password
			,createTime
		)
		VALUES
		(
			#{userName}
			,#{password}
			,now()
		)
	</insert>
	
	<select id="select" parameterType="com.gavin.dubbo.pojo.User" resultType="com.gavin.dubbo.pojo.User">
		SELECT userId
		,userName
		,createTime
		FROM user
		<trim prefix="where" prefixOverrides="and|or|AND|OR">
			<if test="userName != null and userName != '' ">
				and userName = #{userName}
			</if>
		</trim>
	</select>
</mapper>

接下来创建dubbo服务实现类,实现UserDubboService

package com.gavin.dubbo.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.dubbo.config.annotation.Service;
import com.gavin.dubbo.mapper.UserMapper;
import com.gavin.dubbo.pojo.User;
import com.gavin.dubbo.service.UserDubboService;

@Component
@Service
public class UserDubboServiceImpl implements UserDubboService{
	@Autowired
	private UserMapper userMapper;
	
	@Override
	public int insertUser(User user) {
		return userMapper.insert(user);
	}

	@Override
	public List<User> selectUsers(User user) {
		return userMapper.select(user);
	}	
}

注意: dubbo服务实现中的@Service注解是com.alibaba.dubbo.config.annotation.Service,不要引成spring的。

至此,服务提供者项目就编写完成了。

编写消费者模块

springboot-dubbo中创建一个名称为springboot-dubbo-customer 的模块,创建完成后开始编写代码。
首先引入pom依赖,需要注意的是,消费者也需要引入springboot-dubbo-service接口模块

<dependencies>
		<!-- 引入springboot-dubbo-service接口项目 -->
		<dependency>
			<groupId>com.gavin</groupId>
			<artifactId>springboot-dubbo-service</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>com.alibaba.boot</groupId>
			<artifactId>dubbo-spring-boot-starter</artifactId>
			<exclusions>
				<exclusion>
					<artifactId>zookeeper</artifactId>
					<groupId>org.apache.zookeeper</groupId>
				</exclusion>
				<exclusion>
					<groupId>com.alibaba</groupId>
					<artifactId>dubbo</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>dubbo</artifactId>
		</dependency>
		<dependency>
			<groupId>org.javassist</groupId>
			<artifactId>javassist</artifactId>
		</dependency>
		<dependency>
			<groupId>org.apache.curator</groupId>
			<artifactId>curator-framework</artifactId>
		</dependency>
		<dependency>
			<groupId>org.apache.curator</groupId>
			<artifactId>curator-recipes</artifactId>
			<exclusions>
				<exclusion>
					<groupId>org.apache.zookeeper</groupId>
					<artifactId>zookeeper</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.apache.zookeeper</groupId>
			<artifactId>zookeeper</artifactId>
		</dependency>
	</dependencies>

接着创建spring配置文件 application.yml ,内容如下

spring:
  profiles:
    active: dev
    

---
#开发环境

#服务器相关配置
server:
  port: 8081
  tomcat:
    uri-encoding: UTF-8
    
#dubbo配置    
dubbo:
  registry:
    address: zookeeper://localhost:2181

dubbo消费者配置类代码

package com.gavin.customer.cfg;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ConsumerConfig;
import com.alibaba.dubbo.config.RegistryConfig;

@Configuration
public class DubboConfiguration {
	
	// 注册中心地址
	@Value("${dubbo.registry.address}")
	private String registryAddress;
	
	/**
	 * @title 服务配置
	 * @author gavin
	 * @date 2019年8月30日
	 * @return
	 */
	@Bean
	public ApplicationConfig applicationConfig() {
		ApplicationConfig applicationConfig = new ApplicationConfig();
		applicationConfig.setName("springboot-dubbo-service");
		applicationConfig.setQosAcceptForeignIp(false);
		applicationConfig.setQosEnable(false);
		applicationConfig.setQosPort(55555);
		return applicationConfig;
	}
	
	/**
	 * @title 消费者配置
	 * @author gavin
	 * @date 2019年8月30日
	 * @return
	 */
	@Bean
	public ConsumerConfig consumerConfig() {
		ConsumerConfig  consumerConfig = new ConsumerConfig();
		// 设置超时时间
		consumerConfig.setTimeout(15000);
		// 设置启动时不监听provider的状态
		consumerConfig.setCheck(false);
		return consumerConfig;
	}
	
	/**
	 * @title 注册中心配置
	 * @author gavin
	 * @date 2019年8月30日
	 * @return
	 */
	@Bean
	public RegistryConfig registryConfig() {
		RegistryConfig registryConfig = new RegistryConfig();
		registryConfig.setAddress(this.registryAddress);
		registryConfig.setClient("curator");
		registryConfig.setTimeout(15000);
		return registryConfig;
	}

	public String getRegistryAddress() {
		return registryAddress;
	}

	public void setRegistryAddress(String registryAddress) {
		this.registryAddress = registryAddress;
	}
}

接下来创建UserService接口,代码如下

package com.gavin.customer.service;

import java.util.List;

import com.gavin.dubbo.pojo.User;

public interface UserService {

	int insert(User user) throws Exception;

	List<User> select(User user) throws Exception;

}

编写UserService实现类

package com.gavin.customer.service.impl;

import java.util.List;

import org.springframework.stereotype.Service;

import com.alibaba.dubbo.config.annotation.Reference;
import com.gavin.customer.service.UserService;
import com.gavin.dubbo.pojo.User;
import com.gavin.dubbo.service.UserDubboService;

@Service
public class UserServiceImpl implements UserService{
	
	@Reference
	private UserDubboService userDubboService;
	
	@Override
	public int insert(User user) throws Exception {
		return userDubboService.insertUser(user);
	}

	@Override
	public List<User> select(User user) throws Exception {
		return userDubboService.selectUsers(user);
	}

}

注意:

  1. @Service 注解是spring框架的,而不是dubbo
  2. @Reference是dubbo注解,用来注入dubbo服务

最后创建UserController,在里面使用UserService

package com.gavin.customer.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import com.gavin.customer.service.UserService;
import com.gavin.dubbo.pojo.User;

@RestController
public class UserController {
	
	@Autowired
	private UserService userService;
	
	@PostMapping("user/add")
	public int addUser(User user) {
		try {
			return this.userService.insert(user);
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}
	}
	
	@GetMapping("user/list")
	public List<User> listUser(User user){
		try {
			return this.userService.select(user);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
}

UserController中申明了两个接口

  1. user/add,用于添加单个用户
  2. user/list ,查询库中所有用户

至此,消费者项目编写完毕。

测试

接下来就是测试消费者中的接口能否正确调用dubbo服务,我们依次启动

  1. zookeeper
  2. dubbo服务方(springboot-dubbo-service-impl)
  3. 消费者(springboot-dubbo-customer)

启动完成后,使用postman测试user/add接口,如下图所示,点击send按钮
图7.添加用户接口
图8.数据库新增记录
接口返回值为1,且数据库中有一条新的记录,说明接口调用成功。

调用user/list接口,结果如下图。
图9.查询所有用户接口
测试完毕!

猜你喜欢

转载自blog.csdn.net/u012693016/article/details/100163501