记录一次springboot
整合dubbo
的过程,本文代码 github 地址
https://github.com/liaozq0426/springboot-dubbo.git
文章目录
- 项目结构说明
- 编写父项目
- 编写服务接口模块
- 编写服务提供者模块
- 编写消费者模块
- 测试
项目结构说明
项目结构如下图所示
springboot-dubbo
是一个maven的多模块项目,各个模块的作用如下
-
springboot-dubbo-service
模块为dubbo
服务接口项目,之所以将接口单独创建一个项目,是因为dubbo
接口既需要被dubbo
服务实现类实现,也需要被消费者引用,也就是说dubbo
接口项目会被多个项目使用。 -
springboot-dubbo-service-impl
模块为dubbo
服务的实现,它所有的service实现类
都实现了springboot-dubbo-service
中的接口 -
springboot-dubbo-customer
模块为消费者项目,在实际开发中,dubbo
往往会采用分布式的方式部署,即服务提供者和消费者部署在不同的服务器,消费者还可能有多个,以实现负载均衡。
编写父项目
创建一个simple
类型的maven
项目,勾选下图红色框中的选项,点击next
填写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
点击next
按钮,进入下一步
填写项目模块名称为springboot-dubbo-service
,点击next
这里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
包发布
- 如果想要部署在
tomcat
等web
容器中运行,则需要打成war
包,打包类型选择war
- 如果直接以
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);
}
}
注意:
- @Service 注解是spring框架的,而不是dubbo
- @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中申明了两个接口
- user/add,用于添加单个用户
- user/list ,查询库中所有用户
至此,消费者项目编写完毕。
测试
接下来就是测试消费者中的接口能否正确调用dubbo服务,我们依次启动
- zookeeper
- dubbo服务方(springboot-dubbo-service-impl)
- 消费者(springboot-dubbo-customer)
启动完成后,使用postman测试user/add接口,如下图所示,点击send按钮
接口返回值为1,且数据库中有一条新的记录,说明接口调用成功。调用user/list接口,结果如下图。
测试完毕!