本文介绍本人通过springboot搭建dubbo服务的项目实例,此服务为dubbo+springboot+mybatis项目,使用到swagger-ui及mybatis-generator功能。
数据层实现,逆向工程使用部分描述简写,详情参考https://www.jianshu.com/p/6bcaf86e84f0
主体结构如图:
此服务为父子级maven项目,主体demoDubbo,内嵌:
common(使用mybatis-generator生成实体及mapper,放置实体类);
provider(提供者,放置mapper,提供调用数据层的方法及service接口实现);
api(放置provider的接口,起到关联provider和consumer的作用);
consumer(消费者,存放controller)
0.前期准备:
本地安装zookeeper(本人使用虚拟机安装的zookeeper,具体自行百度或参考下方链接):
window安装:https://www.jianshu.com/p/0dbbb97d7e21
linux安装:https://www.jianshu.com/p/cd6c2110aa71数据库执行下面语句,创建d_user表
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for d_user
-- ----------------------------
DROP TABLE IF EXISTS `d_user`;
CREATE TABLE `d_user` (
`id` int(0) NOT NULL,
`name` varchar(25) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of d_user
-- ----------------------------
INSERT INTO `d_user` VALUES (1001, '雨欣', '100011');
INSERT INTO `d_user` VALUES (1002, '雨欣:324:324:324', '100012');
SET FOREIGN_KEY_CHECKS = 1;
如下:
-
创建maven父级项目
依次点击idea: File>new>Project新建项目,选择maven,next后创建项目名dubbo新窗口打开,如下:
父级项目删除src,test文件夹。
1.创建common子项目
右键父项目名,new>module如下
选择maven项目,勾选如下确定,下一步(可不用勾选webapp)
创建项目名common,依次下一步创建common子项目,删除pom中的
javax.persistence
persistence-api
1.0
compile
common
org.mybatis.generator
mybatis-generator-maven-plugin
1.3.2
src/main/resources/generator/genteratorCongfig.xml
true
true
mysql
mysql-connector-java
8.0.16
tk.mybatis
mapper
3.4.2
删除main文件夹内的webapps文件夹,创建java,resources文件夹如下:
!!若文件夹属性不对(后续子项目都会涉及),可点击File>project Structure修改文件属性,如下
在resources下创建文件夹generator,并创建逆向工程文件配置如下:
其中config.properties文件内容如下,注意修改你的数据库配置,自动生成的mapper,dao子文件夹名称,以及生成路径
jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowMultiQueries=true
jdbc.user=root
jdbc.password=root
#模块名
moduleName=d_user
#表名
tableName=d_user
#默认路径
modelPath=com.example.demo1
其中genteratorCongfig.xml 文件内容如下
双击生成mapper;dao;model如下
implements Serializable 添加序列化实体对象如下:
Dubbo服务间的调用需要实体序列化,不然调用会报错:
org.apache.dubbo.remoting.RemotingException: Failed to send response: Response [id=2, version=2.0.2, status=20, event=false, error=null, result=AppResponse [value=com.example.common.model.entity.d_user.DUser@3f3ffb93, exception=null]], cause: java.lang.IllegalStateException: Serialized class com.example.common.model.entity.d_user.DUser must implement java.io.Serializable
java.lang.IllegalStateException: Serialized class com.example.common.model.entity.d_user.DUser must implement java.io.Serializable
生成如下:
2.创建provider子项目
首先同创建common子项目,创建provider子项目
修改pom文件如下:
4.0.0
org.example
provider
1.0-SNAPSHOT
war
provider Maven Webapp
http://www.example.com
org.springframework.boot
spring-boot-starter-parent
2.0.4.RELEASE
UTF-8
1.7
1.7
2.7.8
2.53.0
org.example
common
1.0-SNAPSHOT
compile
org.springframework.boot
spring-boot-starter-web
mysql
mysql-connector-java
8.0.16
runtime
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.1.1
org.mybatis
mybatis
3.4.6
compile
junit
junit
test
org.springframework
spring-test
test
org.springframework.boot
spring-boot-test
test
tk.mybatis
mapper
4.1.5
org.apache.dubbo
dubbo-spring-boot-starter
${dubbo.version}
org.apache.dubbo
dubbo-dependencies-zookeeper
${dubbo.version}
pom
org.slf4j
slf4j-log4j12
org.seleniumhq.selenium
selenium-server-standalone
${selenium.version}
provider
src/main/java
**/*.properties
**/*.xml
**/*.yml
false
src/main/resources
**/*.properties
**/*.xml
**/*.yml
false
添加并修改yml文件如下:(注意zookeeper配置)
spring:
application:
name: this-provider
# profiles:
# active: test
datasource:
#MySQL数据库支持配置
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowMultiQueries=true
username: root
password: root
type: com.zaxxer.hikari.HikariDataSource
hikari:
minimum-idle: 5
maximum-pool-size: 100
idle-timeout: 600000
pool-name: OrderHikariCP
max-lifetime: 1800000
connection-timeout: 60000
connection-test-query: SELECT 1
server:
port: 8081
mybatis:
config-location: classpath:mybatis-config.xml
type-aliases-package: org.example.provider.dao.**
mapper-locations: classpath:mapper/*/*.xml
dataType: 0
dubbo:
# Base packages to scan Dubbo Component: @org.apache.dubbo.config.annotation.Service
scan:
# 扫描 DubboService 注解
base-packages: org.example.provider.**
## ApplicationConfig Bean
application:
# 服务id
id: this-provider
# 服务名称
name: this-provider
# QOS服务:通过一些命令来返回响应的结果,达到动态控制的目的
qos-port: 22212
qos-enable: true
## ProtocolConfig Bea n
protocol:
# 底层通讯协议,在多协议时使用?
id: dubbo
name: dubbo
port: 10345
status: server
payload: 83886080
## RegistryConfig Bean
registry:
id: this-provider
# 使用的zookeeper 地址
address: 10.1.31.199:2181
protocol: zookeeper
provider:
# 当 ProtocolConfig 和 ServiceConfig 某属性没有配置时,采用此缺省值,可选
timeout: 300000
payload: 83886080
consumer:
# 当 ReferenceConfig 某属性没有配置时,采用此缺省值,可选
timeout: 300000
check: false
添加并修改mybatis-config文件如下:
再将common的dao层及mapper文件夹移至provider中(pom内引入common依赖后,修改引入路径),
整体结构如下:
在mapper.xml文件内编写sql查询语句,并在dao内,添加该方法:
id,name,ip
DUser selectAllById(@Param("id") Integer id);
创建service文件夹,预留存放Service接口实现;
创建application启动类文件ProviderApplication如下:
package com.example.provider;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import tk.mybatis.spring.annotation.MapperScan;
/**
* 订单provider启动类
*
* @author ZSC-DXHY
*/
@SpringBootApplication
@ComponentScan(value = {"com.example"})
@MapperScan(basePackages = "com.example.provider.dao.**")
@EnableConfigurationProperties
@EnableDubbo
public class ProviderApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(ProviderApplication.class);
}
public static void main(String[] args) {
new SpringApplicationBuilder(ProviderApplication.class)
.run(args);
}
}
创建test测试项,测试数据查询实现如下:
在src下创建文件夹test,修改文件夹属性为Tests,在目录下创建providerApplicationTests测试类代码如下:
package com.example.demomybatis;
import com.example.provider.ProviderApplication;
import com.example.provider.dao.d_user.DUserMapper;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.junit.runner.RunWith;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ProviderApplication.class)
public class providerApplicationTests {
@Autowired
DUserMapper dUserMapper;
@Test
public void contextLoads() {
System.out.println("here==="+dUserMapper.selectAllById(1001).getName());
}
}
启动测试文件,查询成功:
整体结构如下:
3.创建api子项目
首先同创建common子项目,创建api子项目,并创建文件夹java/com/example/api,添加service接口层,如下:
在api的service内添加接口方法DUserService;
在provider的service创建impl文件夹,并在内添加接口方法的实现类DUserServiceImpl实现DUserService接口。
代码如下:
package com.example.api.service;
import com.example.common.model.entity.d_user.DUser;
public interface DUserService {
DUser selectById(Integer id);
}
package com.example.provider.service.impl;
import com.example.api.service.DUserService;
import com.example.common.model.entity.d_user.DUser;
import com.example.provider.dao.d_user.DUserMapper;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
@DubboService
public class DUserServiceImpl implements DUserService {
@Autowired
DUserMapper dUserMapper;
@Override
public DUser selectById(Integer id){
return dUserMapper.selectAllById(id);
}
}
注意:
1dubbo的service注解使用DubboService
2为api项目的pom添加common依赖,为provider项目添加api依赖
3.创建consumer子项目
首先同创建common子项目,创建consumer子项目,并创建目录结构;
consumer使用swagger-ui接口,大致创建可仿common及provider子项目实现,具体结构如下:
其中pom文件内容如下:
4.0.0
org.example
consumer
1.0-SNAPSHOT
war
consumer Maven Webapp
http://www.example.com
org.springframework.boot
spring-boot-starter-parent
2.0.4.RELEASE
UTF-8
1.7
1.7
2.7.8
2.53.0
org.springframework.boot
spring-boot-starter-web
org.apache.dubbo
dubbo-spring-boot-starter
${dubbo.version}
org.apache.dubbo
dubbo-dependencies-zookeeper
${dubbo.version}
pom
org.slf4j
slf4j-log4j12
org.seleniumhq.selenium
selenium-server-standalone
${selenium.version}
io.springfox
springfox-swagger2
2.6.1
io.springfox
springfox-swagger-ui
2.6.1
com.spring4all
spring-boot-starter-swagger
1.5.1.RELEASE
com.alibaba
fastjson
1.2.47
org.example
api
1.0-SNAPSHOT
compile
consumer
application.yml文件如下:
spring:
application:
name: consumer
profiles:
active: test
server:
port: 8082
servlet:
context-path: /
max-http-header-size: 4048576
dubbo:
# Base packages to scan Dubbo Component: @org.apache.dubbo.config.annotation.Service
scan:
# 扫描 DubboService 注解
base-packages: org.example.consmuer.**
## ApplicationConfig Bean
application:
# 服务id
id: this-consumer
# 服务名称
name: this-consumer
# QOS服务:通过一些命令来返回响应的结果,达到动态控制的目的
qos-port: 22213
qos-enable: true
## RegistryConfig Bean
registry:
id: this-provider
# 使用的zookeeper 地址
address: 10.1.31.199:2181
protocol: zookeeper
provider:
# 当 ProtocolConfig 和 ServiceConfig 某属性没有配置时,采用此缺省值,可选
timeout: 300000
consumer:
# 当 ReferenceConfig 某属性没有配置时,采用此缺省值,可选
timeout: 300000
check: false
swagger2Config文件如下:
package com.example.config;
import com.google.common.base.Predicates;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class Swagger2Config {
@Bean
public Docket createRestApi(){
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.any())// 对所有api进行监控
.paths(Predicates.not(PathSelectors.regex("/error.*")))//错误路径不监控
.paths(PathSelectors.regex("/.*"))// 对根下所有路径进行监控
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("测试swagger-dubbo接口")
.description("dxhy-api文档")
// .termsOfServiceUrl("/")
.version("1.0")
.build();
}
}
创建的controller实现类文件如下:
package com.example.consumer.openapi;
import com.example.api.service.DUserService;
import com.example.common.model.entity.d_user.DUser;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.*;
@Api(value = "demo",description = "API for demo",protocols = "http")
@RestController
@RequestMapping("/demo")
public class testController {
@DubboReference
private DUserService duserService;
@ApiOperation(value="",notes="")
@GetMapping("/getById")
public DUser demoForController(@RequestParam(value="id",defaultValue ="1001" )@ApiParam(value="uersId")String id){
DUser user =new DUser();
if(StringUtils.isNotEmpty(id)){
user = duserService.selectById(Integer.valueOf(id));
}
return user;
}
}
注意:duserService接口引入api的,注解使用:@DubboReference
启动项文件ConsumerStarter 内容为:
package com.example.consumer;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* 订单服务启动类
*
* @author ZSC-DXHY
*/
@SpringBootApplication
@ComponentScan(value = {"com.example"})
@EnableDubbo
@EnableSwagger2
public class ConsumerStarter extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(ConsumerStarter.class);
}
public static void main(String[] args) {
new SpringApplicationBuilder(ConsumerStarter.class)
.run(args);
}
}
至此项目创建完毕。
5测试项目功能实现
先启动provider服务;
再启动consumer服务;
浏览器访问swagger-ui链接如下:
http://localhost:8082/swagger-ui.html#!/test-controller/demoForControllerUsingGET
整体实现成功~